Merge "[SettingsProvider] lint checks for non-user getter calls from system server"
diff --git a/Android.bp b/Android.bp
index 62dce7f..3afd6ec 100644
--- a/Android.bp
+++ b/Android.bp
@@ -101,6 +101,7 @@
         // AIDL sources from external directories
         ":android.hardware.security.keymint-V1-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
+        ":android.hardware.tv.tuner-V1-java-source",
         ":android.security.apc-java-source",
         ":android.security.authorization-java-source",
         ":android.security.legacykeystore-java-source",
@@ -250,8 +251,6 @@
         "android.hardware.thermal-V1.1-java",
         "android.hardware.thermal-V2.0-java",
         "android.hardware.tv.input-V1.0-java-constants",
-        "android.hardware.tv.tuner-V1.0-java-constants",
-        "android.hardware.tv.tuner-V1.1-java-constants",
         "android.hardware.usb-V1.0-java-constants",
         "android.hardware.usb-V1.1-java-constants",
         "android.hardware.usb-V1.2-java-constants",
@@ -331,6 +330,7 @@
     ],
     sdk_version: "core_platform",
     static_libs: [
+        "android.hardware.common.fmq-V1-java",
         // TODO(b/184162091)
         "android.hardware.soundtrigger3-V1-java",
         "bouncycastle-repackaged-unbundled",
@@ -559,8 +559,6 @@
         "android.hardware.thermal-V1.0-java-constants",
         "android.hardware.thermal-V2.0-java",
         "android.hardware.tv.input-V1.0-java-constants",
-        "android.hardware.tv.tuner-V1.0-java-constants",
-        "android.hardware.tv.tuner-V1.1-java-constants",
         "android.hardware.usb-V1.0-java-constants",
         "android.hardware.usb-V1.1-java-constants",
         "android.hardware.usb.gadget-V1.0-java",
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 0e76488..fc70219 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -20,6 +20,7 @@
         "androidx.annotation_annotation",
         "apct-perftests-utils",
         "collector-device-lib-platform",
+        "cts-install-lib-java",
     ],
 
     libs: ["android.test.base"],
diff --git a/apct-tests/perftests/packagemanager/AndroidManifest.xml b/apct-tests/perftests/packagemanager/AndroidManifest.xml
index 4bcd557..3b9431f 100644
--- a/apct-tests/perftests/packagemanager/AndroidManifest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidManifest.xml
@@ -17,6 +17,12 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.perftests.packagemanager">
+    <!-- prevent test application from being obscured because of package visibility -->
+    <queries>
+        <package android:name="com.android.cts.install.lib.testapp.A" />
+        <package android:name="com.android.cts.install.lib.testapp.B" />
+        <package android:name="com.android.cts.install.lib.testapp.C" />
+    </queries>
 
     <permission android:name="com.android.perftests.packagemanager.TestPermission" />
     <uses-permission android:name="com.android.perftests.packagemanager.TestPermission" />
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index 4903510..c9d45a6 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -130,6 +130,10 @@
         <option name="instrumentation-arg" key="perfetto_config_file"
                 value="trace_config.textproto"/>
 
+        <!--
+         PackageInstallerBenchmark will break for 5 minutes time out so it changes to 10 minutes
+          -->
+        <option name="test-timeout" value="600000" />
     </test>
 
 
diff --git a/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
new file mode 100644
index 0000000..3b4f72b
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.HandlerThread;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.LocalIntentSender;
+import com.android.cts.install.lib.TestApp;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PackageInstallerBenchmark {
+    private static final String TAG = "PackageInstallerBenchmark";
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    /**
+     * This rule adopts the Shell process permissions, needed because INSTALL_PACKAGES
+     * and DELETE_PACKAGES are privileged permission.
+     */
+    @Rule
+    public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+            InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+            Manifest.permission.INSTALL_PACKAGES,
+            Manifest.permission.DELETE_PACKAGES);
+
+    private static class SessionCallback extends PackageInstaller.SessionCallback {
+        private final List<Integer> mExpectedSessions;
+        private final CountDownLatch mCountDownLatch;
+        private final boolean mExpectedSuccess;
+
+        SessionCallback(boolean expectedSuccess, List<Integer> expectedSessions,
+                @NonNull CountDownLatch countDownLatch) {
+            mExpectedSuccess = expectedSuccess;
+            mCountDownLatch = countDownLatch;
+            mExpectedSessions = expectedSessions;
+        }
+
+        @Override
+        public void onCreated(int sessionId) { }
+
+        @Override
+        public void onBadgingChanged(int sessionId) { }
+
+        @Override
+        public void onActiveChanged(int sessionId, boolean active) { }
+
+        @Override
+        public void onProgressChanged(int sessionId, float progress) { }
+
+        @Override
+        public void onFinished(int sessionId, boolean success) {
+            if (success == mExpectedSuccess && mExpectedSessions.contains(sessionId)) {
+                mCountDownLatch.countDown();
+            }
+        }
+    }
+
+    private CountDownLatch mCountDownLatch;
+    private SessionCallback mSessionCallback;
+    private PackageInstaller mPackageInstaller;
+    private Install mInstall;
+    private HandlerThread mHandlerThread;
+    private List<PackageInstaller.Session> mExpectedSessions;
+    private List<Integer> mExpectedSessionIds;
+    final LocalIntentSender mLocalIntentSender = new LocalIntentSender();
+    private IntentSender mIntentSender;
+
+    @Before
+    public void setUp() throws IOException {
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mPackageInstaller =  context.getPackageManager().getPackageInstaller();
+        mHandlerThread = new HandlerThread("PackageInstallerBenchmark");
+        mHandlerThread.start();
+
+        mIntentSender = mLocalIntentSender.getIntentSender();
+    }
+
+    @After
+    public void tearDown() throws InterruptedException {
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        context.unregisterReceiver(mLocalIntentSender);
+
+        uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+        mHandlerThread.quitSafely();
+    }
+
+    private List<PackageInstaller.Session> createSinglePackageSessions(
+            BenchmarkState state, boolean expectedResult, TestApp...testApps)
+            throws IOException, InterruptedException {
+        state.pauseTiming();
+        uninstall(false /* stop at fail */, testApps);
+
+        mExpectedSessions = new ArrayList<>();
+        mExpectedSessionIds = new ArrayList<>();
+        for (TestApp testApp : testApps) {
+            mInstall = Install.single(testApp);
+            final int expectedSessionId = mInstall.createSession();
+            PackageInstaller.Session session =
+                    InstallUtils.openPackageInstallerSession(expectedSessionId);
+            Log.d(TAG, "createNewSession: session expectedSessionId = " + expectedSessionId);
+            mExpectedSessions.add(session);
+            mExpectedSessionIds.add(expectedSessionId);
+        }
+
+        mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+        mSessionCallback = new SessionCallback(expectedResult, mExpectedSessionIds,
+                mCountDownLatch);
+        mPackageInstaller.registerSessionCallback(mSessionCallback,
+                mHandlerThread.getThreadHandler());
+        state.resumeTiming();
+        return mExpectedSessions;
+    }
+
+    private List<PackageInstaller.Session> createMultiplePackageSessions(BenchmarkState state,
+            boolean expectedSuccess, List<TestApp[]> testAppsList)
+            throws IOException, InterruptedException {
+        state.pauseTiming();
+        mExpectedSessions = new ArrayList<>();
+        mExpectedSessionIds = new ArrayList<>();
+        for (TestApp[] testApps : testAppsList) {
+            uninstall(false /* stop at fail */, testApps);
+
+            mInstall = Install.multi(testApps);
+            final int expectedSessionId = mInstall.createSession();
+            PackageInstaller.Session session =
+                    InstallUtils.openPackageInstallerSession(expectedSessionId);
+            mExpectedSessions.add(session);
+            mExpectedSessionIds.add(expectedSessionId);
+        }
+
+        mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+        mSessionCallback = new SessionCallback(expectedSuccess, mExpectedSessionIds,
+                mCountDownLatch);
+        mPackageInstaller.registerSessionCallback(mSessionCallback,
+                mHandlerThread.getThreadHandler());
+        state.resumeTiming();
+        return mExpectedSessions;
+    }
+
+    private void uninstall(boolean stopAtFail, TestApp...testApps) throws InterruptedException {
+        String[] packageNames = new String[testApps.length];
+        for (int i = 0; i < testApps.length; i++) {
+            packageNames[i] = testApps[i].getPackageName();
+        }
+        uninstall(stopAtFail, packageNames);
+    }
+
+    private void uninstall(boolean stopAtFail, String...packageNames) throws InterruptedException {
+        LocalIntentSender localIntentSender = new LocalIntentSender();
+        IntentSender intentSender = localIntentSender.getIntentSender();
+        for (String packageName : packageNames) {
+            try {
+                mPackageInstaller.uninstall(packageName, intentSender);
+            } catch (IllegalArgumentException e) {
+                continue;
+            }
+            Intent intent = localIntentSender.getResult();
+            if (stopAtFail) {
+                InstallUtils.assertStatusSuccess(intent);
+            }
+        }
+
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        context.unregisterReceiver(localIntentSender);
+    }
+
+    private void uninstallSession(BenchmarkState state, String...packageNames)
+            throws InterruptedException {
+        state.pauseTiming();
+        uninstall(true /* stop at fail */, packageNames);
+        mPackageInstaller.unregisterSessionCallback(mSessionCallback);
+        state.resumeTiming();
+    }
+
+    @Test(timeout = 600_000L)
+    public void commit_aSingleApkSession_untilFinishBenchmark() throws Exception {
+        uninstall(false /* stop at fail */, TestApp.A);
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            List<PackageInstaller.Session> sessions =
+                    createSinglePackageSessions(state, true, TestApp.A1);
+
+            for (PackageInstaller.Session session : sessions) {
+                session.commit(mIntentSender);
+            }
+            mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+            uninstallSession(state, TestApp.A);
+        }
+    }
+
+    @Test(timeout = 600_000L)
+    public void commit_threeSingleApkSessions_untilFinishBenchmark() throws Exception {
+        uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+                    state, true, TestApp.A1, TestApp.B1, TestApp.C1);
+
+            for (PackageInstaller.Session session : sessions) {
+                session.commit(mIntentSender);
+            }
+            mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+            uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+        }
+    }
+
+    @Test(timeout = 600_000L)
+    public void commit_aMultiplePackagesSession_untilFinishBenchmark()
+            throws IOException, InterruptedException {
+        uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final List<TestApp[]> multiPackageApps = new ArrayList<>();
+        multiPackageApps.add(new TestApp[] {TestApp.A1, TestApp.B1, TestApp.C1});
+
+        while (state.keepRunning()) {
+            List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+                    state, true, multiPackageApps);
+
+            for (PackageInstaller.Session session : sessions) {
+                session.commit(mIntentSender);
+            }
+            mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+            uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+        }
+    }
+
+    @Test(timeout = 600_000L)
+    public void commit_threeMultiplePackageSessions_untilFinishBenchmark()
+            throws Exception {
+        uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final List<TestApp[]> multiPackageApps = new ArrayList<>();
+        multiPackageApps.add(new TestApp[] {TestApp.A1});
+        multiPackageApps.add(new TestApp[] {TestApp.B1});
+        multiPackageApps.add(new TestApp[] {TestApp.C1});
+
+        while (state.keepRunning()) {
+            List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+                    state, true, multiPackageApps);
+
+            for (PackageInstaller.Session session : sessions) {
+                session.commit(mIntentSender);
+            }
+            mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+            uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+        }
+    }
+
+    @Test(timeout = 600_000L)
+    public void commit_aMultipleApksSession_untilFinishBenchmark()
+            throws IOException, InterruptedException {
+        uninstall(false /* stop at fail */, TestApp.A);
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+                    state, true, TestApp.ASplit1);
+
+            for (PackageInstaller.Session session : sessions) {
+                session.commit(mIntentSender);
+            }
+            mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+            uninstallSession(state, TestApp.A);
+        }
+    }
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index 6e4a5a0..7b287d5 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.JobSchedulerImpl;
 import android.app.SystemServiceRegistry;
+import android.app.tare.EconomyManager;
 import android.content.Context;
 import android.os.DeviceIdleManager;
 import android.os.IDeviceIdleController;
@@ -56,5 +57,7 @@
         SystemServiceRegistry.registerContextAwareService(
                 Context.POWER_EXEMPTION_SERVICE, PowerExemptionManager.class,
                 PowerExemptionManager::new);
+        SystemServiceRegistry.registerStaticService(
+                Context.RESOURCE_ECONOMY_SERVICE, EconomyManager.class, EconomyManager::new);
     }
 }
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
new file mode 100644
index 0000000..2f3b36c
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.tare;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * Provides access to the resource economy service.
+ *
+ * @hide
+ */
+@SystemService(Context.RESOURCE_ECONOMY_SERVICE)
+public class EconomyManager {
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 74ed334..829ad27 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -26,6 +26,8 @@
 import static com.android.server.tare.EconomicPolicy.TYPE_REWARD;
 import static com.android.server.tare.EconomicPolicy.eventToString;
 import static com.android.server.tare.EconomicPolicy.getEventType;
+import static com.android.server.tare.TareUtils.appToString;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
 import static com.android.server.tare.TareUtils.narcToString;
 
 import android.annotation.NonNull;
@@ -183,7 +185,7 @@
                 mCurrentOngoingEvents.get(userId, pkgName);
         if (ongoingEvents != null) {
             final long nowElapsed = SystemClock.elapsedRealtime();
-            final long now = System.currentTimeMillis();
+            final long now = getCurrentTimeMillis();
             mTotalDeltaCalculator.reset(ledger, nowElapsed, now);
             ongoingEvents.forEach(mTotalDeltaCalculator);
             balance += mTotalDeltaCalculator.mTotal;
@@ -194,7 +196,12 @@
     @GuardedBy("mLock")
     void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName,
             final int eventId, @Nullable String tag) {
-        final long now = System.currentTimeMillis();
+        if (mIrs.isSystem(userId, pkgName)) {
+            // Events are free for the system. Don't bother recording them.
+            return;
+        }
+
+        final long now = getCurrentTimeMillis();
         final Ledger ledger = getLedgerLocked(userId, pkgName);
 
         final int eventType = getEventType(eventId);
@@ -278,7 +285,7 @@
 
     @GuardedBy("mLock")
     void onDeviceStateChangedLocked() {
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
 
         mCurrentOngoingEvents.forEach((userId, pkgName, ongoingEvents) -> {
@@ -326,7 +333,7 @@
 
     @GuardedBy("mLock")
     void onAppStatesChangedLocked(final int userId, @NonNull ArraySet<String> pkgNames) {
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
 
         for (int i = 0; i < pkgNames.size(); ++i) {
@@ -415,12 +422,15 @@
         }
         ongoingEvent.refCount--;
         if (ongoingEvent.refCount <= 0) {
-            final long startElapsed = ongoingEvent.startTimeElapsed;
-            final long startTime = now - (nowElapsed - startElapsed);
-            final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
-            recordTransactionLocked(userId, pkgName, ledger,
-                    new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
-                    notifyOnAffordabilityChange);
+            if (!mIrs.isSystem(userId, pkgName)) {
+                final long startElapsed = ongoingEvent.startTimeElapsed;
+                final long startTime = now - (nowElapsed - startElapsed);
+                final long actualDelta =
+                        getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
+                recordTransactionLocked(userId, pkgName, ledger,
+                        new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
+                        notifyOnAffordabilityChange);
+            }
             ongoingEvents.delete(eventId, tag);
         }
         if (updateBalanceCheck) {
@@ -446,6 +456,15 @@
     private void recordTransactionLocked(final int userId, @NonNull final String pkgName,
             @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction,
             final boolean notifyOnAffordabilityChange) {
+        if (transaction.delta == 0) {
+            // Skip recording transactions with a delta of 0 to save on space.
+            return;
+        }
+        if (mIrs.isSystem(userId, pkgName)) {
+            Slog.wtfStack(TAG,
+                    "Tried to adjust system balance for " + appToString(userId, pkgName));
+            return;
+        }
         final long maxCirculationAllowed = mIrs.getMaxCirculationLocked();
         final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta;
         if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) {
@@ -477,7 +496,7 @@
             // The earliest transaction won't change until we clean up the ledger, so no point
             // continuing to reschedule an existing cleanup.
             final long cleanupAlarmElapsed = SystemClock.elapsedRealtime() + MAX_TRANSACTION_AGE_MS
-                    - (System.currentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
+                    - (getCurrentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
             mLedgerCleanupAlarmListener.addAlarmLocked(userId, pkgName, cleanupAlarmElapsed);
         }
         // TODO: save changes to disk in a background thread
@@ -509,7 +528,7 @@
     @GuardedBy("mLock")
     void reclaimUnusedAssetsLocked(double percentage) {
         final List<PackageInfo> pkgs = mIrs.getInstalledPackages();
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
         for (int i = 0; i < pkgs.size(); ++i) {
             final int userId = UserHandle.getUserId(pkgs.get(i).applicationInfo.uid);
             final String pkgName = pkgs.get(i).packageName;
@@ -543,11 +562,15 @@
     @GuardedBy("mLock")
     void distributeBasicIncomeLocked(int batteryLevel) {
         List<PackageInfo> pkgs = mIrs.getInstalledPackages();
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
         for (int i = 0; i < pkgs.size(); ++i) {
             final PackageInfo pkgInfo = pkgs.get(i);
             final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid);
             final String pkgName = pkgInfo.packageName;
+            if (mIrs.isSystem(userId, pkgName)) {
+                // No point allocating ARCs to the system. It can do whatever it wants.
+                continue;
+            }
             Ledger ledger = getLedgerLocked(userId, pkgName);
             final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
             final double perc = batteryLevel / 100d;
@@ -578,12 +601,16 @@
         List<PackageInfo> pkgs = packageManager.getInstalledPackagesAsUser(0, userId);
         final long maxBirthright =
                 mIrs.getMaxCirculationLocked() / mIrs.getInstalledPackages().size();
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
 
         for (int i = 0; i < pkgs.size(); ++i) {
             final PackageInfo packageInfo = pkgs.get(i);
             final String pkgName = packageInfo.packageName;
             final Ledger ledger = getLedgerLocked(userId, pkgName);
+            if (mIrs.isSystem(userId, pkgName)) {
+                // No point allocating ARCs to the system. It can do whatever it wants.
+                continue;
+            }
             if (ledger.getCurrentBalance() > 0) {
                 // App already got credits somehow. Move along.
                 Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up");
@@ -609,7 +636,7 @@
         List<PackageInfo> pkgs = mIrs.getInstalledPackages();
         final int numPackages = pkgs.size();
         final long maxBirthright = mIrs.getMaxCirculationLocked() / numPackages;
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
 
         recordTransactionLocked(userId, pkgName, ledger,
                 new Ledger.Transaction(now, now, REGULATION_BIRTHRIGHT, null,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 831c05f..29aa946 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -124,6 +124,11 @@
      */
     boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
 
+    /**
+     * Returns the maximum duration (in milliseconds) that the specified app can afford the bill,
+     * based on current prices.
+     */
+    long getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
 
     /**
      * Register an {@link AffordabilityChangeListener} to track when an app's ability to afford the
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 67d7a95..a2ba75c 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -19,6 +19,8 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
@@ -30,6 +32,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.BatteryManagerInternal;
@@ -45,6 +48,7 @@
 import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArrayMap;
 import android.util.SparseSetArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -81,6 +85,7 @@
     private final Handler mHandler;
     private final BatteryManagerInternal mBatteryManagerInternal;
     private final PackageManager mPackageManager;
+    private final PackageManagerInternal mPackageManagerInternal;
 
     private final Agent mAgent;
     private final CompleteEconomicPolicy mCompleteEconomicPolicy;
@@ -95,6 +100,10 @@
     @GuardedBy("mLock")
     private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
 
+    /** Cached mapping of userId+package to their UIDs (for all users) */
+    @GuardedBy("mPackageToUidCache")
+    private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
+
     private volatile boolean mIsEnabled;
     private volatile int mBootPhase;
     // In the range [0,100] to represent 0% to 100% battery.
@@ -104,7 +113,6 @@
     @GuardedBy("mLock")
     private long mLastUnusedReclamationTime;
 
-    @SuppressWarnings("FieldCanBeLocal")
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Nullable
         private String getPackageName(Intent intent) {
@@ -159,7 +167,7 @@
                 public void onAlarm() {
                     synchronized (mLock) {
                         mAgent.reclaimUnusedAssetsLocked(DEFAULT_UNUSED_RECLAMATION_PERCENTAGE);
-                        mLastUnusedReclamationTime = System.currentTimeMillis();
+                        mLastUnusedReclamationTime = getCurrentTimeMillis();
                         scheduleUnusedWealthReclamationLocked();
                     }
                 }
@@ -185,6 +193,7 @@
         mHandler = new IrsHandler(TareHandlerThread.get().getLooper());
         mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
         mPackageManager = context.getPackageManager();
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mEconomyManagerStub = new EconomyManagerStub();
         mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
         mAgent = new Agent(this, mCompleteEconomicPolicy);
@@ -232,10 +241,28 @@
                 / 100;
     }
 
+    int getUid(final int userId, @NonNull final String pkgName) {
+        synchronized (mPackageToUidCache) {
+            Integer uid = mPackageToUidCache.get(userId, pkgName);
+            if (uid == null) {
+                uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId);
+                mPackageToUidCache.add(userId, pkgName, uid);
+            }
+            return uid;
+        }
+    }
+
     boolean isEnabled() {
         return mIsEnabled;
     }
 
+    boolean isSystem(final int userId, @NonNull String pkgName) {
+        if ("android".equals(pkgName)) {
+            return true;
+        }
+        return UserHandle.isCore(getUid(userId, pkgName));
+    }
+
     void onBatteryLevelChanged() {
         synchronized (mLock) {
             final int newBatteryLevel = getCurrentBatteryLevel();
@@ -261,6 +288,9 @@
             Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName);
             return;
         }
+        synchronized (mPackageToUidCache) {
+            mPackageToUidCache.add(userId, pkgName, uid);
+        }
         synchronized (mLock) {
             mPkgCache.add(packageInfo);
             mUidToPackageCache.add(uid, pkgName);
@@ -277,6 +307,9 @@
 
     void onPackageRemoved(final int uid, @NonNull final String pkgName) {
         final int userId = UserHandle.getUserId(uid);
+        synchronized (mPackageToUidCache) {
+            mPackageToUidCache.delete(userId, pkgName);
+        }
         synchronized (mLock) {
             mUidToPackageCache.remove(uid, pkgName);
             for (int i = 0; i < mPkgCache.size(); ++i) {
@@ -342,7 +375,7 @@
 
     @GuardedBy("mLock")
     private void scheduleUnusedWealthReclamationLocked() {
-        final long now = System.currentTimeMillis();
+        final long now = getCurrentTimeMillis();
         final long nextReclamationTime =
                 Math.max(mLastUnusedReclamationTime + UNUSED_RECLAMATION_PERIOD_MS, now + 30_000);
         mHandler.post(() -> {
@@ -447,6 +480,9 @@
             mUidToPackageCache.clear();
             getContext().unregisterReceiver(mBroadcastReceiver);
         }
+        synchronized (mPackageToUidCache) {
+            mPackageToUidCache.clear();
+        }
     }
 
     private final class IrsHandler extends Handler {
@@ -514,9 +550,22 @@
     }
 
     private final class LocalService implements EconomyManagerInternal {
+        /**
+         * Use an extremely large value to indicate that an app can pay for a bill indefinitely.
+         * The value set here should be large/long enough that there's no reasonable expectation
+         * of a device operating uninterrupted (or in the exact same state) for that period of time.
+         * We intentionally don't use Long.MAX_VALUE to avoid potential overflow if a client
+         * doesn't check the value and just immediately adds it to the current time.
+         */
+        private static final long FOREVER_MS = 27 * 365 * 24 * HOUR_IN_MILLIS;
+
         @Override
         public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName,
                 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+            if (isSystem(userId, pkgName)) {
+                // The system's affordability never changes.
+                return;
+            }
             synchronized (mLock) {
                 mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
             }
@@ -525,6 +574,10 @@
         @Override
         public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName,
                 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+            if (isSystem(userId, pkgName)) {
+                // The system's affordability never changes.
+                return;
+            }
             synchronized (mLock) {
                 mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
             }
@@ -535,6 +588,11 @@
             if (!mIsEnabled) {
                 return true;
             }
+            if (isSystem(userId, pkgName)) {
+                // The government, I mean the system, can create ARCs as it needs to in order to
+                // operate.
+                return true;
+            }
             // TODO: take temp-allowlist into consideration
             long requiredBalance = 0;
             final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
@@ -552,6 +610,32 @@
         }
 
         @Override
+        public long getMaxDurationMs(int userId, @NonNull String pkgName,
+                @NonNull ActionBill bill) {
+            if (!mIsEnabled) {
+                return FOREVER_MS;
+            }
+            if (isSystem(userId, pkgName)) {
+                return FOREVER_MS;
+            }
+            long totalCostPerSecond = 0;
+            final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
+                    bill.getAnticipatedActions();
+            for (int i = 0; i < projectedActions.size(); ++i) {
+                AnticipatedAction action = projectedActions.get(i);
+                final long cost =
+                        mCompleteEconomicPolicy.getCostOfAction(action.actionId, userId, pkgName);
+                totalCostPerSecond += cost;
+            }
+            if (totalCostPerSecond == 0) {
+                return FOREVER_MS;
+            }
+            synchronized (mLock) {
+                return mAgent.getBalanceLocked(userId, pkgName) * 1000 / totalCostPerSecond;
+            }
+        }
+
+        @Override
         public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
                 @Nullable String tag) {
             if (!mIsEnabled) {
@@ -581,7 +665,7 @@
                 return;
             }
             final long nowElapsed = SystemClock.elapsedRealtime();
-            final long now = System.currentTimeMillis();
+            final long now = getCurrentTimeMillis();
             synchronized (mLock) {
                 mAgent.stopOngoingActionLocked(userId, pkgName, eventId, tag, nowElapsed, now);
             }
@@ -630,6 +714,9 @@
 
     private void dumpInternal(final IndentingPrintWriter pw) {
         synchronized (mLock) {
+            pw.print("Is enabled: ");
+            pw.println(mIsEnabled);
+
             pw.print("Current battery level: ");
             pw.println(mCurrentBatteryLevel);
 
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
index ae1bf26..76543d7 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
@@ -19,6 +19,7 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 
 import static com.android.server.tare.TareUtils.dumpTime;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
 import static com.android.server.tare.TareUtils.narcToString;
 
 import android.annotation.NonNull;
@@ -109,8 +110,8 @@
 
     /** Deletes transactions that are older than {@code minAgeMs}. */
     void removeOldTransactions(long minAgeMs) {
-        final long cutoff = System.currentTimeMillis() - minAgeMs;
-        while (mTransactions.get(0).endTimeMs <= cutoff) {
+        final long cutoff = getCurrentTimeMillis() - minAgeMs;
+        while (mTransactions.size() > 0 && mTransactions.get(0).endTimeMs <= cutoff) {
             mTransactions.remove(0);
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
index 92a2014a..67a3dc6 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.IUidObserver;
-import android.content.pm.PackageManagerInternal;
 import android.os.RemoteException;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
@@ -28,7 +27,6 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.server.LocalServices;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -56,7 +54,6 @@
 
     private final Object mLock = new Object();
     private final InternalResourceService mIrs;
-    private final PackageManagerInternal mPackageManagerInternal;
 
     /** Cached mapping of userId+package to their UIDs (for all users) */
     private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
@@ -105,7 +102,6 @@
     ProcessStateModifier(@NonNull InternalResourceService irs) {
         super();
         mIrs = irs;
-        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
     }
 
     @Override
@@ -143,7 +139,7 @@
         final int procState;
         synchronized (mLock) {
             procState = mUidProcStateBucketCache.get(
-                    getUidLocked(userId, pkgName), PROC_STATE_BUCKET_NONE);
+                    mIrs.getUid(userId, pkgName), PROC_STATE_BUCKET_NONE);
         }
         switch (procState) {
             case PROC_STATE_BUCKET_TOP:
@@ -166,15 +162,6 @@
         pw.println(mUidProcStateBucketCache);
     }
 
-    @GuardedBy("mLock")
-    private int getUidLocked(final int userId, @NonNull final String pkgName) {
-        if (!mPackageToUidCache.contains(userId, pkgName)) {
-            mPackageToUidCache.add(userId, pkgName,
-                    mPackageManagerInternal.getPackageUid(pkgName, 0, userId));
-        }
-        return mPackageToUidCache.get(userId, pkgName);
-    }
-
     @ProcStateBucket
     private int getProcStateBucket(int procState) {
         if (procState <= ActivityManager.PROCESS_STATE_TOP) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
index 2d72f56..1e047aa 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
@@ -20,7 +20,10 @@
 import android.annotation.SuppressLint;
 import android.util.IndentingPrintWriter;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.text.SimpleDateFormat;
+import java.time.Clock;
 
 class TareUtils {
     private static final long NARC_IN_ARC = 1_000_000_000L;
@@ -29,6 +32,9 @@
     private static final SimpleDateFormat sDumpDateFormat =
             new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
 
+    @VisibleForTesting
+    static Clock sSystemClock = Clock.systemUTC();
+
     static long arcToNarc(int arcs) {
         return arcs * NARC_IN_ARC;
     }
@@ -37,6 +43,10 @@
         pw.print(sDumpDateFormat.format(time));
     }
 
+    static long getCurrentTimeMillis() {
+        return sSystemClock.millis();
+    }
+
     static int narcToArc(long narcs) {
         return (int) (narcs / NARC_IN_ARC);
     }
@@ -59,4 +69,10 @@
         sb.append(" ARCs");
         return sb.toString();
     }
+
+    /** Returns a standardized format for printing userId+pkgName combinations. */
+    @NonNull
+    static String appToString(int userId, String pkgName) {
+        return "<" + userId + ">" + pkgName;
+    }
 }
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index b2b66c2..3534624 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -71,7 +71,7 @@
         "libui",
         "libjnigraphics",
         "libEGL",
-        "libGLESv1_CM",
+        "libGLESv2",
         "libgui",
     ],
 }
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 3109c5c..6e27aff 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -52,9 +52,8 @@
 #include <gui/DisplayEventReceiver.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 #include <EGL/eglext.h>
 
 #include "BootAnimation.h"
@@ -108,6 +107,56 @@
 static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
 static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
 static constexpr size_t TEXT_POS_LEN_MAX = 16;
+static const char U_TEXTURE[] = "uTexture";
+static const char U_FADE[] = "uFade";
+static const char U_CROP_AREA[] = "uCropArea";
+static const char A_UV[] = "aUv";
+static const char A_POSITION[] = "aPosition";
+static const char VERTEX_SHADER_SOURCE[] = R"(
+    precision mediump float;
+    attribute vec4 aPosition;
+    attribute highp vec2 aUv;
+    varying highp vec2 vUv;
+    void main() {
+        gl_Position = aPosition;
+        vUv = aUv;
+    })";
+static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
+    precision mediump float;
+    uniform sampler2D uTexture;
+    uniform float uFade;
+    varying highp vec2 vUv;
+    void main() {
+        vec4 color = texture2D(uTexture, vUv);
+        gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade);
+    })";
+static const char TEXT_FRAG_SHADER_SOURCE[] = R"(
+    precision mediump float;
+    uniform sampler2D uTexture;
+    uniform vec4 uCropArea;
+    varying highp vec2 vUv;
+    void main() {
+        vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x),
+                       mix(uCropArea.y, uCropArea.w, vUv.y));
+        gl_FragColor = texture2D(uTexture, uv);
+    })";
+
+static GLfloat quadPositions[] = {
+    -0.5f, -0.5f,
+    +0.5f, -0.5f,
+    +0.5f, +0.5f,
+    +0.5f, +0.5f,
+    -0.5f, +0.5f,
+    -0.5f, -0.5f
+};
+static GLfloat quadUVs[] = {
+    0.0f, 1.0f,
+    1.0f, 1.0f,
+    1.0f, 0.0f,
+    1.0f, 0.0f,
+    0.0f, 0.0f,
+    0.0f, 1.0f
+};
 
 // ---------------------------------------------------------------------------
 
@@ -209,7 +258,6 @@
     const int w = bitmapInfo.width;
     const int h = bitmapInfo.height;
 
-    GLint crop[4] = { 0, h, w, -h };
     texture->w = w;
     texture->h = h;
 
@@ -237,11 +285,10 @@
             break;
     }
 
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     return NO_ERROR;
 }
@@ -263,7 +310,6 @@
     const int w = bitmapInfo.width;
     const int h = bitmapInfo.height;
 
-    GLint crop[4] = { 0, h, w, -h };
     int tw = 1 << (31 - __builtin_clz(w));
     int th = 1 << (31 - __builtin_clz(h));
     if (tw < w) tw <<= 1;
@@ -297,7 +343,10 @@
             break;
     }
 
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     *width = w;
     *height = h;
@@ -470,7 +519,9 @@
     eglInitialize(display, nullptr, nullptr);
     EGLConfig config = getEglConfig(display);
     EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
-    EGLContext context = eglCreateContext(display, config, nullptr, nullptr);
+    // Initialize egl context with client version number 2.0.
+    EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+    EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes);
     EGLint w, h;
     eglQuerySurface(display, surface, EGL_WIDTH, &w);
     eglQuerySurface(display, surface, EGL_HEIGHT, &h);
@@ -503,11 +554,6 @@
 void BootAnimation::projectSceneToWindow() {
     glViewport(0, 0, mWidth, mHeight);
     glScissor(0, 0, mWidth, mHeight);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    glOrthof(0, static_cast<float>(mWidth), 0, static_cast<float>(mHeight), -1, 1);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
 }
 
 void BootAnimation::resizeSurface(int newWidth, int newHeight) {
@@ -600,8 +646,68 @@
     }
 }
 
+GLuint compileShader(GLenum shaderType, const GLchar *source) {
+    GLuint shader = glCreateShader(shaderType);
+    glShaderSource(shader, 1, &source, 0);
+    glCompileShader(shader);
+    GLint isCompiled = 0;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
+    if (isCompiled == GL_FALSE) {
+        SLOGE("Compile shader failed. Shader type: %d", shaderType);
+        return 0;
+    }
+    return shader;
+}
+
+GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) {
+    GLuint program = glCreateProgram();
+    glAttachShader(program, vertexShader);
+    glAttachShader(program, fragmentShader);
+    glLinkProgram(program);
+    GLint isLinked = 0;
+    glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
+    if (isLinked == GL_FALSE) {
+        SLOGE("Linking shader failed. Shader handles: vert %d, frag %d",
+            vertexShader, fragmentShader);
+        return 0;
+    }
+    return program;
+}
+
+void BootAnimation::initShaders() {
+    GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE);
+    GLuint imageFragmentShader =
+        compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE);
+    GLuint textFragmentShader =
+        compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE);
+
+    // Initialize image shader.
+    mImageShader = linkShader(vertexShader, imageFragmentShader);
+    GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION);
+    GLint uvLocation = glGetAttribLocation(mImageShader, A_UV);
+    mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE);
+    mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE);
+    glEnableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 2,  GL_FLOAT, GL_FALSE, 0, quadPositions);
+    glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+    glEnableVertexAttribArray(uvLocation);
+
+    // Initialize text shader.
+    mTextShader = linkShader(vertexShader, textFragmentShader);
+    positionLocation = glGetAttribLocation(mTextShader, A_POSITION);
+    uvLocation = glGetAttribLocation(mTextShader, A_UV);
+    mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE);
+    mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA);
+    glEnableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 2,  GL_FLOAT, GL_FALSE, 0, quadPositions);
+    glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+    glEnableVertexAttribArray(uvLocation);
+}
+
 bool BootAnimation::threadLoop() {
     bool result;
+    initShaders();
+
     // We have no bootanimation file, so we use the stock android logo
     // animation.
     if (mZipFileName.isEmpty()) {
@@ -623,6 +729,8 @@
 }
 
 bool BootAnimation::android() {
+    glActiveTexture(GL_TEXTURE0);
+
     SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
             elapsedRealtime());
     initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
@@ -631,19 +739,14 @@
     mCallbacks->init({});
 
     // clear screen
-    glShadeModel(GL_FLAT);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
     glClearColor(0,0,0,1);
     glClear(GL_COLOR_BUFFER_BIT);
     eglSwapBuffers(mDisplay, mSurface);
 
-    glEnable(GL_TEXTURE_2D);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
     // Blend state
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
     const nsecs_t startTime = systemTime();
     do {
@@ -666,12 +769,12 @@
         glEnable(GL_SCISSOR_TEST);
         glDisable(GL_BLEND);
         glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
-        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
-        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
+        drawTexturedQuad(x,                 yc, mAndroid[1].w, mAndroid[1].h);
+        drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
 
         glEnable(GL_BLEND);
         glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
-        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
+        drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
 
         EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
         if (res == EGL_FALSE)
@@ -798,10 +901,10 @@
 
         status = initTexture(font->map, &font->texture.w, &font->texture.h);
 
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     } else if (fallback != nullptr) {
         status = initTexture(&font->texture, mAssets, fallback);
     } else {
@@ -816,40 +919,11 @@
     return status;
 }
 
-void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth,
-                              const int frameHeight, const Animation::Part& part,
-                              const int fadedFramesCount) {
-    glEnable(GL_BLEND);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glDisable(GL_TEXTURE_2D);
-    // avoid creating a hole due to mixing result alpha with GL_REPLACE texture
-    glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
-
-    const float alpha = static_cast<float>(fadedFramesCount) / part.framesToFadeCount;
-    glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha);
-
-    const float frameStartX = static_cast<float>(frameLeft);
-    const float frameStartY = static_cast<float>(frameBottom);
-    const float frameEndX = frameStartX + frameWidth;
-    const float frameEndY = frameStartY + frameHeight;
-    const GLfloat frameRect[] = {
-        frameStartX, frameStartY,
-        frameEndX,   frameStartY,
-        frameEndX,   frameEndY,
-        frameStartX, frameEndY
-    };
-    glVertexPointer(2, GL_FLOAT, 0, frameRect);
-    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glEnable(GL_TEXTURE_2D);
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisable(GL_BLEND);
-}
-
 void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
     glEnable(GL_BLEND);  // Allow us to draw on top of the animation
     glBindTexture(GL_TEXTURE_2D, font.texture.name);
+    glUseProgram(mTextShader);
+    glUniform1i(mTextTextureLocation, 0);
 
     const int len = strlen(str);
     const int strWidth = font.char_width * len;
@@ -865,8 +939,6 @@
         *y = mHeight + *y - font.char_height;
     }
 
-    int cropRect[4] = { 0, 0, font.char_width, -font.char_height };
-
     for (int i = 0; i < len; i++) {
         char c = str[i];
 
@@ -878,13 +950,13 @@
         const int charPos = (c - FONT_BEGIN_CHAR);  // Position in the list of valid characters
         const int row = charPos / FONT_NUM_COLS;
         const int col = charPos % FONT_NUM_COLS;
-        cropRect[0] = col * font.char_width;  // Left of column
-        cropRect[1] = row * font.char_height * 2; // Top of row
-        // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
-        cropRect[1] += bold ? 2 * font.char_height : font.char_height;
-        glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
-
-        glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);
+        // Bold fonts are expected in the second half of each row.
+        float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS;
+        float u0 = ((float)col) / FONT_NUM_COLS;
+        float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2;
+        float u1 = u0 + 1.0f / FONT_NUM_COLS;
+        glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1);
+        drawTexturedQuad(*x, *y, font.char_width, font.char_height);
 
         *x += font.char_width;
     }
@@ -1166,19 +1238,16 @@
 
     // Blend required to draw time on top of animation frames.
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glShadeModel(GL_FLAT);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
     glDisable(GL_BLEND);
 
-    glBindTexture(GL_TEXTURE_2D, 0);
     glEnable(GL_TEXTURE_2D);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     bool clockFontInitialized = false;
     if (mClockEnabled) {
         clockFontInitialized =
@@ -1218,6 +1287,34 @@
         (lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
 }
 
+// Linear mapping from range <a1, a2> to range <b1, b2>
+float mapLinear(float x, float a1, float a2, float b1, float b2) {
+    return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
+}
+
+void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) {
+    // Map coordinates from screen space to world space.
+    float x0 = mapLinear(xStart, 0, mWidth, -1, 1);
+    float y0 = mapLinear(yStart, 0, mHeight, -1, 1);
+    float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1);
+    float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1);
+    // Update quad vertex positions.
+    quadPositions[0] = x0;
+    quadPositions[1] = y0;
+    quadPositions[2] = x1;
+    quadPositions[3] = y0;
+    quadPositions[4] = x1;
+    quadPositions[5] = y1;
+    quadPositions[6] = x1;
+    quadPositions[7] = y1;
+    quadPositions[8] = x0;
+    quadPositions[9] = y1;
+    quadPositions[10] = x0;
+    quadPositions[11] = y0;
+    glDrawArrays(GL_TRIANGLES, 0,
+        sizeof(quadPositions) / sizeof(quadPositions[0]) / 2);
+}
+
 bool BootAnimation::playAnimation(const Animation& animation) {
     const size_t pcount = animation.parts.size();
     nsecs_t frameDuration = s2ns(1) / animation.fps;
@@ -1230,7 +1327,6 @@
     for (size_t i=0 ; i<pcount ; i++) {
         const Animation::Part& part(animation.parts[i]);
         const size_t fcount = part.frames.size();
-        glBindTexture(GL_TEXTURE_2D, 0);
 
         // Handle animation package
         if (part.animation != nullptr) {
@@ -1272,12 +1368,8 @@
                 if (r > 0) {
                     glBindTexture(GL_TEXTURE_2D, frame.tid);
                 } else {
-                    if (part.count != 1) {
-                        glGenTextures(1, &frame.tid);
-                        glBindTexture(GL_TEXTURE_2D, frame.tid);
-                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-                    }
+                    glGenTextures(1, &frame.tid);
+                    glBindTexture(GL_TEXTURE_2D, frame.tid);
                     int w, h;
                     initTexture(frame.map, &w, &h);
                 }
@@ -1300,16 +1392,21 @@
                 // specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
                 // which is equivalent to mHeight - (yc + frame.trimHeight)
                 const int frameDrawY = mHeight - (yc + frame.trimHeight);
-                glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight);
 
+                float fade = 0;
                 // if the part hasn't been stopped yet then continue fading if necessary
                 if (exitPending() && part.hasFadingPhase()) {
-                    fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,
-                              ++fadedFramesCount);
+                    fade = static_cast<float>(++fadedFramesCount) / part.framesToFadeCount;
                     if (fadedFramesCount >= part.framesToFadeCount) {
                         fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading
                     }
                 }
+                glUseProgram(mImageShader);
+                glUniform1i(mImageTextureLocation, 0);
+                glUniform1f(mImageFadeLocation, fade);
+                glEnable(GL_BLEND);
+                drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight);
+                glDisable(GL_BLEND);
 
                 if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
                     drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f8a31c6..7b616d9 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -31,7 +31,7 @@
 #include <binder/IBinder.h>
 
 #include <EGL/egl.h>
-#include <GLES/gl.h>
+#include <GLES2/gl2.h>
 
 namespace android {
 
@@ -166,6 +166,7 @@
     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
     status_t initTexture(FileMap* map, int* width, int* height);
     status_t initFont(Font* font, const char* fallback);
+    void initShaders();
     bool android();
     bool movie();
     void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
@@ -173,6 +174,7 @@
     void drawProgress(int percent, const Font& font, const int xPos, const int yPos);
     void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
                    const Animation::Part& part, int fadedFramesCount);
+    void drawTexturedQuad(float xStart, float yStart, float width, float height);
     bool validClock(const Animation::Part& part);
     Animation* loadAnimation(const String8&);
     bool playAnimation(const Animation&);
@@ -218,6 +220,12 @@
     sp<TimeCheckThread> mTimeCheckThread = nullptr;
     sp<Callbacks> mCallbacks;
     Animation* mAnimation = nullptr;
+    GLuint mImageShader;
+    GLuint mTextShader;
+    GLuint mImageFadeLocation;
+    GLuint mImageTextureLocation;
+    GLuint mTextCropAreaLocation;
+    GLuint mTextTextureLocation;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/core/api/current.txt b/core/api/current.txt
index 4c1476c..396c080 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25266,13 +25266,17 @@
   public final class MediaSessionManager {
     method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName);
     method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @Nullable android.os.Handler);
+    method public void addOnMediaKeyEventSessionChangedListener(@NonNull android.content.ComponentName, @NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
     method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
     method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener, @NonNull android.os.Handler);
     method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
+    method @Nullable public android.media.session.MediaSession.Token getMediaKeyEventSession(@NonNull android.content.ComponentName);
+    method @NonNull public String getMediaKeyEventSessionPackageName(@NonNull android.content.ComponentName);
     method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
     method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
     method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
     method public void removeOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
+    method public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
     method public void removeOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
   }
 
@@ -25280,6 +25284,10 @@
     method public void onActiveSessionsChanged(@Nullable java.util.List<android.media.session.MediaController>);
   }
 
+  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
+    method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
+  }
+
   public static interface MediaSessionManager.OnSession2TokensChangedListener {
     method public void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
   }
@@ -31676,6 +31684,7 @@
     method public boolean isDeviceIdleMode();
     method public boolean isIgnoringBatteryOptimizations(String);
     method public boolean isInteractive();
+    method public boolean isLightDeviceIdleMode();
     method public boolean isPowerSaveMode();
     method public boolean isRebootingUserspaceSupported();
     method @Deprecated public boolean isScreenOn();
@@ -31686,6 +31695,7 @@
     method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
+    field public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
     field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
     field @Deprecated public static final int FULL_WAKE_LOCK = 26; // 0x1a
     field public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; // 0x2
@@ -34824,6 +34834,7 @@
   }
 
   public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
+    field public static final String ACTION_SET_DEFAULT_ACCOUNT = "android.provider.action.SET_DEFAULT_ACCOUNT";
     field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
     field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
     field public static final android.net.Uri CONTENT_URI;
@@ -51933,7 +51944,7 @@
     method public boolean finishComposingText();
     method public int getCursorCapsMode(int);
     method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
-    method public android.os.Handler getHandler();
+    method @Nullable public android.os.Handler getHandler();
     method public CharSequence getSelectedText(int);
     method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
     method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 96c990d..1eec826 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5587,7 +5587,6 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession();
     method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName();
     method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
-    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
     method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
   }
@@ -5596,10 +5595,6 @@
     method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token);
   }
 
-  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
-    method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
-  }
-
   public static interface MediaSessionManager.OnMediaKeyListener {
     method public boolean onMediaKey(android.view.KeyEvent);
   }
@@ -7028,13 +7023,13 @@
     field public static final long FEC_23_36 = 268435456L; // 0x10000000L
     field public static final long FEC_25_36 = 536870912L; // 0x20000000L
     field public static final long FEC_26_45 = 1073741824L; // 0x40000000L
-    field public static final long FEC_28_45 = -2147483648L; // 0xffffffff80000000L
-    field public static final long FEC_29_45 = 1L; // 0x1L
+    field public static final long FEC_28_45 = 2147483648L; // 0x80000000L
+    field public static final long FEC_29_45 = 4294967296L; // 0x100000000L
     field public static final long FEC_2_3 = 32L; // 0x20L
     field public static final long FEC_2_5 = 64L; // 0x40L
     field public static final long FEC_2_9 = 128L; // 0x80L
-    field public static final long FEC_31_45 = 2L; // 0x2L
-    field public static final long FEC_32_45 = 4L; // 0x4L
+    field public static final long FEC_31_45 = 8589934592L; // 0x200000000L
+    field public static final long FEC_32_45 = 17179869184L; // 0x400000000L
     field public static final long FEC_3_4 = 256L; // 0x100L
     field public static final long FEC_3_5 = 512L; // 0x200L
     field public static final long FEC_4_15 = 2048L; // 0x800L
@@ -7042,7 +7037,7 @@
     field public static final long FEC_5_6 = 4096L; // 0x1000L
     field public static final long FEC_5_9 = 8192L; // 0x2000L
     field public static final long FEC_6_7 = 16384L; // 0x4000L
-    field public static final long FEC_77_90 = 8L; // 0x8L
+    field public static final long FEC_77_90 = 34359738368L; // 0x800000000L
     field public static final long FEC_7_15 = 131072L; // 0x20000L
     field public static final long FEC_7_8 = 32768L; // 0x8000L
     field public static final long FEC_7_9 = 65536L; // 0x10000L
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 45db0f6..fd6589c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -2112,7 +2112,8 @@
                     throw new ActivityNotFoundException(
                             "Unable to find explicit activity class "
                             + ((Intent)intent).getComponent().toShortString()
-                            + "; have you declared this activity in your AndroidManifest.xml?");
+                            + "; have you declared this activity in your AndroidManifest.xml"
+                            + ", or does your intent not match its declared <intent-filter>?");
                 throw new ActivityNotFoundException(
                         "No Activity found to handle " + intent);
             case ActivityManager.START_PERMISSION_DENIED:
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 27db25d..9a37d04 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -13736,8 +13736,6 @@
      *
      * It is recommended that the Enterprise ID is at least 6 characters long, and no more than
      * 64 characters.
-     * This API is supposed to be called only after the boot phase is complete,
-     * throws {@link IllegalStateException} if called before boot phase is complete.
      *
      * @param enterpriseId An identifier of the organization this work profile or device is
      *                     enrolled into.
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
index 266e33a..5694ca8 100644
--- a/core/java/android/appwidget/AppWidgetManagerInternal.java
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -19,8 +19,6 @@
 import android.annotation.Nullable;
 import android.util.ArraySet;
 
-import java.util.Set;
-
 /**
  * App widget manager local system service interface.
  *
@@ -44,16 +42,4 @@
      * @param userId The user that is being unlocked.
      */
     public abstract void unlockUser(int userId);
-
-    /**
-     * Updates all widgets, applying changes to Runtime Resource Overlay affecting the specified
-     * target packages.
-     *
-     * @param packageNames The names of all target packages for which an overlay was modified
-     * @param userId The user for which overlay modifications occurred.
-     * @param updateFrameworkRes Whether or not an overlay affected the values of framework
-     *                           resources.
-     */
-    public abstract void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
-            boolean updateFrameworkRes);
 }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a741f96..c714f507 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -745,9 +745,6 @@
         if (Binder.getCallingPid() == Process.myPid()) {
             return PermissionChecker.PERMISSION_GRANTED;
         }
-        if (!attributionSource.checkCallingUid()) {
-            return PermissionChecker.PERMISSION_HARD_DENIED;
-        }
         return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(),
                 permission, -1, new AttributionSource(getContext().getAttributionSource(),
                         attributionSource), /*message*/ null);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bed0383..29ce397 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -55,6 +55,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.overlay.OverlayPaths;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.split.SplitAssetLoader;
 import android.content.pm.parsing.result.ParseResult;
 import android.content.pm.parsing.result.ParseTypeImpl;
 import android.content.res.ApkAssets;
@@ -7425,7 +7427,7 @@
             mCompileSdkVersionCodename = dest.readString();
             mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
 
-            mKeySetMapping = readKeySetMapping(dest);
+            mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest);
 
             cpuAbiOverride = dest.readString();
             use32bitAbi = (dest.readInt() == 1);
@@ -7551,73 +7553,13 @@
             dest.writeInt(mCompileSdkVersion);
             dest.writeString(mCompileSdkVersionCodename);
             dest.writeArraySet(mUpgradeKeySets);
-            writeKeySetMapping(dest, mKeySetMapping);
+            ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping);
             dest.writeString(cpuAbiOverride);
             dest.writeInt(use32bitAbi ? 1 : 0);
             dest.writeByteArray(restrictUpdateHash);
             dest.writeInt(visibleToInstantApps ? 1 : 0);
         }
 
-        /**
-         * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
-         */
-        private static void writeKeySetMapping(
-                Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
-            if (keySetMapping == null) {
-                dest.writeInt(-1);
-                return;
-            }
-
-            final int N = keySetMapping.size();
-            dest.writeInt(N);
-
-            for (int i = 0; i < N; i++) {
-                dest.writeString(keySetMapping.keyAt(i));
-                ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
-                if (keys == null) {
-                    dest.writeInt(-1);
-                    continue;
-                }
-
-                final int M = keys.size();
-                dest.writeInt(M);
-                for (int j = 0; j < M; j++) {
-                    dest.writeSerializable(keys.valueAt(j));
-                }
-            }
-        }
-
-        /**
-         * Reads a keyset mapping from the given parcel at the given data position. May return
-         * {@code null} if the serialized mapping was {@code null}.
-         */
-        private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
-            final int N = in.readInt();
-            if (N == -1) {
-                return null;
-            }
-
-            ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
-            for (int i = 0; i < N; ++i) {
-                String key = in.readString();
-                final int M = in.readInt();
-                if (M == -1) {
-                    keySetMapping.put(key, null);
-                    continue;
-                }
-
-                ArraySet<PublicKey> keys = new ArraySet<>(M);
-                for (int j = 0; j < M; ++j) {
-                    PublicKey pk = (PublicKey) in.readSerializable();
-                    keys.add(pk);
-                }
-
-                keySetMapping.put(key, keys);
-            }
-
-            return keySetMapping;
-        }
-
         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
             public Package createFromParcel(Parcel in) {
                 return new Package(in);
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index 9fee7bb..f2a6a5c 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -535,7 +535,7 @@
         ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
         Float minAspectRatio = a.getMinAspectRatio();
         ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
-        ai.supportsSizeChanges = a.getSupportsSizeChanges();
+        ai.supportsSizeChanges = a.isSupportsSizeChanges();
         ai.requestedVrComponent = a.getRequestedVrComponent();
         ai.rotationAnimation = a.getRotationAnimation();
         ai.colorMode = a.getColorMode();
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 72cc929..d6e1ac9 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -360,7 +360,7 @@
 
     ParsingPackage setCompileSdkVersion(int compileSdkVersion);
 
-    ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
+    ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName);
 
     ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);
 
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 0db6546..f0d95d9 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -553,7 +553,7 @@
 
             setCompileSdkVersion(manifestArray.getInteger(
                     R.styleable.AndroidManifest_compileSdkVersion, 0));
-            setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
+            setCompileSdkVersionCodeName(manifestArray.getNonConfigurationString(
                     R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
 
             setIsolatedSplitLoading(manifestArray.getBoolean(
@@ -2686,8 +2686,8 @@
     }
 
     @Override
-    public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
-        this.compileSdkVersionCodeName = compileSdkVersionCodename;
+    public ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName) {
+        this.compileSdkVersionCodeName = compileSdkVersionCodeName;
         return this;
     }
 
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
index 73ee132..adb6b76 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivity.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -23,6 +23,7 @@
 import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
@@ -423,6 +424,7 @@
         }
     }
 
+    @NonNull
     public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
         @Override
         public ParsedActivity createFromParcel(Parcel source) {
@@ -513,10 +515,6 @@
         return minAspectRatio;
     }
 
-    public boolean getSupportsSizeChanges() {
-        return supportsSizeChanges;
-    }
-
     @Nullable
     public String getRequestedVrComponent() {
         return requestedVrComponent;
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
index 3c0f097..838adfd 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -43,8 +43,8 @@
 /** @hide */
 public abstract class ParsedComponent implements Parcelable {
 
-    private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
-            ParsedIntentInfo.ListParceler.class);
+    private static final ParsedIntentInfo.ListParceler sForIntentInfos =
+            Parcelling.Cache.getOrCreate(ParsedIntentInfo.ListParceler.class);
 
     @NonNull
     @DataClass.ParcelWith(ForInternedString.class)
diff --git a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
index 65ff472..4178920 100644
--- a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
+++ b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.os.Parcel;
@@ -94,6 +95,7 @@
         this.functionalTest = in.readByte() != 0;
     }
 
+    @NonNull
     public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
             new Parcelable.Creator<ParsedInstrumentation>() {
                 @Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
index 01ee0f4..59d4a95 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm.parsing.component;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.IntentFilter;
 import android.os.Parcel;
@@ -58,6 +59,7 @@
             item.writeIntentInfoToParcel(dest, parcelFlags);
         }
 
+        @NonNull
         @Override
         public ParsedIntentInfo unparcel(Parcel source) {
             return new ParsedIntentInfo(source);
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermission.java b/core/java/android/content/pm/parsing/component/ParsedPermission.java
index 50bc3d9..0f82941 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermission.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermission.java
@@ -16,6 +16,7 @@
 
 package android.content.pm.parsing.component;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.PermissionInfo;
 import android.os.Parcel;
@@ -167,6 +168,7 @@
         this.knownCerts = sForStringSet.unparcel(in);
     }
 
+    @NonNull
     public static final Parcelable.Creator<ParsedPermission> CREATOR =
             new Parcelable.Creator<ParsedPermission>() {
                 @Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcess.java b/core/java/android/content/pm/parsing/component/ParsedProcess.java
index c39d6b1..fe10225 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcess.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcess.java
@@ -19,7 +19,6 @@
 import static java.util.Collections.emptySet;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
diff --git a/core/java/android/content/pm/parsing/component/ParsedProvider.java b/core/java/android/content/pm/parsing/component/ParsedProvider.java
index ebf85f7..9a12b48 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProvider.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProvider.java
@@ -169,6 +169,7 @@
         this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
     }
 
+    @NonNull
     public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
         @Override
         public ParsedProvider createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/parsing/component/ParsedService.java b/core/java/android/content/pm/parsing/component/ParsedService.java
index 471d346..5499a13 100644
--- a/core/java/android/content/pm/parsing/component/ParsedService.java
+++ b/core/java/android/content/pm/parsing/component/ParsedService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.os.Parcel;
@@ -83,6 +84,7 @@
         this.permission = sForInternedString.unparcel(in);
     }
 
+    @NonNull
     public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
         @Override
         public ParsedService createFromParcel(Parcel source) {
diff --git a/core/java/android/hardware/camera2/MultiResolutionImageReader.java b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
index 3af1b5b..0dbf29d 100644
--- a/core/java/android/hardware/camera2/MultiResolutionImageReader.java
+++ b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
@@ -91,7 +91,7 @@
      * </p>
      * <p>
      * The {@code maxImages} parameter determines the maximum number of
-     * {@link Image} objects that can be be acquired from each of the {@code ImageReader}
+     * {@link Image} objects that can be acquired from each of the {@code ImageReader}
      * within the {@code MultiResolutionImageReader}. However, requesting more buffers will
      * use up more memory, so it is important to use only the minimum number necessary. The
      * application is strongly recommended to acquire no more than {@code maxImages} images
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 8fd9a6a..196134b 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1720,21 +1720,21 @@
                 new SetCommand() {
             @Override
             public <T> void setValue(CameraMetadataNative metadata, T value) {
-                metadata.setAWBRegions((MeteringRectangle[]) value);
+                metadata.setAWBRegions(value);
             }
         });
         sSetCommandMap.put(CaptureRequest.CONTROL_AF_REGIONS.getNativeKey(),
                 new SetCommand() {
             @Override
             public <T> void setValue(CameraMetadataNative metadata, T value) {
-                metadata.setAFRegions((MeteringRectangle[]) value);
+                metadata.setAFRegions(value);
             }
         });
         sSetCommandMap.put(CaptureRequest.CONTROL_AE_REGIONS.getNativeKey(),
                 new SetCommand() {
             @Override
             public <T> void setValue(CameraMetadataNative metadata, T value) {
-                metadata.setAERegions((MeteringRectangle[]) value);
+                metadata.setAERegions(value);
             }
         });
     }
@@ -1815,30 +1815,33 @@
         return true;
     }
 
-    private <T> boolean setAFRegions(MeteringRectangle[] afRegions) {
+    private <T> boolean setAFRegions(T afRegions) {
         if (afRegions == null) {
             return false;
         }
         setBase(CaptureRequest.CONTROL_AF_REGIONS_SET, true);
-        setBase(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
+        // The cast to CaptureRequest.Key is needed since java does not support template
+        // specialization and we need to route this method to
+        // setBase(CaptureRequest.Key<T> key, T value)
+        setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AF_REGIONS, afRegions);
         return true;
     }
 
-    private <T> boolean setAERegions(MeteringRectangle[] aeRegions) {
+    private <T> boolean setAERegions(T aeRegions) {
         if (aeRegions == null) {
             return false;
         }
         setBase(CaptureRequest.CONTROL_AE_REGIONS_SET, true);
-        setBase(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
+        setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
         return true;
     }
 
-    private <T> boolean setAWBRegions(MeteringRectangle[] awbRegions) {
+    private <T> boolean setAWBRegions(T awbRegions) {
         if (awbRegions == null) {
             return false;
         }
         setBase(CaptureRequest.CONTROL_AWB_REGIONS_SET, true);
-        setBase(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
+        setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
         return true;
     }
 
diff --git a/core/java/android/hardware/camera2/params/InputConfiguration.java b/core/java/android/hardware/camera2/params/InputConfiguration.java
index 8dfc0a7b..70c85a1 100644
--- a/core/java/android/hardware/camera2/params/InputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/InputConfiguration.java
@@ -42,7 +42,7 @@
     private final boolean mIsMultiResolution;
 
     /**
-     * Create an input configration with the width, height, and user-defined format.
+     * Create an input configuration with the width, height, and user-defined format.
      *
      * <p>Images of a user-defined format are accessible by applications. Use
      * {@link android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP}
@@ -64,7 +64,7 @@
     }
 
     /**
-     * Create an input configration with the format and a list of multi-resolution input stream
+     * Create an input configuration with the format and a list of multi-resolution input stream
      * info.
      *
      * <p>Use {@link
@@ -108,7 +108,7 @@
     }
 
     /**
-     * Get the width of this input configration.
+     * Get the width of this input configuration.
      *
      * @return width of this input configuration.
      */
@@ -117,7 +117,7 @@
     }
 
     /**
-     * Get the height of this input configration.
+     * Get the height of this input configuration.
      *
      * @return height of this input configuration.
      */
@@ -126,7 +126,7 @@
     }
 
     /**
-     * Get the format of this input configration.
+     * Get the format of this input configuration.
      *
      * @return format of this input configuration.
      */
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index f38271a..403f55c 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.os.IDropBoxManagerService;
 
+import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
@@ -257,7 +258,8 @@
             } else {
                 return null;
             }
-            return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+            return (mFlags & IS_GZIPPED) != 0
+                ? new GZIPInputStream(new BufferedInputStream(is)) : is;
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3aa0bcb..2f66a39 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2092,9 +2092,7 @@
      * when light idle mode restrictions are being actively applied; it will return false if the
      * device is in a long-term idle mode but currently running a maintenance window where
      * restrictions have been lifted.
-     * @hide
      */
-    @UnsupportedAppUsage
     public boolean isLightDeviceIdleMode() {
         try {
             return mService.isLightDeviceIdleMode();
@@ -2555,9 +2553,7 @@
     /**
      * Intent that is broadcast when the state of {@link #isLightDeviceIdleMode()} changes.
      * This broadcast is only sent to registered receivers.
-     * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
             = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b3d60a5..570d73d 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8588,6 +8588,15 @@
          * Type: INTEGER
          */
         public static final String UNGROUPED_WITH_PHONES = "summ_phones";
+
+        /**
+         * Flag indicating if the account is the default account for new contacts. At most one
+         * account has this flag set at a time. It can only be set to 1 on a row with null data set.
+         * <p>
+         * Type: INTEGER (boolean)
+         * @hide
+         */
+        String IS_DEFAULT = "x_is_default";
     }
 
     /**
@@ -8681,6 +8690,13 @@
          * The MIME-type of {@link #CONTENT_URI} providing a single setting.
          */
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
+
+        /**
+         * Action used to launch the UI to set the default account for new contacts.
+         */
+        @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+        public static final String ACTION_SET_DEFAULT_ACCOUNT =
+                "android.provider.action.SET_DEFAULT_ACCOUNT";
     }
 
     /**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 9cb0d1f..e7ff978 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1463,10 +1463,10 @@
             return false;
         }
         final Configuration config = mResources.getConfiguration();
-        // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking
-        // if the caller is the recents component.
+        // TODO(b/179308296) Temporarily - never report max bounds to only Launcher if the feature
+        // is disabled.
         return config != null && !config.windowConfiguration.getMaxBounds().isEmpty()
-                && !isRecentsComponent();
+                && (mDisplayInfo.shouldConstrainMetricsForLauncher || !isRecentsComponent());
     }
 
     /**
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 8e5f905..6572510 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -306,6 +306,13 @@
     public float brightnessDefault;
 
     /**
+     * @hide
+     * True if Display#getRealSize and getRealMetrics should be constrained for Launcher, false
+     * otherwise.
+     */
+    public boolean shouldConstrainMetricsForLauncher = false;
+
+    /**
      * The {@link RoundedCorners} if present, otherwise {@code null}.
      */
     @Nullable
@@ -381,7 +388,8 @@
                 && brightnessMinimum == other.brightnessMinimum
                 && brightnessMaximum == other.brightnessMaximum
                 && brightnessDefault == other.brightnessDefault
-                && Objects.equals(roundedCorners, other.roundedCorners);
+                && Objects.equals(roundedCorners, other.roundedCorners)
+                && shouldConstrainMetricsForLauncher == other.shouldConstrainMetricsForLauncher;
     }
 
     @Override
@@ -432,6 +440,7 @@
         brightnessMaximum = other.brightnessMaximum;
         brightnessDefault = other.brightnessDefault;
         roundedCorners = other.roundedCorners;
+        shouldConstrainMetricsForLauncher = other.shouldConstrainMetricsForLauncher;
     }
 
     public void readFromParcel(Parcel source) {
@@ -488,6 +497,7 @@
         for (int i = 0; i < numUserDisabledFormats; i++) {
             userDisabledHdrTypes[i] = source.readInt();
         }
+        shouldConstrainMetricsForLauncher = source.readBoolean();
     }
 
     @Override
@@ -542,6 +552,7 @@
         for (int i = 0; i < userDisabledHdrTypes.length; i++) {
             dest.writeInt(userDisabledHdrTypes[i]);
         }
+        dest.writeBoolean(shouldConstrainMetricsForLauncher);
     }
 
     @Override
@@ -796,6 +807,8 @@
         sb.append(brightnessMaximum);
         sb.append(", brightnessDefault ");
         sb.append(brightnessDefault);
+        sb.append(", shouldConstrainMetricsForLauncher ");
+        sb.append(shouldConstrainMetricsForLauncher);
         sb.append("}");
         return sb.toString();
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 48ef27f..a4e7a43 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,6 +33,7 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.RenderNode;
@@ -237,15 +238,6 @@
             new SurfaceControl.Transaction();
 
     /**
-     * Transaction that should be used for
-     * {@link RenderNode.PositionUpdateListener#positionChanged(long, int, int, int, int)}
-     * The callback is invoked from a thread pool so it's not thread safe with other render thread
-     * transactions. Keep the transactions for position changed callbacks on its own transaction.
-     */
-    private final SurfaceControl.Transaction mPositionChangedTransaction =
-            new SurfaceControl.Transaction();
-
-    /**
      * A temporary transaction holder that should only be used when applying right away. There
      * should be no assumption about thread safety for this transaction.
      */
@@ -295,7 +287,6 @@
             int defStyleRes, boolean disableBackgroundLayer) {
         super(context, attrs, defStyleAttr, defStyleRes);
         mUseBlastAdapter = useBlastAdapter(context);
-        mRenderNode.addPositionUpdateListener(mPositionListener);
 
         setWillNotDraw(true);
         mDisableBackgroundLayer = disableBackgroundLayer;
@@ -943,6 +934,24 @@
         }
     }
 
+
+    // The position update listener is used to safely share the surface size between render thread
+    // workers and the UI thread. Both threads need to know the surface size to determine the scale.
+    // The parent layer scales the surface size to view size. The child (BBQ) layer scales
+    // the buffer to the surface size. Both scales along with the window crop must be applied
+    // synchronously otherwise we may see flickers.
+    // When the listener is updated, we will get at least a single position update call so we can
+    // guarantee any changes we post will be applied.
+    private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight,
+            @Nullable Transaction geometryTransaction) {
+        if (mPositionListener != null) {
+            mRenderNode.removePositionUpdateListener(mPositionListener);
+        }
+        mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight,
+                geometryTransaction);
+        mRenderNode.addPositionUpdateListener(mPositionListener);
+    }
+
     private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
             boolean creating, boolean sizeChanged, boolean hintChanged) {
         boolean realSizeChanged = false;
@@ -985,13 +994,13 @@
             // While creating the surface, we will set it's initial
             // geometry. Outside of that though, we should generally
             // leave it to the RenderThread.
-            //
-            // There is one more case when the buffer size changes we aren't yet
-            // prepared to sync (as even following the transaction applying
-            // we still need to latch a buffer).
-            // b/28866173
-            if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
-                onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+            Transaction geometryTransaction = new Transaction();
+            geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+            if ((sizeChanged || hintChanged) && !creating) {
+                setBufferSize(geometryTransaction);
+            }
+            if (sizeChanged || creating || !isHardwareAccelerated()) {
+                onSetSurfacePositionAndScaleRT(geometryTransaction, mSurfaceControl,
                         mScreenRect.left, /*positionLeft*/
                         mScreenRect.top /*positionTop*/ ,
                         mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
@@ -1002,17 +1011,31 @@
                 // use SCALING_MODE_SCALE and submit a larger size than the surface
                 // size.
                 if (mClipSurfaceToBounds && mClipBounds != null) {
-                    mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+                    geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
                 } else {
-                    mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+                    geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                             mSurfaceHeight);
                 }
-            }
-            mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
-            if ((sizeChanged || hintChanged) && !creating) {
-                setBufferSize(mTmpTransaction);
-            }
 
+                boolean applyChangesOnRenderThread =
+                        sizeChanged && !creating && isHardwareAccelerated();
+                if (isHardwareAccelerated()) {
+                    // This will consume the passed in transaction and the transaction will be
+                    // applied on a render worker thread.
+                    replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight,
+                            applyChangesOnRenderThread ? geometryTransaction : null);
+                }
+                if (DEBUG_POSITION) {
+                    Log.d(TAG, String.format(
+                            "%d updateSurfacePosition %s"
+                                + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+                            System.identityHashCode(this),
+                            applyChangesOnRenderThread ? "RenderWorker" : "UiThread",
+                            mScreenRect.left, mScreenRect.top, mScreenRect.right,
+                            mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
+                }
+            }
+            mTmpTransaction.merge(geometryTransaction);
             mTmpTransaction.apply();
             updateEmbeddedAccessibilityMatrix();
 
@@ -1399,19 +1422,6 @@
         mTmpTransaction.apply();
     }
 
-    private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
-            Rect position) {
-        onSetSurfacePositionAndScaleRT(t, surface,
-                position.left /*positionLeft*/,
-                position.top /*positionTop*/,
-                position.width() / (float) mSurfaceWidth /*postScaleX*/,
-                position.height() / (float) mSurfaceHeight /*postScaleY*/);
-
-        if (mViewVisibility) {
-            t.show(surface);
-        }
-    }
-
     /**
      * @return The last render position of the backing surface or an empty rect.
      *
@@ -1421,13 +1431,6 @@
         return mRTLastReportedPosition;
     }
 
-    private void setParentSpaceRectangle(Rect position, long frameNumber, Transaction t) {
-        final ViewRootImpl viewRoot = getViewRootImpl();
-        applySurfaceTransforms(mSurfaceControl, t, position);
-        applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber);
-        applyOrMergeTransaction(t, frameNumber);
-    }
-
     private void applyOrMergeTransaction(Transaction t, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
         boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
@@ -1440,9 +1443,24 @@
     }
 
     private Rect mRTLastReportedPosition = new Rect();
+    private Point mRTLastReportedSurfaceSize = new Point();
 
-    private RenderNode.PositionUpdateListener mPositionListener =
-            new RenderNode.PositionUpdateListener() {
+    private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
+        int mRtSurfaceWidth = -1;
+        int mRtSurfaceHeight = -1;
+        private final SurfaceControl.Transaction mPositionChangedTransaction =
+                new SurfaceControl.Transaction();
+        boolean mPendingTransaction = false;
+
+        SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight,
+                @Nullable Transaction t) {
+            mRtSurfaceWidth = surfaceWidth;
+            mRtSurfaceHeight = surfaceHeight;
+            if (t != null) {
+                mPositionChangedTransaction.merge(t);
+                mPendingTransaction = true;
+            }
+        }
 
         @Override
         public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
@@ -1464,21 +1482,34 @@
             if (mRTLastReportedPosition.left == left
                     && mRTLastReportedPosition.top == top
                     && mRTLastReportedPosition.right == right
-                    && mRTLastReportedPosition.bottom == bottom) {
+                    && mRTLastReportedPosition.bottom == bottom
+                    && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
+                    && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight
+                    && !mPendingTransaction) {
                 return;
             }
             try {
                 if (DEBUG_POSITION) {
                     Log.d(TAG, String.format(
                             "%d updateSurfacePosition RenderWorker, frameNr = %d, "
-                                    + "position = [%d, %d, %d, %d]",
-                            System.identityHashCode(this), frameNumber,
-                            left, top, right, bottom));
+                                    + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+                            System.identityHashCode(SurfaceView.this), frameNumber,
+                            left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight));
                 }
                 mRTLastReportedPosition.set(left, top, right, bottom);
-                setParentSpaceRectangle(mRTLastReportedPosition, frameNumber,
-                        mPositionChangedTransaction);
-                // Now overwrite mRTLastReportedPosition with our values
+                mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
+                onSetSurfacePositionAndScaleRT(mPositionChangedTransaction, mSurfaceControl,
+                        mRTLastReportedPosition.left /*positionLeft*/,
+                        mRTLastReportedPosition.top /*positionTop*/,
+                        mRTLastReportedPosition.width() / (float) mRtSurfaceWidth /*postScaleX*/,
+                        mRTLastReportedPosition.height() / (float) mRtSurfaceHeight /*postScaleY*/);
+                if (mViewVisibility) {
+                    mPositionChangedTransaction.show(mSurfaceControl);
+                }
+                applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
+                        getViewRootImpl().mSurface, frameNumber);
+                applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
+                mPendingTransaction = false;
             } catch (Exception ex) {
                 Log.e(TAG, "Exception from repositionChild", ex);
             }
@@ -1502,7 +1533,13 @@
                         System.identityHashCode(this), frameNumber));
             }
             mRTLastReportedPosition.setEmpty();
-
+            mRTLastReportedSurfaceSize.set(-1, -1);
+            if (mPendingTransaction) {
+                Log.w(TAG, System.identityHashCode(SurfaceView.this)
+                        + "Pending transaction cleared.");
+                mPositionChangedTransaction.clear();
+                mPendingTransaction = false;
+            }
             if (mSurfaceControl == null) {
                 return;
             }
@@ -1521,7 +1558,9 @@
                 mRtHandlingPositionUpdates = false;
             }
         }
-    };
+    }
+
+    private SurfaceViewPositionUpdateListener mPositionListener = null;
 
     private SurfaceHolder.Callback[] getSurfaceCallbacks() {
         SurfaceHolder.Callback[] callbacks;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f3ebe5b..ffc98d2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -19816,6 +19816,9 @@
     /**
      * Check if this view can be scrolled horizontally in a certain direction.
      *
+     * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+     * in response to user input or not.
+     *
      * @param direction Negative to check scrolling left, positive to check scrolling right.
      * @return true if this view can be scrolled in the specified direction, false otherwise.
      */
@@ -19833,6 +19836,9 @@
     /**
      * Check if this view can be scrolled vertically in a certain direction.
      *
+     * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+     * in response to user input or not.
+     *
      * @param direction Negative to check scrolling up, positive to check scrolling down.
      * @return true if this view can be scrolled in the specified direction, false otherwise.
      */
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 5f036a3..5185dc2 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -843,9 +843,14 @@
     /**
      * Called back when the connected IME switches between fullscreen and normal modes.
      *
-     * <p>Note: On {@link android.os.Build.VERSION_CODES#O} and later devices, input methods are no
-     * longer allowed to directly call this method at any time. To signal this event in the target
-     * application, input methods should always call
+     * <p><p><strong>Editor authors:</strong> There is a bug on
+     * {@link android.os.Build.VERSION_CODES#O} and later devices that this method is called back
+     * on the main thread even when {@link #getHandler()} is overridden.  This bug is fixed in
+     * {@link android.os.Build.VERSION_CODES#TIRAMISU}.</p>
+     *
+     * <p><p><strong>IME authors:</strong> On {@link android.os.Build.VERSION_CODES#O} and later
+     * devices, input methods are no longer allowed to directly call this method at any time.
+     * To signal this event in the target application, input methods should always call
      * {@link InputMethodService#updateFullscreenMode()} instead. This approach should work on API
      * {@link android.os.Build.VERSION_CODES#N_MR1} and prior devices.</p>
      *
@@ -927,14 +932,20 @@
     boolean requestCursorUpdates(int cursorUpdateMode);
 
     /**
-     * Called by the {@link InputMethodManager} to enable application developers to specify a
-     * dedicated {@link Handler} on which incoming IPC method calls from input methods will be
-     * dispatched.
+     * Called by the system to enable application developers to specify a dedicated thread on which
+     * {@link InputConnection} methods are called back.
      *
-     * <p>Note: This does nothing when called from input methods.</p>
+     * <p><strong>Editor authors</strong>: although you can return your custom subclasses of
+     * {@link Handler}, the system only uses {@link android.os.Looper} returned from
+     * {@link Handler#getLooper()}.  You cannot intercept or cancel {@link InputConnection}
+     * callbacks by implementing this method.</p>
+     *
+     * <p><strong>IME authors</strong>: This method is not intended to be called from the IME.  You
+     * will always receive {@code null}.</p>
      *
      * @return {@code null} to use the default {@link Handler}.
      */
+    @Nullable
     Handler getHandler();
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c023c6e..ab7e5a9 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -950,15 +950,15 @@
                 }
                 case MSG_REPORT_FULLSCREEN_MODE: {
                     final boolean fullscreen = msg.arg1 != 0;
-                    InputConnection ic = null;
+                    RemoteInputConnectionImpl ic = null;
                     synchronized (mH) {
                         if (mFullscreenMode != fullscreen && mServedInputConnection != null) {
-                            ic = mServedInputConnection.getInputConnection();
+                            ic = mServedInputConnection;
                             mFullscreenMode = fullscreen;
                         }
                     }
                     if (ic != null) {
-                        ic.reportFullscreenMode(fullscreen);
+                        ic.dispatchReportFullscreenMode(fullscreen);
                     }
                     return;
                 }
@@ -1381,8 +1381,7 @@
     public boolean isAcceptingText() {
         checkFocus();
         synchronized (mH) {
-            return mServedInputConnection != null
-                    && mServedInputConnection.getInputConnection() != null;
+            return mServedInputConnection != null && !mServedInputConnection.isFinished();
         }
     }
 
diff --git a/core/java/android/view/translation/Translator.java b/core/java/android/view/translation/Translator.java
index edd0d16..606f39d 100644
--- a/core/java/android/view/translation/Translator.java
+++ b/core/java/android/view/translation/Translator.java
@@ -18,6 +18,7 @@
 
 import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
 import static android.view.translation.TranslationManager.SYNC_CALLS_TIMEOUT_MS;
+import static android.view.translation.UiTranslationController.DEBUG;
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
@@ -38,7 +39,6 @@
 import com.android.internal.os.IResultReceiver;
 
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -395,27 +395,26 @@
 
     private static class TranslationResponseCallbackImpl extends ITranslationCallback.Stub {
 
-        private final WeakReference<Consumer<TranslationResponse>> mCallback;
-        private final WeakReference<Executor> mExecutor;
+        private final Consumer<TranslationResponse> mCallback;
+        private final Executor mExecutor;
 
         TranslationResponseCallbackImpl(Consumer<TranslationResponse> callback, Executor executor) {
-            mCallback = new WeakReference<>(callback);
-            mExecutor = new WeakReference<>(executor);
+            mCallback = callback;
+            mExecutor = executor;
         }
 
         @Override
         public void onTranslationResponse(TranslationResponse response) throws RemoteException {
-            final Consumer<TranslationResponse> callback = mCallback.get();
+            if (DEBUG) {
+                Log.i(TAG, "onTranslationResponse called.");
+            }
             final Runnable runnable =
-                    () -> callback.accept(response);
-            if (callback != null) {
-                final Executor executor = mExecutor.get();
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    executor.execute(runnable);
-                } finally {
-                    restoreCallingIdentity(token);
-                }
+                    () -> mCallback.accept(response);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(runnable);
+            } finally {
+                restoreCallingIdentity(token);
             }
         }
     }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 91fc5a5..e827f0a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -5824,25 +5824,6 @@
         return false;
     }
 
-    /** @hide */
-    public void updateAppInfo(@NonNull ApplicationInfo info) {
-        if (mApplication != null && mApplication.sourceDir.equals(info.sourceDir)) {
-            // Overlay paths are generated against a particular version of an application.
-            // The overlays paths of a newly upgraded application are incompatible with the
-            // old version of the application.
-            mApplication = info;
-        }
-        if (hasSizedRemoteViews()) {
-            for (RemoteViews layout : mSizedRemoteViews) {
-                layout.updateAppInfo(info);
-            }
-        }
-        if (hasLandscapeAndPortraitLayouts()) {
-            mLandscape.updateAppInfo(info);
-            mPortrait.updateAppInfo(info);
-        }
-    }
-
     private Context getContextForResources(Context context) {
         if (mApplication != null) {
             if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index b7de7b8..1c5b39e 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -23,6 +23,7 @@
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_NONE;
@@ -94,8 +95,16 @@
     /** The container can show on top of lock screen. */
     public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6;
 
+    /**
+     * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is
+     * used to prevent seamless rotation.
+     * TODO(b/194540864): Once we can include all windows in transition, then replace this with
+     *         something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations.
+     */
+    public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7;
+
     /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
-    public static final int FLAG_FIRST_CUSTOM = 1 << 7;
+    public static final int FLAG_FIRST_CUSTOM = 1 << 8;
 
     /** @hide */
     @IntDef(prefix = { "FLAG_" }, value = {
@@ -107,6 +116,7 @@
             FLAG_IS_VOICE_INTERACTION,
             FLAG_IS_DISPLAY,
             FLAG_OCCLUDES_KEYGUARD,
+            FLAG_DISPLAY_HAS_ALERT_WINDOWS,
             FLAG_FIRST_CUSTOM
     })
     public @interface ChangeFlags {}
@@ -209,6 +219,10 @@
         return mOptions;
     }
 
+    /**
+     * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom
+     *         in Z (meaning index 0 is the top-most container).
+     */
     @NonNull
     public List<Change> getChanges() {
         return mChanges;
@@ -290,6 +304,9 @@
         if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) {
             sb.append((sb.length() == 0 ? "" : "|") + "OCCLUDES_KEYGUARD");
         }
+        if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+            sb.append((sb.length() == 0 ? "" : "|") + "DISPLAY_HAS_ALERT_WINDOWS");
+        }
         if ((flags & FLAG_FIRST_CUSTOM) != 0) {
             sb.append((sb.length() == 0 ? "" : "|") + "FIRST_CUSTOM");
         }
@@ -337,6 +354,7 @@
         private ActivityManager.RunningTaskInfo mTaskInfo = null;
         private int mStartRotation = ROTATION_UNDEFINED;
         private int mEndRotation = ROTATION_UNDEFINED;
+        private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
 
         public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
             mContainer = container;
@@ -356,6 +374,7 @@
             mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
             mStartRotation = in.readInt();
             mEndRotation = in.readInt();
+            mRotationAnimation = in.readInt();
         }
 
         /** Sets the parent of this change's container. The parent must be a participant or null. */
@@ -402,6 +421,14 @@
             mEndRotation = end;
         }
 
+        /**
+         * Sets the app-requested animation type for rotation. Will be one of the
+         * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams};
+         */
+        public void setRotationAnimation(int anim) {
+            mRotationAnimation = anim;
+        }
+
         /** @return the container that is changing. May be null if non-remotable (eg. activity) */
         @Nullable
         public WindowContainerToken getContainer() {
@@ -473,6 +500,11 @@
             return mEndRotation;
         }
 
+        /** @return the rotation animation. */
+        public int getRotationAnimation() {
+            return mRotationAnimation;
+        }
+
         /** @hide */
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -487,6 +519,7 @@
             dest.writeTypedObject(mTaskInfo, flags);
             dest.writeInt(mStartRotation);
             dest.writeInt(mEndRotation);
+            dest.writeInt(mRotationAnimation);
         }
 
         @NonNull
@@ -514,7 +547,7 @@
             return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
                     + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
                     + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
-                    + mStartRotation + "->" + mEndRotation + "}";
+                    + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + "}";
         }
     }
 
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index d1bca85..2d44054 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -86,13 +86,17 @@
      * @return {@link InputConnection} to which incoming IPCs will be dispatched.
      */
     @Nullable
-    public InputConnection getInputConnection() {
+    private InputConnection getInputConnection() {
         synchronized (mLock) {
             return mInputConnection;
         }
     }
 
-    private boolean isFinished() {
+    /**
+     * @return {@code true} until the target {@link InputConnection} receives
+     * {@link InputConnection#closeConnection()} as a result of {@link #deactivate()}.
+     */
+    public boolean isFinished() {
         synchronized (mLock) {
             return mFinished;
         }
@@ -169,6 +173,23 @@
         }
     }
 
+    /**
+     * Invoke {@link InputConnection#reportFullscreenMode(boolean)} or schedule it on the target
+     * thread associated with {@link InputConnection#getHandler()}.
+     *
+     * @param enabled the parameter to be passed to
+     *                {@link InputConnection#reportFullscreenMode(boolean)}.
+     */
+    public void dispatchReportFullscreenMode(boolean enabled) {
+        dispatch(() -> {
+            final InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                return;
+            }
+            ic.reportFullscreenMode(enabled);
+        });
+    }
+
     @Override
     public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
         dispatch(() -> {
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a6d038d..8a1f1a0 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2432,6 +2432,12 @@
     return (jint)nativeToJavaStatus(status);
 }
 
+static jint android_media_AudioSystem_setHotwordDetectionServiceUid(JNIEnv *env, jobject thiz,
+                                                                    jint uid) {
+    status_t status = AudioSystem::setHotwordDetectionServiceUid(uid);
+    return (jint)nativeToJavaStatus(status);
+}
+
 static jint
 android_media_AudioSystem_setA11yServicesUids(JNIEnv *env, jobject thiz, jintArray uids) {
     std::vector<uid_t> nativeUidsVector;
@@ -2804,6 +2810,8 @@
          {"setSurroundFormatEnabled", "(IZ)I",
           (void *)android_media_AudioSystem_setSurroundFormatEnabled},
          {"setAssistantUid", "(I)I", (void *)android_media_AudioSystem_setAssistantUid},
+         {"setHotwordDetectionServiceUid", "(I)I",
+          (void *)android_media_AudioSystem_setHotwordDetectionServiceUid},
          {"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
          {"isHapticPlaybackSupported", "()Z",
           (void *)android_media_AudioSystem_isHapticPlaybackSupported},
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5245437..4b1c544 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1938,7 +1938,7 @@
     <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-Warnung"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeitsprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Gewarnt"</string>
-    <string name="notification_verified_content_description" msgid="6401483602782359391">"Bestätigt"</string>
+    <string name="notification_verified_content_description" msgid="6401483602782359391">"Verifiziert"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Maximieren"</string>
     <string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Minimieren"</string>
     <string name="expand_action_accessibility" msgid="1947657036871746627">"Maximierung ein-/auschalten"</string>
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index 4925209..872331c 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -67,7 +67,7 @@
 
     @NonNull RippleAnimationSession enter(Canvas canvas) {
         mStartTime = AnimationUtils.currentAnimationTimeMillis();
-        if (isHwAccelerated(canvas)) {
+        if (useRTAnimations(canvas)) {
             enterHardware((RecordingCanvas) canvas);
         } else {
             enterSoftware();
@@ -82,7 +82,7 @@
     }
 
     @NonNull RippleAnimationSession exit(Canvas canvas) {
-        if (isHwAccelerated(canvas)) exitHardware((RecordingCanvas) canvas);
+        if (useRTAnimations(canvas)) exitHardware((RecordingCanvas) canvas);
         else exitSoftware();
         return this;
     }
@@ -102,8 +102,12 @@
         return this;
     }
 
-    private boolean isHwAccelerated(Canvas canvas) {
-        return canvas.isHardwareAccelerated() && !mForceSoftware;
+    private boolean useRTAnimations(Canvas canvas) {
+        if (mForceSoftware) return false;
+        if (!canvas.isHardwareAccelerated()) return false;
+        RecordingCanvas hwCanvas = (RecordingCanvas) canvas;
+        if (hwCanvas.mNode == null || !hwCanvas.mNode.isAttached()) return false;
+        return true;
     }
 
     private void exitSoftware() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index d3cff5c..7354c90 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -49,7 +49,9 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.os.Build;
+import android.os.Looper;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.animation.AnimationUtils;
 import android.view.animation.LinearInterpolator;
 
@@ -113,6 +115,7 @@
  * @attr ref android.R.styleable#RippleDrawable_color
  */
 public class RippleDrawable extends LayerDrawable {
+    private static final String TAG = "RippleDrawable";
     /**
      * Radius value that specifies the ripple radius should be computed based
      * on the size of the ripple's container.
@@ -848,6 +851,10 @@
 
     private void startBackgroundAnimation() {
         mRunBackgroundAnimation = false;
+        if (Looper.myLooper() == null) {
+            Log.w(TAG, "Thread doesn't have a looper. Skipping animation.");
+            return;
+        }
         mBackgroundAnimation = ValueAnimator.ofFloat(mBackgroundOpacity, mTargetBackgroundOpacity);
         mBackgroundAnimation.setInterpolator(LINEAR_INTERPOLATOR);
         mBackgroundAnimation.setDuration(BACKGROUND_OPACITY_DURATION);
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 624b8b3..c2b6ffb 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -31,7 +31,7 @@
     <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"స్టాచ్"</string>
     <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ఆన్‌స్టాచ్"</string>
     <string name="dock_forced_resizable" msgid="1749750436092293116">"స్క్రీన్ విభజనతో యాప్‌ పని చేయకపోవచ్చు."</string>
-    <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"యాప్‌లో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
     <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్‌ప్లేలో యాప్ పని చేయకపోవచ్చు."</string>
     <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్‌ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string>
     <string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index d1fbf31..9bbede3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -24,6 +24,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.annotations.ExternalThread;
 import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
 import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
 import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -47,6 +48,7 @@
     private final Optional<AppPairsController> mAppPairsOptional;
     private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
     private final FullscreenTaskListener mFullscreenTaskListener;
+    private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
     private final ShellExecutor mMainExecutor;
     private final Transitions mTransitions;
     private final StartingWindowController mStartingWindow;
@@ -62,6 +64,7 @@
             Optional<AppPairsController> appPairsOptional,
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             FullscreenTaskListener fullscreenTaskListener,
+            Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional,
             Transitions transitions,
             StartingWindowController startingWindow,
             ShellExecutor mainExecutor) {
@@ -74,6 +77,7 @@
         mAppPairsOptional = appPairsOptional;
         mFullscreenTaskListener = fullscreenTaskListener;
         mPipTouchHandlerOptional = pipTouchHandlerOptional;
+        mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f);
         mTransitions = transitions;
         mMainExecutor = mainExecutor;
         mStartingWindow = startingWindow;
@@ -108,6 +112,11 @@
         // controller instead of the feature interface, can just initialize the touch handler if
         // needed
         mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
+
+        // Initialize optional freeform
+        mFreeformTaskListenerOptional.ifPresent(f ->
+                mShellTaskOrganizer.addListenerForType(
+                        f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
     }
 
     @ExternalThread
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index ba0ab6d..ab8a21c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -71,12 +71,14 @@
     public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
     public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
     public static final int TASK_LISTENER_TYPE_PIP = -4;
+    public static final int TASK_LISTENER_TYPE_FREEFORM = -5;
 
     @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
             TASK_LISTENER_TYPE_UNDEFINED,
             TASK_LISTENER_TYPE_FULLSCREEN,
             TASK_LISTENER_TYPE_MULTI_WINDOW,
             TASK_LISTENER_TYPE_PIP,
+            TASK_LISTENER_TYPE_FREEFORM,
     })
     public @interface TaskListenerType {}
 
@@ -572,6 +574,7 @@
             case WINDOWING_MODE_PINNED:
                 return TASK_LISTENER_TYPE_PIP;
             case WINDOWING_MODE_FREEFORM:
+                return TASK_LISTENER_TYPE_FREEFORM;
             case WINDOWING_MODE_UNDEFINED:
             default:
                 return TASK_LISTENER_TYPE_UNDEFINED;
@@ -586,6 +589,8 @@
                 return "TASK_LISTENER_TYPE_MULTI_WINDOW";
             case TASK_LISTENER_TYPE_PIP:
                 return "TASK_LISTENER_TYPE_PIP";
+            case TASK_LISTENER_TYPE_FREEFORM:
+                return "TASK_LISTENER_TYPE_FREEFORM";
             case TASK_LISTENER_TYPE_UNDEFINED:
                 return "TASK_LISTENER_TYPE_UNDEFINED";
             default:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index b7235a3..b90283f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -82,6 +82,9 @@
     private boolean mHasNavigationBar = false;
     private boolean mHasStatusBar = false;
     private int mNavBarFrameHeight = 0;
+    private boolean mAllowSeamlessRotationDespiteNavBarMoving = false;
+    private boolean mNavigationBarCanMove = false;
+    private boolean mReverseDefaultRotation = false;
 
     @Override
     public boolean equals(Object o) {
@@ -98,6 +101,10 @@
                 && Objects.equals(mStableInsets, other.mStableInsets)
                 && mHasNavigationBar == other.mHasNavigationBar
                 && mHasStatusBar == other.mHasStatusBar
+                && mAllowSeamlessRotationDespiteNavBarMoving
+                        == other.mAllowSeamlessRotationDespiteNavBarMoving
+                && mNavigationBarCanMove == other.mNavigationBarCanMove
+                && mReverseDefaultRotation == other.mReverseDefaultRotation
                 && mNavBarFrameHeight == other.mNavBarFrameHeight;
     }
 
@@ -105,7 +112,8 @@
     public int hashCode() {
         return Objects.hash(mUiMode, mWidth, mHeight, mCutout, mRotation, mDensityDpi,
                 mNonDecorInsets, mStableInsets, mHasNavigationBar, mHasStatusBar,
-                mNavBarFrameHeight);
+                mNavBarFrameHeight, mAllowSeamlessRotationDespiteNavBarMoving,
+                mNavigationBarCanMove, mReverseDefaultRotation);
     }
 
     /**
@@ -150,6 +158,9 @@
         mDensityDpi = dl.mDensityDpi;
         mHasNavigationBar = dl.mHasNavigationBar;
         mHasStatusBar = dl.mHasStatusBar;
+        mAllowSeamlessRotationDespiteNavBarMoving = dl.mAllowSeamlessRotationDespiteNavBarMoving;
+        mNavigationBarCanMove = dl.mNavigationBarCanMove;
+        mReverseDefaultRotation = dl.mReverseDefaultRotation;
         mNavBarFrameHeight = dl.mNavBarFrameHeight;
         mNonDecorInsets.set(dl.mNonDecorInsets);
         mStableInsets.set(dl.mStableInsets);
@@ -165,6 +176,10 @@
         mDensityDpi = info.logicalDensityDpi;
         mHasNavigationBar = hasNavigationBar;
         mHasStatusBar = hasStatusBar;
+        mAllowSeamlessRotationDespiteNavBarMoving = res.getBoolean(
+            R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
+        mNavigationBarCanMove = res.getBoolean(R.bool.config_navBarCanMove);
+        mReverseDefaultRotation = res.getBoolean(R.bool.config_reverseDefaultRotation);
         recalcInsets(res);
     }
 
@@ -249,6 +264,28 @@
         return mNavBarFrameHeight;
     }
 
+    /** @return whether we can seamlessly rotate even if nav-bar can change sides. */
+    public boolean allowSeamlessRotationDespiteNavBarMoving() {
+        return mAllowSeamlessRotationDespiteNavBarMoving;
+    }
+
+    /** @return whether the navigation bar will change sides during rotation. */
+    public boolean navigationBarCanMove() {
+        return mNavigationBarCanMove;
+    }
+
+    /** @return the rotation that would make the physical display "upside down". */
+    public int getUpsideDownRotation() {
+        boolean displayHardwareIsLandscape = mWidth > mHeight;
+        if ((mRotation % 2) != 0) {
+            displayHardwareIsLandscape = !displayHardwareIsLandscape;
+        }
+        if (displayHardwareIsLandscape) {
+            return mReverseDefaultRotation ? Surface.ROTATION_270 : Surface.ROTATION_90;
+        }
+        return Surface.ROTATION_180;
+    }
+
     /** Gets the orientation of this layout */
     public int getOrientation() {
         return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
new file mode 100644
index 0000000..5fb3297
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+import java.io.PrintWriter;
+
+/**
+ * {@link ShellTaskOrganizer.TaskListener} for {@link
+ * ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
+ */
+public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
+    private static final String TAG = "FreeformTaskListener";
+
+    private final SyncTransactionQueue mSyncQueue;
+
+    private final SparseArray<State> mTasks = new SparseArray<>();
+
+    private static class State {
+        RunningTaskInfo mTaskInfo;
+        SurfaceControl mLeash;
+    }
+
+    public FreeformTaskListener(SyncTransactionQueue syncQueue) {
+        mSyncQueue = syncQueue;
+    }
+
+    @Override
+    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+        if (mTasks.get(taskInfo.taskId) != null) {
+            throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
+        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
+                taskInfo.taskId);
+        final State state = new State();
+        state.mTaskInfo = taskInfo;
+        state.mLeash = leash;
+        mTasks.put(taskInfo.taskId, state);
+
+        final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+        mSyncQueue.runInSync(t -> {
+            Point taskPosition = taskInfo.positionInParent;
+            t.setPosition(leash, taskPosition.x, taskPosition.y)
+                    .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+                    .show(leash);
+        });
+    }
+
+    @Override
+    public void onTaskVanished(RunningTaskInfo taskInfo) {
+        State state = mTasks.get(taskInfo.taskId);
+        if (state == null) {
+            Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+            return;
+        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
+                taskInfo.taskId);
+        mTasks.remove(taskInfo.taskId);
+    }
+
+    @Override
+    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+        State state = mTasks.get(taskInfo.taskId);
+        if (state == null) {
+            throw new RuntimeException(
+                    "Task info changed before appearing: #" + taskInfo.taskId);
+        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
+                taskInfo.taskId);
+        state.mTaskInfo = taskInfo;
+
+        final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+        final SurfaceControl leash = state.mLeash;
+        mSyncQueue.runInSync(t -> {
+            Point taskPosition = taskInfo.positionInParent;
+            t.setPosition(leash, taskPosition.x, taskPosition.y)
+                    .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+                    .show(leash);
+        });
+    }
+
+    @Override
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + this);
+        pw.println(innerPrefix + mTasks.size() + " tasks");
+    }
+
+    @Override
+    public String toString() {
+        return TAG;
+    }
+
+    /**
+     * Checks if freeform support is enabled in system.
+     *
+     * @param context context used to check settings and package manager.
+     * @return {@code true} if freeform is enabled, {@code false} if not.
+     */
+    public static boolean isFreeformEnabled(Context context) {
+        return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
+                || Settings.Global.getInt(context.getContentResolver(),
+                DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
+    }
+
+    /**
+     * Creates {@link FreeformTaskListener} if freeform is enabled.
+     */
+    public static FreeformTaskListener create(Context context,
+            SyncTransactionQueue syncQueue) {
+        if (!isFreeformEnabled(context)) {
+            return null;
+        }
+
+        return new FreeformTaskListener(syncQueue);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 21bc889..ff333c8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -130,7 +130,7 @@
      */
     public boolean getSettingsTapsAppToExit(ContentResolver resolver, int userId) {
         return Settings.Secure.getIntForUser(resolver,
-                Settings.Secure.TAPS_APP_TO_EXIT, 0, userId) == 1;
+                Settings.Secure.TAPS_APP_TO_EXIT, 1, userId) == 1;
     }
 
     /**
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 01134a7..b584038 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
@@ -23,6 +23,10 @@
 import static android.app.ActivityOptions.ANIM_SCALE_UP;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
@@ -31,8 +35,10 @@
 import static android.view.WindowManager.TRANSIT_RELAUNCH;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
 import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
@@ -68,9 +74,12 @@
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.AttributeCache;
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -97,6 +106,7 @@
             SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
 
     private final TransactionPool mTransactionPool;
+    private final DisplayController mDisplayController;
     private final Context mContext;
     private final ShellExecutor mMainExecutor;
     private final ShellExecutor mAnimExecutor;
@@ -114,8 +124,10 @@
 
     private ScreenRotationAnimation mRotationAnimation;
 
-    DefaultTransitionHandler(@NonNull TransactionPool transactionPool, Context context,
+    DefaultTransitionHandler(@NonNull DisplayController displayController,
+            @NonNull TransactionPool transactionPool, Context context,
             @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+        mDisplayController = displayController;
         mTransactionPool = transactionPool;
         mContext = context;
         mMainExecutor = mainExecutor;
@@ -126,6 +138,110 @@
         AttributeCache.init(context);
     }
 
+    @VisibleForTesting
+    static boolean isRotationSeamless(@NonNull TransitionInfo info,
+            DisplayController displayController) {
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                "Display is rotating, check if it should be seamless.");
+        boolean checkedDisplayLayout = false;
+        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+
+            // Only look at changing things. showing/hiding don't need to rotate.
+            if (change.getMode() != TRANSIT_CHANGE) continue;
+
+            // This container isn't rotating, so we can ignore it.
+            if (change.getEndRotation() == change.getStartRotation()) continue;
+
+            if ((change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+                // In the presence of System Alert windows we can not seamlessly rotate.
+                if ((change.getFlags() & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                            "  display has system alert windows, so not seamless.");
+                    return false;
+                }
+            } else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+                if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                            "  wallpaper is participating but isn't seamless.");
+                    return false;
+                }
+            } else if (change.getTaskInfo() != null) {
+                // We only enable seamless rotation if all the visible task windows requested it.
+                if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                            "  task %s isn't requesting seamless, so not seamless.",
+                            change.getTaskInfo().taskId);
+                    return false;
+                }
+
+                // This is the only way to get display-id currently, so we will check display
+                // capabilities here
+                if (!checkedDisplayLayout) {
+                    // only need to check display once.
+                    checkedDisplayLayout = true;
+                    final DisplayLayout displayLayout = displayController.getDisplayLayout(
+                            change.getTaskInfo().displayId);
+                    // For the upside down rotation we don't rotate seamlessly as the navigation
+                    // bar moves position. Note most apps (using orientation:sensor or user as
+                    // opposed to fullSensor) will not enter the reverse portrait orientation, so
+                    // actually the orientation won't change at all.
+                    int upsideDownRotation = displayLayout.getUpsideDownRotation();
+                    if (change.getStartRotation() == upsideDownRotation
+                            || change.getEndRotation() == upsideDownRotation) {
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                                "  rotation involves upside-down portrait, so not seamless.");
+                        return false;
+                    }
+
+                    // If the navigation bar can't change sides, then it will jump when we change
+                    // orientations and we don't rotate seamlessly - unless that is allowed, eg.
+                    // with gesture navigation where the navbar is low-profile enough that this
+                    // isn't very noticeable.
+                    if (!displayLayout.allowSeamlessRotationDespiteNavBarMoving()
+                            && (!(displayLayout.navigationBarCanMove()
+                                    && (change.getStartAbsBounds().width()
+                                            != change.getStartAbsBounds().height())))) {
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                                "  nav bar changes sides, so not seamless.");
+                        return false;
+                    }
+                }
+            }
+        }
+
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  Rotation IS seamless.");
+        return true;
+    }
+
+    /**
+     * Gets the rotation animation for the topmost task. Assumes that seamless is checked
+     * elsewhere, so it will default SEAMLESS to ROTATE.
+     */
+    private int getRotationAnimation(@NonNull TransitionInfo info) {
+        // Traverse in top-to-bottom order so that the first task is top-most
+        for (int i = 0; i < info.getChanges().size(); ++i) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+
+            // Only look at changing things. showing/hiding don't need to rotate.
+            if (change.getMode() != TRANSIT_CHANGE) continue;
+
+            // This container isn't rotating, so we can ignore it.
+            if (change.getEndRotation() == change.getStartRotation()) continue;
+
+            if (change.getTaskInfo() != null) {
+                final int anim = change.getRotationAnimation();
+                if (anim == ROTATION_ANIMATION_UNSPECIFIED
+                        // Fallback animation for seamless should also be default.
+                        || anim == ROTATION_ANIMATION_SEAMLESS) {
+                    return ROTATION_ANIMATION_ROTATE;
+                }
+                return anim;
+            }
+        }
+        return ROTATION_ANIMATION_ROTATE;
+    }
+
     @Override
     public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction startTransaction,
@@ -168,11 +284,15 @@
             if (info.getType() == TRANSIT_CHANGE && change.getMode() == TRANSIT_CHANGE
                     && (change.getEndRotation() != change.getStartRotation())
                     && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
-                mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
-                        mTransactionPool, startTransaction, change, info.getRootLeash());
-                mRotationAnimation.startAnimation(animations, onAnimFinish,
-                        mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
-                continue;
+                boolean isSeamless = isRotationSeamless(info, mDisplayController);
+                final int anim = getRotationAnimation(info);
+                if (!(isSeamless || anim == ROTATION_ANIMATION_JUMPCUT)) {
+                    mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
+                            mTransactionPool, startTransaction, change, info.getRootLeash());
+                    mRotationAnimation.startAnimation(animations, onAnimFinish,
+                            mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
+                    continue;
+                }
             }
 
             if (change.getMode() == TRANSIT_CHANGE) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 01ef2a6..09dfabf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -54,6 +54,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
@@ -113,15 +114,16 @@
     private final ArrayList<ActiveTransition> mActiveTransitions = new ArrayList<>();
 
     public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
-            @NonNull Context context, @NonNull ShellExecutor mainExecutor,
-            @NonNull ShellExecutor animExecutor) {
+            @NonNull DisplayController displayController, @NonNull Context context,
+            @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
         mOrganizer = organizer;
         mContext = context;
         mMainExecutor = mainExecutor;
         mAnimExecutor = animExecutor;
         mPlayerImpl = new TransitionPlayerImpl();
         // The very last handler (0 in the list) should be the default one.
-        mHandlers.add(new DefaultTransitionHandler(pool, context, mainExecutor, animExecutor));
+        mHandlers.add(new DefaultTransitionHandler(displayController, pool, context, mainExecutor,
+                animExecutor));
         // Next lowest priority is remote transitions.
         mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
         mHandlers.add(mRemoteTransitionHandler);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 21329c7..84565e5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -20,12 +20,18 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -49,6 +55,9 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.view.IDisplayWindowListener;
+import android.view.IWindowManager;
+import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.IRemoteTransition;
@@ -66,12 +75,15 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.wm.shell.TestShellExecutor;
+import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 
@@ -98,8 +110,7 @@
 
     @Test
     public void testBasicTransitionFlow() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         IBinder transitToken = new Binder();
@@ -118,8 +129,7 @@
 
     @Test
     public void testNonDefaultHandler() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final WindowContainerTransaction handlerWCT = new WindowContainerTransaction();
@@ -202,8 +212,7 @@
 
     @Test
     public void testRequestRemoteTransition() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
@@ -297,8 +306,7 @@
 
     @Test
     public void testRegisteredRemoteTransition() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
@@ -343,8 +351,7 @@
 
     @Test
     public void testOneShotRemoteHandler() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
@@ -390,8 +397,7 @@
 
     @Test
     public void testTransitionQueueing() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         IBinder transitToken1 = new Binder();
@@ -431,8 +437,7 @@
 
     @Test
     public void testTransitionMerging() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
-                mMainExecutor, mAnimExecutor);
+        Transitions transitions = createTestTransitions();
         mDefaultHandler.setSimulateMerge(true);
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
@@ -468,6 +473,63 @@
         assertEquals(0, mDefaultHandler.activeCount());
     }
 
+    @Test
+    public void testShouldRotateSeamlessly() throws Exception {
+        final RunningTaskInfo taskInfo =
+                createTaskInfo(1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final RunningTaskInfo taskInfoPip =
+                createTaskInfo(1, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+
+        final DisplayController displays = createTestDisplayController();
+        final @Surface.Rotation int upsideDown = displays
+                .getDisplayLayout(DEFAULT_DISPLAY).getUpsideDownRotation();
+
+        final TransitionInfo normalDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+                        .build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo).setRotate().build())
+                .build();
+        assertFalse(DefaultTransitionHandler.isRotationSeamless(normalDispRotate, displays));
+
+        // Seamless if all tasks are seamless
+        final TransitionInfo rotateSeamless = new TransitionInfoBuilder(TRANSIT_CHANGE)
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+                        .build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+                        .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+                .build();
+        assertTrue(DefaultTransitionHandler.isRotationSeamless(rotateSeamless, displays));
+
+        // Not seamless if there is PiP (or any other non-seamless task)
+        final TransitionInfo pipDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+                        .build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+                        .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfoPip)
+                        .setRotate().build())
+                .build();
+        assertFalse(DefaultTransitionHandler.isRotationSeamless(pipDispRotate, displays));
+
+        // Not seamless if one of rotations is upside-down
+        final TransitionInfo seamlessUpsideDown = new TransitionInfoBuilder(TRANSIT_CHANGE)
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
+                        .setRotate(upsideDown, ROTATION_ANIMATION_UNSPECIFIED).build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+                        .setRotate(upsideDown, ROTATION_ANIMATION_SEAMLESS).build())
+                .build();
+        assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessUpsideDown, displays));
+
+        // Not seamless if system alert windows
+        final TransitionInfo seamlessButAlert = new TransitionInfoBuilder(TRANSIT_CHANGE)
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(
+                        FLAG_IS_DISPLAY | FLAG_DISPLAY_HAS_ALERT_WINDOWS).setRotate().build())
+                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+                        .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+                .build();
+        assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessButAlert, displays));
+    }
+
     class TransitionInfoBuilder {
         final TransitionInfo mInfo;
 
@@ -490,11 +552,53 @@
             return addChange(mode, null /* taskInfo */);
         }
 
+        TransitionInfoBuilder addChange(TransitionInfo.Change change) {
+            mInfo.addChange(change);
+            return this;
+        }
+
         TransitionInfo build() {
             return mInfo;
         }
     }
 
+    class ChangeBuilder {
+        final TransitionInfo.Change mChange;
+
+        ChangeBuilder(@WindowManager.TransitionType int mode) {
+            mChange = new TransitionInfo.Change(null /* token */, null /* leash */);
+            mChange.setMode(mode);
+        }
+
+        ChangeBuilder setFlags(@TransitionInfo.ChangeFlags int flags) {
+            mChange.setFlags(flags);
+            return this;
+        }
+
+        ChangeBuilder setTask(RunningTaskInfo taskInfo) {
+            mChange.setTaskInfo(taskInfo);
+            return this;
+        }
+
+        ChangeBuilder setRotate(int anim) {
+            return setRotate(Surface.ROTATION_90, anim);
+        }
+
+        ChangeBuilder setRotate() {
+            return setRotate(ROTATION_ANIMATION_UNSPECIFIED);
+        }
+
+        ChangeBuilder setRotate(@Surface.Rotation int target, int anim) {
+            mChange.setRotation(Surface.ROTATION_0, target);
+            mChange.setRotationAnimation(anim);
+            return this;
+        }
+
+        TransitionInfo.Change build() {
+            return mChange;
+        }
+    }
+
     class TestTransitionHandler implements Transitions.TransitionHandler {
         ArrayList<Transitions.TransitionFinishCallback> mFinishes = new ArrayList<>();
         final ArrayList<IBinder> mMerged = new ArrayList<>();
@@ -566,4 +670,45 @@
         return taskInfo;
     }
 
+    private DisplayController createTestDisplayController() {
+        IWindowManager mockWM = mock(IWindowManager.class);
+        final IDisplayWindowListener[] displayListener = new IDisplayWindowListener[1];
+        try {
+            doAnswer(new Answer() {
+                @Override
+                public Object answer(InvocationOnMock invocation) {
+                    displayListener[0] = invocation.getArgument(0);
+                    return null;
+                }
+            }).when(mockWM).registerDisplayWindowListener(any());
+        } catch (RemoteException e) {
+            // No remote stuff happening, so this can't be hit
+        }
+        DisplayController out = new DisplayController(mContext, mockWM, mMainExecutor);
+        try {
+            displayListener[0].onDisplayAdded(DEFAULT_DISPLAY);
+            mMainExecutor.flushAll();
+        } catch (RemoteException e) {
+            // Again, no remote stuff
+        }
+        return out;
+    }
+
+    private Transitions createTestTransitions() {
+        return new Transitions(mOrganizer, mTransactionPool, createTestDisplayController(),
+                mContext, mMainExecutor, mAnimExecutor);
+    }
+//
+//    private class TestDisplayController extends DisplayController {
+//        private final DisplayLayout mTestDisplayLayout;
+//        TestDisplayController() {
+//            super(mContext, mock(IWindowManager.class), mMainExecutor);
+//            mTestDisplayLayout = new DisplayLayout();
+//            mTestDisplayLayout.
+//        }
+//
+//        @Override
+//        DisplayLayout
+//    }
+
 }
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index c827932..cb887f2 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -38,6 +38,17 @@
 
     public abstract void updateRingerModeAffectedStreamsInternal();
 
+    /**
+     * Notify the UID of the currently active {@link android.service.voice.HotwordDetectionService}.
+     *
+     * <p>The caller is expected to take care of any performance implications, e.g. by using a
+     * background thread to call this method.</p>
+     *
+     * @param uid UID of the currently active service or {@link android.os.Process#INVALID_UID} if
+     *            none.
+     */
+    public abstract void setHotwordDetectionServiceUid(int uid);
+
     public abstract void setAccessibilityServiceUids(IntArray uids);
 
     /**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 321db4e..5bd6891 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1769,6 +1769,13 @@
     public static native int setAssistantUid(int uid);
 
     /**
+     * Communicate UID of the current {@link android.service.voice.HotwordDetectionService} to audio
+     * policy service.
+     * @hide
+     */
+    public static native int setHotwordDetectionServiceUid(int uid);
+
+    /**
      * @hide
      * Communicate UIDs of active accessibility services to audio policy service.
      */
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 3b0f577..7c750ce 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -39,8 +39,8 @@
     ISession createSession(String packageName, in ISessionCallback sessionCb, String tag,
             in Bundle sessionInfo, int userId);
     List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
-    MediaSession.Token getMediaKeyEventSession();
-    String getMediaKeyEventSessionPackageName();
+    MediaSession.Token getMediaKeyEventSession(in ComponentName compName);
+    String getMediaKeyEventSessionPackageName(in ComponentName compName);
     void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
             boolean needWakeLock);
     boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
@@ -66,7 +66,8 @@
     void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
     void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
     void addOnMediaKeyEventSessionChangedListener(
-            in IOnMediaKeyEventSessionChangedListener listener);
+            in IOnMediaKeyEventSessionChangedListener listener,
+            in ComponentName notificationListener);
     void removeOnMediaKeyEventSessionChangedListener(
             in IOnMediaKeyEventSessionChangedListener listener);
     void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 269b70b..8e731a5 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -205,7 +205,28 @@
     @Nullable
     public MediaSession.Token getMediaKeyEventSession() {
         try {
-            return mService.getMediaKeyEventSession();
+            return mService.getMediaKeyEventSession(null);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to get media key event session", ex);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the media key event session, which would receive a media key event unless specified.
+     * <p>
+     * This requires that your app is an enabled notificationlistener using the
+     * {@link NotificationListenerService} APIs, in which case you must pass
+     * the {@link ComponentName} of your enabled listener.
+     *
+     * @return The media key event session, which would receive key events by default, unless
+     *          the caller has specified the target. Can be {@code null}.
+     */
+    @Nullable
+    public MediaSession.Token getMediaKeyEventSession(@NonNull ComponentName notificationListener) {
+        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+        try {
+            return mService.getMediaKeyEventSession(notificationListener);
         } catch (RemoteException ex) {
             Log.e(TAG, "Failed to get media key event session", ex);
         }
@@ -224,10 +245,34 @@
     @NonNull
     public String getMediaKeyEventSessionPackageName() {
         try {
-            String packageName = mService.getMediaKeyEventSessionPackageName();
+            String packageName = mService.getMediaKeyEventSessionPackageName(null);
             return (packageName != null) ? packageName : "";
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to get media key event session", ex);
+            Log.e(TAG, "Failed to get media key event session package name", ex);
+        }
+        return "";
+    }
+
+    /**
+     * Gets the package name of the media key event session.
+     * <p>
+     * This requires that your app is an enabled notificationlistener using the
+     * {@link NotificationListenerService} APIs, in which case you must pass
+     * the {@link ComponentName} of your enabled listener.
+     *
+     * @return The package name of the media key event session or the last session's media button
+     *          receiver if the media key event session is {@code null}. Returns an empty string
+     *          if neither of them exists.
+     * @see #getMediaKeyEventSession(ComponentName)
+     */
+    @NonNull
+    public String getMediaKeyEventSessionPackageName(@NonNull ComponentName notificationListener) {
+        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+        try {
+            String packageName = mService.getMediaKeyEventSessionPackageName(notificationListener);
+            return (packageName != null) ? packageName : "";
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to get media key event session package name", ex);
         }
         return "";
     }
@@ -905,44 +950,67 @@
     public void addOnMediaKeyEventSessionChangedListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnMediaKeyEventSessionChangedListener listener) {
+        addOnMediaKeyEventSessionChangedListenerInternal(null, executor, listener);
+    }
+
+    /**
+     * Add a listener to be notified when the media key session is changed.
+     * <p>
+     * This requires that your app is an enabled notificationlistener using the
+     * {@link NotificationListenerService} APIs, in which case you must pass
+     * the {@link ComponentName} of your enabled listener.
+     *
+     * @param notificationListener The enabled notification listener component.
+     * @param executor The executor on which the listener should be invoked.
+     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
+     */
+    public void addOnMediaKeyEventSessionChangedListener(
+            @NonNull ComponentName notificationListener,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnMediaKeyEventSessionChangedListener listener) {
+        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+        addOnMediaKeyEventSessionChangedListenerInternal(notificationListener, executor, listener);
+    }
+
+    private void addOnMediaKeyEventSessionChangedListenerInternal(
+            @Nullable ComponentName notificationListener,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnMediaKeyEventSessionChangedListener listener) {
         Objects.requireNonNull(executor, "executor shouldn't be null");
         Objects.requireNonNull(listener, "listener shouldn't be null");
         synchronized (mLock) {
             try {
+                if (mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
+                    mService.addOnMediaKeyEventSessionChangedListener(
+                            mOnMediaKeyEventSessionChangedListenerStub, notificationListener);
+                }
                 mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
                 executor.execute(
                         () -> listener.onMediaKeyEventSessionChanged(
                                 mCurMediaKeyEventSessionPackage, mCurMediaKeyEventSession));
-                if (mMediaKeyEventSessionChangedCallbacks.size() == 1) {
-                    mService.addOnMediaKeyEventSessionChangedListener(
-                            mOnMediaKeyEventSessionChangedListenerStub);
-                }
             } catch (RemoteException e) {
-                Log.e(TAG, "Failed to set media key listener", e);
+                Log.e(TAG, "Failed to add MediaKeyEventSessionChangedListener", e);
             }
         }
     }
 
     /**
-     * Remove a {@link OnMediaKeyEventSessionChangedListener}.
+     * Stop receiving updates on media key event session change on the specified listener.
      *
      * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
-     * @hide
      */
-    @SystemApi
-    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
     public void removeOnMediaKeyEventSessionChangedListener(
             @NonNull OnMediaKeyEventSessionChangedListener listener) {
         Objects.requireNonNull(listener, "listener shouldn't be null");
         synchronized (mLock) {
             try {
-                mMediaKeyEventSessionChangedCallbacks.remove(listener);
-                if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
+                if (mMediaKeyEventSessionChangedCallbacks.remove(listener) != null
+                        && mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
                     mService.removeOnMediaKeyEventSessionChangedListener(
                             mOnMediaKeyEventSessionChangedListenerStub);
                 }
             } catch (RemoteException e) {
-                Log.e(TAG, "Failed to set media key listener", e);
+                Log.e(TAG, "Failed to remove MediaKeyEventSessionChangedListener", e);
             }
         }
     }
@@ -1124,16 +1192,14 @@
     /**
      * Listener to receive changes in the media key event session, which would receive a media key
      * event unless specified.
-     * @hide
      */
-    @SystemApi
     public interface OnMediaKeyEventSessionChangedListener {
         /**
          * Called when the media key session is changed to the given media session. The key event
          * session is the media session which would receive key event by default, unless the caller
          * has specified the target.
          * <p>
-         * The session token can be {@link null} if the media button session is unset. In that case,
+         * The session token can be {@code null} if the media button session is unset. In that case,
          * packageName will return the package name of the last session's media button receiver, or
          * an empty string if the last session didn't set a media button receiver.
          *
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 0037b53..6a6a22c 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -20,7 +20,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.LnbEventType;
+import android.hardware.tv.tuner.LnbPosition;
+import android.hardware.tv.tuner.LnbTone;
+import android.hardware.tv.tuner.LnbVoltage;
 import android.media.tv.tuner.Tuner.Result;
 
 import java.lang.annotation.Retention;
@@ -48,39 +51,39 @@
     /**
      * LNB power voltage not set.
      */
-    public static final int VOLTAGE_NONE = Constants.LnbVoltage.NONE;
+    public static final int VOLTAGE_NONE = LnbVoltage.NONE;
     /**
      * LNB power voltage 5V.
      */
-    public static final int VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V;
+    public static final int VOLTAGE_5V = LnbVoltage.VOLTAGE_5V;
     /**
      * LNB power voltage 11V.
      */
-    public static final int VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V;
+    public static final int VOLTAGE_11V = LnbVoltage.VOLTAGE_11V;
     /**
      * LNB power voltage 12V.
      */
-    public static final int VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V;
+    public static final int VOLTAGE_12V = LnbVoltage.VOLTAGE_12V;
     /**
      * LNB power voltage 13V.
      */
-    public static final int VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V;
+    public static final int VOLTAGE_13V = LnbVoltage.VOLTAGE_13V;
     /**
      * LNB power voltage 14V.
      */
-    public static final int VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V;
+    public static final int VOLTAGE_14V = LnbVoltage.VOLTAGE_14V;
     /**
      * LNB power voltage 15V.
      */
-    public static final int VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V;
+    public static final int VOLTAGE_15V = LnbVoltage.VOLTAGE_15V;
     /**
      * LNB power voltage 18V.
      */
-    public static final int VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V;
+    public static final int VOLTAGE_18V = LnbVoltage.VOLTAGE_18V;
     /**
      * LNB power voltage 19V.
      */
-    public static final int VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
+    public static final int VOLTAGE_19V = LnbVoltage.VOLTAGE_19V;
 
     /** @hide */
     @IntDef(prefix = "TONE_",
@@ -91,11 +94,11 @@
     /**
      * LNB tone mode not set.
      */
-    public static final int TONE_NONE = Constants.LnbTone.NONE;
+    public static final int TONE_NONE = LnbTone.NONE;
     /**
      * LNB continuous tone mode.
      */
-    public static final int TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
+    public static final int TONE_CONTINUOUS = LnbTone.CONTINUOUS;
 
     /** @hide */
     @IntDef(prefix = "POSITION_",
@@ -106,15 +109,15 @@
     /**
      * LNB position is not defined.
      */
-    public static final int POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED;
+    public static final int POSITION_UNDEFINED = LnbPosition.UNDEFINED;
     /**
      * Position A of two-band LNBs
      */
-    public static final int POSITION_A = Constants.LnbPosition.POSITION_A;
+    public static final int POSITION_A = LnbPosition.POSITION_A;
     /**
      * Position B of two-band LNBs
      */
-    public static final int POSITION_B = Constants.LnbPosition.POSITION_B;
+    public static final int POSITION_B = LnbPosition.POSITION_B;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -126,22 +129,19 @@
     /**
      * Outgoing Diseqc message overflow.
      */
-    public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW =
-            Constants.LnbEventType.DISEQC_RX_OVERFLOW;
+    public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = LnbEventType.DISEQC_RX_OVERFLOW;
     /**
      * Outgoing Diseqc message isn't delivered on time.
      */
-    public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT =
-            Constants.LnbEventType.DISEQC_RX_TIMEOUT;
+    public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = LnbEventType.DISEQC_RX_TIMEOUT;
     /**
      * Incoming Diseqc message has parity error.
      */
-    public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR =
-            Constants.LnbEventType.DISEQC_RX_PARITY_ERROR;
+    public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = LnbEventType.DISEQC_RX_PARITY_ERROR;
     /**
      * LNB is overload.
      */
-    public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
+    public static final int EVENT_TYPE_LNB_OVERLOAD = LnbEventType.LNB_OVERLOAD;
 
     private static final String TAG = "Lnb";
 
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index a384bef..ed5e6ee 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -25,7 +25,9 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.Constant;
+import android.hardware.tv.tuner.Constant64Bit;
+import android.hardware.tv.tuner.FrontendScanType;
 import android.media.tv.TvInputService;
 import android.media.tv.tuner.dvr.DvrPlayback;
 import android.media.tv.tuner.dvr.DvrRecorder;
@@ -85,19 +87,19 @@
     /**
      * Invalid TS packet ID.
      */
-    public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+    public static final int INVALID_TS_PID = Constant.INVALID_TS_PID;
     /**
      * Invalid stream ID.
      */
-    public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+    public static final int INVALID_STREAM_ID = Constant.INVALID_STREAM_ID;
     /**
      * Invalid filter ID.
      */
-    public static final int INVALID_FILTER_ID = Constants.Constant.INVALID_FILTER_ID;
+    public static final int INVALID_FILTER_ID = Constant.INVALID_FILTER_ID;
     /**
      * Invalid AV Sync ID.
      */
-    public static final int INVALID_AV_SYNC_ID = Constants.Constant.INVALID_AV_SYNC_ID;
+    public static final int INVALID_AV_SYNC_ID = Constant.INVALID_AV_SYNC_ID;
     /**
      * Invalid timestamp.
      *
@@ -113,7 +115,7 @@
      * @see android.media.tv.tuner.filter.MmtpRecordEvent#getPts()
      */
     public static final long INVALID_TIMESTAMP =
-            android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
+            Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
     /**
      * Invalid mpu sequence number in MmtpRecordEvent.
      *
@@ -123,8 +125,7 @@
      * @see android.media.tv.tuner.filter.MmtpRecordEvent#getMpuSequenceNumber()
      */
     public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM =
-            android.hardware.tv.tuner.V1_1.Constants.Constant
-                    .INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
+            Constant.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
     /**
      * Invalid first macroblock address in MmtpRecordEvent and TsRecordEvent.
      *
@@ -135,7 +136,7 @@
      * @see android.media.tv.tuner.filter.TsRecordEvent#getMbInSlice()
      */
     public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
+            Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
     /**
      * Invalid local transport stream id.
      *
@@ -144,30 +145,26 @@
      *
      * @see #linkFrontendToCiCam(int)
      */
-    public static final int INVALID_LTS_ID =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LTS_ID;
+    public static final int INVALID_LTS_ID = Constant.INVALID_LTS_ID;
     /**
      * Invalid 64-bit filter ID.
      */
-    public static final long INVALID_FILTER_ID_LONG =
-            android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
+    public static final long INVALID_FILTER_ID_LONG = Constant64Bit.INVALID_FILTER_ID_64BIT;
     /**
      * Invalid frequency that is used as the default frontend frequency setting.
      */
     public static final int INVALID_FRONTEND_SETTING_FREQUENCY =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
+            Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
     /**
      * Invalid frontend id.
      */
-    public static final int INVALID_FRONTEND_ID =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_ID;
+    public static final int INVALID_FRONTEND_ID = Constant.INVALID_FRONTEND_ID;
     /**
      * Invalid LNB id.
      *
      * @hide
      */
-    public static final int INVALID_LNB_ID =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LNB_ID;
+    public static final int INVALID_LNB_ID = Constant.INVALID_LNB_ID;
     /**
      * A void key token. It is used to remove the current key from descrambler.
      *
@@ -175,8 +172,7 @@
      * to use this constant to remove current key before closing MediaCas session.
      */
     @NonNull
-    public static final byte[] VOID_KEYTOKEN =
-            {android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_KEYTOKEN};
+    public static final byte[] VOID_KEYTOKEN = {Constant.INVALID_KEYTOKEN};
 
     /** @hide */
     @IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
@@ -185,20 +181,20 @@
     /**
      * Scan type undefined.
      */
-    public static final int SCAN_TYPE_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+    public static final int SCAN_TYPE_UNDEFINED = FrontendScanType.SCAN_UNDEFINED;
     /**
      * Scan type auto.
      *
      * <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
      */
-    public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+    public static final int SCAN_TYPE_AUTO = FrontendScanType.SCAN_AUTO;
     /**
      * Blind scan.
      *
      * <p>Frequency range is not specified. The {@link android.media.tv.tuner.Tuner} will scan an
      * implementation specific range.
      */
-    public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+    public static final int SCAN_TYPE_BLIND = FrontendScanType.SCAN_BLIND;
 
 
     /** @hide */
@@ -210,31 +206,33 @@
     /**
      * Operation succeeded.
      */
-    public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+    public static final int RESULT_SUCCESS = android.hardware.tv.tuner.Result.SUCCESS;
     /**
      * Operation failed because the corresponding resources are not available.
      */
-    public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+    public static final int RESULT_UNAVAILABLE = android.hardware.tv.tuner.Result.UNAVAILABLE;
     /**
      * Operation failed because the corresponding resources are not initialized.
      */
-    public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+    public static final int RESULT_NOT_INITIALIZED =
+            android.hardware.tv.tuner.Result.NOT_INITIALIZED;
     /**
      * Operation failed because it's not in a valid state.
      */
-    public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+    public static final int RESULT_INVALID_STATE = android.hardware.tv.tuner.Result.INVALID_STATE;
     /**
      * Operation failed because there are invalid arguments.
      */
-    public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+    public static final int RESULT_INVALID_ARGUMENT =
+            android.hardware.tv.tuner.Result.INVALID_ARGUMENT;
     /**
      * Memory allocation failed.
      */
-    public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+    public static final int RESULT_OUT_OF_MEMORY = android.hardware.tv.tuner.Result.OUT_OF_MEMORY;
     /**
      * Operation failed due to unknown errors.
      */
-    public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
+    public static final int RESULT_UNKNOWN_ERROR = android.hardware.tv.tuner.Result.UNKNOWN_ERROR;
 
 
 
@@ -257,12 +255,12 @@
      * DVR for recording.
      * @hide
      */
-    public static final int DVR_TYPE_RECORD = Constants.DvrType.RECORD;
+    public static final int DVR_TYPE_RECORD = android.hardware.tv.tuner.DvrType.RECORD;
     /**
      * DVR for playback of recorded programs.
      * @hide
      */
-    public static final int DVR_TYPE_PLAYBACK = Constants.DvrType.PLAYBACK;
+    public static final int DVR_TYPE_PLAYBACK = android.hardware.tv.tuner.DvrType.PLAYBACK;
 
     static {
         try {
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index a13077c..3a15daf 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -17,7 +17,11 @@
 package android.media.tv.tuner;
 
 import android.annotation.Nullable;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpFilterType;
+import android.hardware.tv.tuner.DemuxIpFilterType;
+import android.hardware.tv.tuner.DemuxMmtpFilterType;
+import android.hardware.tv.tuner.DemuxTlvFilterType;
+import android.hardware.tv.tuner.DemuxTsFilterType;
 import android.media.tv.tuner.filter.Filter;
 
 /**
@@ -37,44 +41,44 @@
         if (mainType == Filter.TYPE_TS) {
             switch (subtype) {
                 case Filter.SUBTYPE_UNDEFINED:
-                    return Constants.DemuxTsFilterType.UNDEFINED;
+                    return DemuxTsFilterType.UNDEFINED;
                 case Filter.SUBTYPE_SECTION:
-                    return Constants.DemuxTsFilterType.SECTION;
+                    return DemuxTsFilterType.SECTION;
                 case Filter.SUBTYPE_PES:
-                    return Constants.DemuxTsFilterType.PES;
+                    return DemuxTsFilterType.PES;
                 case Filter.SUBTYPE_TS:
-                    return Constants.DemuxTsFilterType.TS;
+                    return DemuxTsFilterType.TS;
                 case Filter.SUBTYPE_AUDIO:
-                    return Constants.DemuxTsFilterType.AUDIO;
+                    return DemuxTsFilterType.AUDIO;
                 case Filter.SUBTYPE_VIDEO:
-                    return Constants.DemuxTsFilterType.VIDEO;
+                    return DemuxTsFilterType.VIDEO;
                 case Filter.SUBTYPE_PCR:
-                    return Constants.DemuxTsFilterType.PCR;
+                    return DemuxTsFilterType.PCR;
                 case Filter.SUBTYPE_RECORD:
-                    return Constants.DemuxTsFilterType.RECORD;
+                    return DemuxTsFilterType.RECORD;
                 case Filter.SUBTYPE_TEMI:
-                    return Constants.DemuxTsFilterType.TEMI;
+                    return DemuxTsFilterType.TEMI;
                 default:
                     break;
             }
         } else if (mainType == Filter.TYPE_MMTP) {
             switch (subtype) {
                 case Filter.SUBTYPE_UNDEFINED:
-                    return Constants.DemuxMmtpFilterType.UNDEFINED;
+                    return DemuxMmtpFilterType.UNDEFINED;
                 case Filter.SUBTYPE_SECTION:
-                    return Constants.DemuxMmtpFilterType.SECTION;
+                    return DemuxMmtpFilterType.SECTION;
                 case Filter.SUBTYPE_PES:
-                    return Constants.DemuxMmtpFilterType.PES;
+                    return DemuxMmtpFilterType.PES;
                 case Filter.SUBTYPE_MMTP:
-                    return Constants.DemuxMmtpFilterType.MMTP;
+                    return DemuxMmtpFilterType.MMTP;
                 case Filter.SUBTYPE_AUDIO:
-                    return Constants.DemuxMmtpFilterType.AUDIO;
+                    return DemuxMmtpFilterType.AUDIO;
                 case Filter.SUBTYPE_VIDEO:
-                    return Constants.DemuxMmtpFilterType.VIDEO;
+                    return DemuxMmtpFilterType.VIDEO;
                 case Filter.SUBTYPE_RECORD:
-                    return Constants.DemuxMmtpFilterType.RECORD;
+                    return DemuxMmtpFilterType.RECORD;
                 case Filter.SUBTYPE_DOWNLOAD:
-                    return Constants.DemuxMmtpFilterType.DOWNLOAD;
+                    return DemuxMmtpFilterType.DOWNLOAD;
                 default:
                     break;
             }
@@ -82,43 +86,43 @@
         } else if (mainType == Filter.TYPE_IP) {
             switch (subtype) {
                 case Filter.SUBTYPE_UNDEFINED:
-                    return Constants.DemuxIpFilterType.UNDEFINED;
+                    return DemuxIpFilterType.UNDEFINED;
                 case Filter.SUBTYPE_SECTION:
-                    return Constants.DemuxIpFilterType.SECTION;
+                    return DemuxIpFilterType.SECTION;
                 case Filter.SUBTYPE_NTP:
-                    return Constants.DemuxIpFilterType.NTP;
+                    return DemuxIpFilterType.NTP;
                 case Filter.SUBTYPE_IP_PAYLOAD:
-                    return Constants.DemuxIpFilterType.IP_PAYLOAD;
+                    return DemuxIpFilterType.IP_PAYLOAD;
                 case Filter.SUBTYPE_IP:
-                    return Constants.DemuxIpFilterType.IP;
+                    return DemuxIpFilterType.IP;
                 case Filter.SUBTYPE_PAYLOAD_THROUGH:
-                    return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
+                    return DemuxIpFilterType.PAYLOAD_THROUGH;
                 default:
                     break;
             }
         } else if (mainType == Filter.TYPE_TLV) {
             switch (subtype) {
                 case Filter.SUBTYPE_UNDEFINED:
-                    return Constants.DemuxTlvFilterType.UNDEFINED;
+                    return DemuxTlvFilterType.UNDEFINED;
                 case Filter.SUBTYPE_SECTION:
-                    return Constants.DemuxTlvFilterType.SECTION;
+                    return DemuxTlvFilterType.SECTION;
                 case Filter.SUBTYPE_TLV:
-                    return Constants.DemuxTlvFilterType.TLV;
+                    return DemuxTlvFilterType.TLV;
                 case Filter.SUBTYPE_PAYLOAD_THROUGH:
-                    return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
+                    return DemuxTlvFilterType.PAYLOAD_THROUGH;
                 default:
                     break;
             }
         } else if (mainType == Filter.TYPE_ALP) {
             switch (subtype) {
                 case Filter.SUBTYPE_UNDEFINED:
-                    return Constants.DemuxAlpFilterType.UNDEFINED;
+                    return DemuxAlpFilterType.UNDEFINED;
                 case Filter.SUBTYPE_SECTION:
-                    return Constants.DemuxAlpFilterType.SECTION;
+                    return DemuxAlpFilterType.SECTION;
                 case Filter.SUBTYPE_PTP:
-                    return Constants.DemuxAlpFilterType.PTP;
+                    return DemuxAlpFilterType.PTP;
                 case Filter.SUBTYPE_PAYLOAD_THROUGH:
-                    return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
+                    return DemuxAlpFilterType.PAYLOAD_THROUGH;
                 default:
                     break;
             }
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 6c2b9e3..cfd8583 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -20,7 +20,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.Tuner.Result;
 import android.media.tv.tuner.TunerUtils;
@@ -56,25 +55,27 @@
     /**
      * The space of the playback is empty.
      */
-    public static final int PLAYBACK_STATUS_EMPTY = Constants.PlaybackStatus.SPACE_EMPTY;
+    public static final int PLAYBACK_STATUS_EMPTY =
+            android.hardware.tv.tuner.PlaybackStatus.SPACE_EMPTY;
     /**
      * The space of the playback is almost empty.
      *
      * <p> the threshold is set in {@link DvrSettings}.
      */
     public static final int PLAYBACK_STATUS_ALMOST_EMPTY =
-            Constants.PlaybackStatus.SPACE_ALMOST_EMPTY;
+            android.hardware.tv.tuner.PlaybackStatus.SPACE_ALMOST_EMPTY;
     /**
      * The space of the playback is almost full.
      *
      * <p> the threshold is set in {@link DvrSettings}.
      */
     public static final int PLAYBACK_STATUS_ALMOST_FULL =
-            Constants.PlaybackStatus.SPACE_ALMOST_FULL;
+            android.hardware.tv.tuner.PlaybackStatus.SPACE_ALMOST_FULL;
     /**
      * The space of the playback is full.
      */
-    public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
+    public static final int PLAYBACK_STATUS_FULL =
+            android.hardware.tv.tuner.PlaybackStatus.SPACE_FULL;
 
     private static final String TAG = "TvTunerPlayback";
 
diff --git a/media/java/android/media/tv/tuner/dvr/DvrSettings.java b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
index 60f0d16..0c4af4b 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrSettings.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
@@ -20,7 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DataFormat;
 import android.media.tv.tuner.filter.Filter;
 
 import java.lang.annotation.Retention;
@@ -43,19 +43,19 @@
     /**
      * Transport Stream.
      */
-    public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+    public static final int DATA_FORMAT_TS = android.hardware.tv.tuner.DataFormat.TS;
     /**
      * Packetized Elementary Stream.
      */
-    public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+    public static final int DATA_FORMAT_PES = android.hardware.tv.tuner.DataFormat.PES;
     /**
      * Elementary Stream.
      */
-    public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+    public static final int DATA_FORMAT_ES = android.hardware.tv.tuner.DataFormat.ES;
     /**
      * TLV (type-length-value) Stream for SHV
      */
-    public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
+    public static final int DATA_FORMAT_SHV_TLV = android.hardware.tv.tuner.DataFormat.SHV_TLV;
 
 
     @Filter.Status
diff --git a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
index 29bc2c9..bac3b56 100644
--- a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
@@ -20,7 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpLengthType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -63,17 +63,17 @@
     /**
      * Length type not defined.
      */
-    public static final int LENGTH_TYPE_UNDEFINED = Constants.DemuxAlpLengthType.UNDEFINED;
+    public static final int LENGTH_TYPE_UNDEFINED = DemuxAlpLengthType.UNDEFINED;
     /**
      * Length does NOT include additional header.
      */
     public static final int LENGTH_TYPE_WITHOUT_ADDITIONAL_HEADER =
-            Constants.DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
+            DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
     /**
      * Length includes additional header.
      */
     public static final int LENGTH_TYPE_WITH_ADDITIONAL_HEADER =
-            Constants.DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
+            DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
 
 
     private final int mPacketType;
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index 25457a7..8bcf3d2 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_1.Constants;
 import android.media.tv.tuner.TunerUtils;
 import android.media.tv.tuner.TunerVersionChecker;
 
@@ -46,55 +45,60 @@
     /*
      * Undefined Video stream type
      */
-    public static final int VIDEO_STREAM_TYPE_UNDEFINED = Constants.VideoStreamType.UNDEFINED;
+    public static final int VIDEO_STREAM_TYPE_UNDEFINED =
+            android.hardware.tv.tuner.VideoStreamType.UNDEFINED;
     /*
      * ITU-T | ISO/IEC Reserved
      */
-    public static final int VIDEO_STREAM_TYPE_RESERVED = Constants.VideoStreamType.RESERVED;
+    public static final int VIDEO_STREAM_TYPE_RESERVED =
+            android.hardware.tv.tuner.VideoStreamType.RESERVED;
     /*
      * ISO/IEC 11172
      */
-    public static final int VIDEO_STREAM_TYPE_MPEG1 = Constants.VideoStreamType.MPEG1;
+    public static final int VIDEO_STREAM_TYPE_MPEG1 =
+            android.hardware.tv.tuner.VideoStreamType.MPEG1;
     /*
      * ITU-T Rec.H.262 and ISO/IEC 13818-2
      */
-    public static final int VIDEO_STREAM_TYPE_MPEG2 = Constants.VideoStreamType.MPEG2;
+    public static final int VIDEO_STREAM_TYPE_MPEG2 =
+            android.hardware.tv.tuner.VideoStreamType.MPEG2;
     /*
      * ISO/IEC 14496-2 (MPEG-4 H.263 based video)
      */
-    public static final int VIDEO_STREAM_TYPE_MPEG4P2 = Constants.VideoStreamType.MPEG4P2;
+    public static final int VIDEO_STREAM_TYPE_MPEG4P2 =
+            android.hardware.tv.tuner.VideoStreamType.MPEG4P2;
     /*
      * ITU-T Rec.H.264 and ISO/IEC 14496-10
      */
-    public static final int VIDEO_STREAM_TYPE_AVC = Constants.VideoStreamType.AVC;
+    public static final int VIDEO_STREAM_TYPE_AVC = android.hardware.tv.tuner.VideoStreamType.AVC;
     /*
      * ITU-T Rec. H.265 and ISO/IEC 23008-2
      */
-    public static final int VIDEO_STREAM_TYPE_HEVC = Constants.VideoStreamType.HEVC;
+    public static final int VIDEO_STREAM_TYPE_HEVC = android.hardware.tv.tuner.VideoStreamType.HEVC;
     /*
      * Microsoft VC.1
      */
-    public static final int VIDEO_STREAM_TYPE_VC1 = Constants.VideoStreamType.VC1;
+    public static final int VIDEO_STREAM_TYPE_VC1 = android.hardware.tv.tuner.VideoStreamType.VC1;
     /*
      * Google VP8
      */
-    public static final int VIDEO_STREAM_TYPE_VP8 = Constants.VideoStreamType.VP8;
+    public static final int VIDEO_STREAM_TYPE_VP8 = android.hardware.tv.tuner.VideoStreamType.VP8;
     /*
      * Google VP9
      */
-    public static final int VIDEO_STREAM_TYPE_VP9 = Constants.VideoStreamType.VP9;
+    public static final int VIDEO_STREAM_TYPE_VP9 = android.hardware.tv.tuner.VideoStreamType.VP9;
     /*
      * AOMedia Video 1
      */
-    public static final int VIDEO_STREAM_TYPE_AV1 = Constants.VideoStreamType.AV1;
+    public static final int VIDEO_STREAM_TYPE_AV1 = android.hardware.tv.tuner.VideoStreamType.AV1;
     /*
      * Chinese Standard
      */
-    public static final int VIDEO_STREAM_TYPE_AVS = Constants.VideoStreamType.AVS;
+    public static final int VIDEO_STREAM_TYPE_AVS = android.hardware.tv.tuner.VideoStreamType.AVS;
     /*
      * New Chinese Standard
      */
-    public static final int VIDEO_STREAM_TYPE_AVS2 = Constants.VideoStreamType.AVS2;
+    public static final int VIDEO_STREAM_TYPE_AVS2 = android.hardware.tv.tuner.VideoStreamType.AVS2;
 
     /** @hide */
     @IntDef(prefix = "AUDIO_STREAM_TYPE_",
@@ -110,67 +114,73 @@
     /*
      * Undefined Audio stream type
      */
-    public static final int AUDIO_STREAM_TYPE_UNDEFINED = Constants.AudioStreamType.UNDEFINED;
+    public static final int AUDIO_STREAM_TYPE_UNDEFINED =
+            android.hardware.tv.tuner.AudioStreamType.UNDEFINED;
     /*
      * Uncompressed Audio
      */
-    public static final int AUDIO_STREAM_TYPE_PCM = Constants.AudioStreamType.PCM;
+    public static final int AUDIO_STREAM_TYPE_PCM = android.hardware.tv.tuner.AudioStreamType.PCM;
     /*
      * MPEG Audio Layer III versions
      */
-    public static final int AUDIO_STREAM_TYPE_MP3 = Constants.AudioStreamType.MP3;
+    public static final int AUDIO_STREAM_TYPE_MP3 = android.hardware.tv.tuner.AudioStreamType.MP3;
     /*
      * ISO/IEC 11172 Audio
      */
-    public static final int AUDIO_STREAM_TYPE_MPEG1 = Constants.AudioStreamType.MPEG1;
+    public static final int AUDIO_STREAM_TYPE_MPEG1 =
+            android.hardware.tv.tuner.AudioStreamType.MPEG1;
     /*
      * ISO/IEC 13818-3
      */
-    public static final int AUDIO_STREAM_TYPE_MPEG2 = Constants.AudioStreamType.MPEG2;
+    public static final int AUDIO_STREAM_TYPE_MPEG2 =
+            android.hardware.tv.tuner.AudioStreamType.MPEG2;
     /*
      * ISO/IEC 23008-3 (MPEG-H Part 3)
      */
-    public static final int AUDIO_STREAM_TYPE_MPEGH = Constants.AudioStreamType.MPEGH;
+    public static final int AUDIO_STREAM_TYPE_MPEGH =
+            android.hardware.tv.tuner.AudioStreamType.MPEGH;
     /*
      * ISO/IEC 14496-3
      */
-    public static final int AUDIO_STREAM_TYPE_AAC = Constants.AudioStreamType.AAC;
+    public static final int AUDIO_STREAM_TYPE_AAC = android.hardware.tv.tuner.AudioStreamType.AAC;
     /*
      * Dolby Digital
      */
-    public static final int AUDIO_STREAM_TYPE_AC3 = Constants.AudioStreamType.AC3;
+    public static final int AUDIO_STREAM_TYPE_AC3 = android.hardware.tv.tuner.AudioStreamType.AC3;
     /*
      * Dolby Digital Plus
      */
-    public static final int AUDIO_STREAM_TYPE_EAC3 = Constants.AudioStreamType.EAC3;
+    public static final int AUDIO_STREAM_TYPE_EAC3 = android.hardware.tv.tuner.AudioStreamType.EAC3;
     /*
      * Dolby AC-4
      */
-    public static final int AUDIO_STREAM_TYPE_AC4 = Constants.AudioStreamType.AC4;
+    public static final int AUDIO_STREAM_TYPE_AC4 = android.hardware.tv.tuner.AudioStreamType.AC4;
     /*
      * Basic DTS
      */
-    public static final int AUDIO_STREAM_TYPE_DTS = Constants.AudioStreamType.DTS;
+    public static final int AUDIO_STREAM_TYPE_DTS = android.hardware.tv.tuner.AudioStreamType.DTS;
     /*
      * High Resolution DTS
      */
-    public static final int AUDIO_STREAM_TYPE_DTS_HD = Constants.AudioStreamType.DTS_HD;
+    public static final int AUDIO_STREAM_TYPE_DTS_HD =
+            android.hardware.tv.tuner.AudioStreamType.DTS_HD;
     /*
      * Windows Media Audio
      */
-    public static final int AUDIO_STREAM_TYPE_WMA = Constants.AudioStreamType.WMA;
+    public static final int AUDIO_STREAM_TYPE_WMA = android.hardware.tv.tuner.AudioStreamType.WMA;
     /*
      * Opus Interactive Audio Codec
      */
-    public static final int AUDIO_STREAM_TYPE_OPUS = Constants.AudioStreamType.OPUS;
+    public static final int AUDIO_STREAM_TYPE_OPUS = android.hardware.tv.tuner.AudioStreamType.OPUS;
     /*
      * VORBIS Interactive Audio Codec
      */
-    public static final int AUDIO_STREAM_TYPE_VORBIS = Constants.AudioStreamType.VORBIS;
+    public static final int AUDIO_STREAM_TYPE_VORBIS =
+            android.hardware.tv.tuner.AudioStreamType.VORBIS;
     /*
      * SJ/T 11368-2006
      */
-    public static final int AUDIO_STREAM_TYPE_DRA = Constants.AudioStreamType.DRA;
+    public static final int AUDIO_STREAM_TYPE_DRA = android.hardware.tv.tuner.AudioStreamType.DRA;
 
 
     private final boolean mIsPassthrough;
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 3db7047..e7612bc 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -21,7 +21,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxFilterMainType;
+import android.hardware.tv.tuner.DemuxFilterMonitorEventType;
+import android.hardware.tv.tuner.DemuxFilterStatus;
 import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.Tuner.Result;
 import android.media.tv.tuner.TunerUtils;
@@ -53,23 +55,23 @@
     /**
      * TS filter type.
      */
-    public static final int TYPE_TS = Constants.DemuxFilterMainType.TS;
+    public static final int TYPE_TS = DemuxFilterMainType.TS;
     /**
      * MMTP filter type.
      */
-    public static final int TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+    public static final int TYPE_MMTP = DemuxFilterMainType.MMTP;
     /**
      * IP filter type.
      */
-    public static final int TYPE_IP = Constants.DemuxFilterMainType.IP;
+    public static final int TYPE_IP = DemuxFilterMainType.IP;
     /**
      * TLV filter type.
      */
-    public static final int TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+    public static final int TYPE_TLV = DemuxFilterMainType.TLV;
     /**
      * ALP filter type.
      */
-    public static final int TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+    public static final int TYPE_ALP = DemuxFilterMainType.ALP;
 
     /** @hide */
     @IntDef(prefix = "SUBTYPE_",
@@ -158,7 +160,7 @@
     /**
      * The status of a filter that the data in the filter buffer is ready to be read.
      */
-    public static final int STATUS_DATA_READY = Constants.DemuxFilterStatus.DATA_READY;
+    public static final int STATUS_DATA_READY = DemuxFilterStatus.DATA_READY;
     /**
      * The status of a filter that the amount of available data in the filter buffer is at low
      * level.
@@ -166,19 +168,19 @@
      * The value is set to 25 percent of the buffer size by default. It can be changed when
      * configuring the filter.
      */
-    public static final int STATUS_LOW_WATER = Constants.DemuxFilterStatus.LOW_WATER;
+    public static final int STATUS_LOW_WATER = DemuxFilterStatus.LOW_WATER;
     /**
      * The status of a filter that the amount of available data in the filter buffer is at high
      * level.
      * The value is set to 75 percent of the buffer size by default. It can be changed when
      * configuring the filter.
      */
-    public static final int STATUS_HIGH_WATER = Constants.DemuxFilterStatus.HIGH_WATER;
+    public static final int STATUS_HIGH_WATER = DemuxFilterStatus.HIGH_WATER;
     /**
      * The status of a filter that the filter buffer is full and newly filtered data is being
      * discarded.
      */
-    public static final int STATUS_OVERFLOW = Constants.DemuxFilterStatus.OVERFLOW;
+    public static final int STATUS_OVERFLOW = DemuxFilterStatus.OVERFLOW;
 
     /** @hide */
     @IntDef(flag = true,
@@ -192,17 +194,17 @@
      * Content’s scrambling status is unknown
      */
     public static final int SCRAMBLING_STATUS_UNKNOWN =
-            android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.UNKNOWN;
+            android.hardware.tv.tuner.ScramblingStatus.UNKNOWN;
     /**
      * Content is not scrambled.
      */
     public static final int SCRAMBLING_STATUS_NOT_SCRAMBLED =
-            android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.NOT_SCRAMBLED;
+            android.hardware.tv.tuner.ScramblingStatus.NOT_SCRAMBLED;
     /**
      * Content is scrambled.
      */
     public static final int SCRAMBLING_STATUS_SCRAMBLED =
-            android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.SCRAMBLED;
+            android.hardware.tv.tuner.ScramblingStatus.SCRAMBLED;
 
     /** @hide */
     @IntDef(flag = true,
@@ -215,12 +217,11 @@
      * Monitor scrambling status change.
      */
     public static final int MONITOR_EVENT_SCRAMBLING_STATUS =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
+            DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
     /**
      * Monitor ip cid change.
      */
-    public static final int MONITOR_EVENT_IP_CID_CHANGE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.IP_CID_CHANGE;
+    public static final int MONITOR_EVENT_IP_CID_CHANGE = DemuxFilterMonitorEventType.IP_CID_CHANGE;
 
     private static final String TAG = "Filter";
 
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 4b69807..6578464 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.annotation.SystemApi;
+import android.hardware.tv.tuner.Constant;
 import android.media.tv.tuner.TunerVersionChecker;
 
 /**
@@ -33,8 +34,7 @@
     /**
      * Undefined filter type.
      */
-    public static final int INVALID_IP_FILTER_CONTEXT_ID =
-            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_IP_FILTER_CONTEXT_ID;
+    public static final int INVALID_IP_FILTER_CONTEXT_ID = Constant.INVALID_IP_FILTER_CONTEXT_ID;
 
     private final byte[] mSrcIpAddress;
     private final byte[] mDstIpAddress;
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 91992af..cd70365 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -19,7 +19,10 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxRecordScIndexType;
+import android.hardware.tv.tuner.DemuxScHevcIndex;
+import android.hardware.tv.tuner.DemuxScIndex;
+import android.hardware.tv.tuner.DemuxTsIndex;
 import android.media.tv.tuner.TunerUtils;
 
 import java.lang.annotation.Retention;
@@ -57,88 +60,80 @@
     /**
      * TS index FIRST_PACKET.
      */
-    public static final int TS_INDEX_FIRST_PACKET = Constants.DemuxTsIndex.FIRST_PACKET;
+    public static final int TS_INDEX_FIRST_PACKET = DemuxTsIndex.FIRST_PACKET;
     /**
      * TS index PAYLOAD_UNIT_START_INDICATOR.
      */
     public static final int TS_INDEX_PAYLOAD_UNIT_START_INDICATOR =
-            Constants.DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
+            DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
     /**
      * TS index CHANGE_TO_NOT_SCRAMBLED.
      */
-    public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED =
-            Constants.DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
+    public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
     /**
      * TS index CHANGE_TO_EVEN_SCRAMBLED.
      */
     public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED =
-            Constants.DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
+            DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
     /**
      * TS index CHANGE_TO_ODD_SCRAMBLED.
      */
-    public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED =
-            Constants.DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
+    public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED = DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
     /**
      * TS index DISCONTINUITY_INDICATOR.
      */
-    public static final int TS_INDEX_DISCONTINUITY_INDICATOR =
-            Constants.DemuxTsIndex.DISCONTINUITY_INDICATOR;
+    public static final int TS_INDEX_DISCONTINUITY_INDICATOR = DemuxTsIndex.DISCONTINUITY_INDICATOR;
     /**
      * TS index RANDOM_ACCESS_INDICATOR.
      */
-    public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR =
-            Constants.DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
+    public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR = DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
     /**
      * TS index PRIORITY_INDICATOR.
      */
-    public static final int TS_INDEX_PRIORITY_INDICATOR = Constants.DemuxTsIndex.PRIORITY_INDICATOR;
+    public static final int TS_INDEX_PRIORITY_INDICATOR = DemuxTsIndex.PRIORITY_INDICATOR;
     /**
      * TS index PCR_FLAG.
      */
-    public static final int TS_INDEX_PCR_FLAG = Constants.DemuxTsIndex.PCR_FLAG;
+    public static final int TS_INDEX_PCR_FLAG = DemuxTsIndex.PCR_FLAG;
     /**
      * TS index OPCR_FLAG.
      */
-    public static final int TS_INDEX_OPCR_FLAG = Constants.DemuxTsIndex.OPCR_FLAG;
+    public static final int TS_INDEX_OPCR_FLAG = DemuxTsIndex.OPCR_FLAG;
     /**
      * TS index SPLICING_POINT_FLAG.
      */
-    public static final int TS_INDEX_SPLICING_POINT_FLAG =
-            Constants.DemuxTsIndex.SPLICING_POINT_FLAG;
+    public static final int TS_INDEX_SPLICING_POINT_FLAG = DemuxTsIndex.SPLICING_POINT_FLAG;
     /**
      * TS index PRIVATE_DATA.
      */
-    public static final int TS_INDEX_PRIVATE_DATA = Constants.DemuxTsIndex.PRIVATE_DATA;
+    public static final int TS_INDEX_PRIVATE_DATA = DemuxTsIndex.PRIVATE_DATA;
     /**
      * TS index ADAPTATION_EXTENSION_FLAG.
      */
     public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG =
-            Constants.DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
+            DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
     /**
      * Index the address of MPEG Media Transport Packet Table(MPT).
      */
-    public static final int MPT_INDEX_MPT =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_MPT;
+    public static final int MPT_INDEX_MPT = DemuxTsIndex.MPT_INDEX_MPT;
     /**
      * Index the address of Video.
      */
-    public static final int MPT_INDEX_VIDEO =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_VIDEO;
+    public static final int MPT_INDEX_VIDEO = DemuxTsIndex.MPT_INDEX_VIDEO;
     /**
      * Index the address of Audio.
      */
-    public static final int MPT_INDEX_AUDIO =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_AUDIO;
+    public static final int MPT_INDEX_AUDIO = DemuxTsIndex.MPT_INDEX_AUDIO;
     /**
      * Index to indicate this is a target of timestamp extraction for video.
      */
     public static final int MPT_INDEX_TIMESTAMP_TARGET_VIDEO =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
+            DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
     /**
      * Index to indicate this is a target of timestamp extraction for audio.
      */
     public static final int MPT_INDEX_TIMESTAMP_TARGET_AUDIO =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
+            DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
 
 
     /** @hide */
@@ -150,15 +145,15 @@
     /**
      * Start Code Index is not used.
      */
-    public static final int INDEX_TYPE_NONE = Constants.DemuxRecordScIndexType.NONE;
+    public static final int INDEX_TYPE_NONE = DemuxRecordScIndexType.NONE;
     /**
      * Start Code index.
      */
-    public static final int INDEX_TYPE_SC = Constants.DemuxRecordScIndexType.SC;
+    public static final int INDEX_TYPE_SC = DemuxRecordScIndexType.SC;
     /**
      * Start Code index for HEVC.
      */
-    public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC;
+    public static final int INDEX_TYPE_SC_HEVC = DemuxRecordScIndexType.SC_HEVC;
 
     /**
      * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
@@ -176,44 +171,39 @@
     /**
      * SC index for a new I-frame.
      */
-    public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME;
+    public static final int SC_INDEX_I_FRAME = DemuxScIndex.I_FRAME;
     /**
      * SC index for a new P-frame.
      */
-    public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME;
+    public static final int SC_INDEX_P_FRAME = DemuxScIndex.P_FRAME;
     /**
      * SC index for a new B-frame.
      */
-    public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME;
+    public static final int SC_INDEX_B_FRAME = DemuxScIndex.B_FRAME;
     /**
      * SC index for a new sequence.
      */
-    public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE;
+    public static final int SC_INDEX_SEQUENCE = DemuxScIndex.SEQUENCE;
     /**
      * All blocks are coded as I blocks.
      */
-    public static final int SC_INDEX_I_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.I_SLICE;
+    public static final int SC_INDEX_I_SLICE = DemuxScIndex.I_SLICE;
     /**
      * Blocks are coded as I or P blocks.
      */
-    public static final int SC_INDEX_P_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.P_SLICE;
+    public static final int SC_INDEX_P_SLICE = DemuxScIndex.P_SLICE;
     /**
      * Blocks are coded as I, P or B blocks.
      */
-    public static final int SC_INDEX_B_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.B_SLICE;
+    public static final int SC_INDEX_B_SLICE = DemuxScIndex.B_SLICE;
     /**
      * A so-called switching I slice that is coded.
      */
-    public static final int SC_INDEX_SI_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SI_SLICE;
+    public static final int SC_INDEX_SI_SLICE = DemuxScIndex.SI_SLICE;
     /**
      * A so-called switching P slice that is coded.
      */
-    public static final int SC_INDEX_SP_SLICE =
-            android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SP_SLICE;
+    public static final int SC_INDEX_SP_SLICE = DemuxScIndex.SP_SLICE;
 
     /**
      * Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
@@ -231,41 +221,35 @@
     /**
      * SC HEVC index SPS.
      */
-    public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS;
+    public static final int SC_HEVC_INDEX_SPS = DemuxScHevcIndex.SPS;
     /**
      * SC HEVC index AUD.
      */
-    public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD;
+    public static final int SC_HEVC_INDEX_AUD = DemuxScHevcIndex.AUD;
     /**
      * SC HEVC index SLICE_CE_BLA_W_LP.
      */
-    public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP =
-            Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
+    public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
     /**
      * SC HEVC index SLICE_BLA_W_RADL.
      */
-    public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL =
-            Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL;
+    public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = DemuxScHevcIndex.SLICE_BLA_W_RADL;
     /**
      * SC HEVC index SLICE_BLA_N_LP.
      */
-    public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP =
-            Constants.DemuxScHevcIndex.SLICE_BLA_N_LP;
+    public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = DemuxScHevcIndex.SLICE_BLA_N_LP;
     /**
      * SC HEVC index SLICE_IDR_W_RADL.
      */
-    public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL =
-            Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL;
+    public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = DemuxScHevcIndex.SLICE_IDR_W_RADL;
     /**
      * SC HEVC index SLICE_IDR_N_LP.
      */
-    public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP =
-            Constants.DemuxScHevcIndex.SLICE_IDR_N_LP;
+    public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = DemuxScHevcIndex.SLICE_IDR_N_LP;
     /**
      * SC HEVC index SLICE_TRAIL_CRA.
      */
-    public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA =
-            Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA;
+    public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = DemuxScHevcIndex.SLICE_TRAIL_CRA;
 
     /**
      * @hide
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index b2c3fd2..768f1d3 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -20,7 +20,9 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAnalogAftFlag;
+import android.hardware.tv.tuner.FrontendAnalogSifStandard;
+import android.hardware.tv.tuner.FrontendAnalogType;
 import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
@@ -45,39 +47,39 @@
     /**
      * Undefined analog signal type.
      */
-    public static final int SIGNAL_TYPE_UNDEFINED = Constants.FrontendAnalogType.UNDEFINED;
+    public static final int SIGNAL_TYPE_UNDEFINED = FrontendAnalogType.UNDEFINED;
     /**
      * AUTO analog signal type.
      */
-    public static final int SIGNAL_TYPE_AUTO = Constants.FrontendAnalogType.AUTO;
+    public static final int SIGNAL_TYPE_AUTO = FrontendAnalogType.AUTO;
     /**
      * PAL analog signal type.
      */
-    public static final int SIGNAL_TYPE_PAL = Constants.FrontendAnalogType.PAL;
+    public static final int SIGNAL_TYPE_PAL = FrontendAnalogType.PAL;
     /**
      * PAL M analog signal type.
      */
-    public static final int SIGNAL_TYPE_PAL_M = Constants.FrontendAnalogType.PAL_M;
+    public static final int SIGNAL_TYPE_PAL_M = FrontendAnalogType.PAL_M;
     /**
      * PAL N analog signal type.
      */
-    public static final int SIGNAL_TYPE_PAL_N = Constants.FrontendAnalogType.PAL_N;
+    public static final int SIGNAL_TYPE_PAL_N = FrontendAnalogType.PAL_N;
     /**
      * PAL 60 analog signal type.
      */
-    public static final int SIGNAL_TYPE_PAL_60 = Constants.FrontendAnalogType.PAL_60;
+    public static final int SIGNAL_TYPE_PAL_60 = FrontendAnalogType.PAL_60;
     /**
      * NTSC analog signal type.
      */
-    public static final int SIGNAL_TYPE_NTSC = Constants.FrontendAnalogType.NTSC;
+    public static final int SIGNAL_TYPE_NTSC = FrontendAnalogType.NTSC;
     /**
      * NTSC 443 analog signal type.
      */
-    public static final int SIGNAL_TYPE_NTSC_443 = Constants.FrontendAnalogType.NTSC_443;
+    public static final int SIGNAL_TYPE_NTSC_443 = FrontendAnalogType.NTSC_443;
     /**
      * SECM analog signal type.
      */
-    public static final int SIGNAL_TYPE_SECAM = Constants.FrontendAnalogType.SECAM;
+    public static final int SIGNAL_TYPE_SECAM = FrontendAnalogType.SECAM;
 
     /** @hide */
     @IntDef(flag = true,
@@ -91,79 +93,79 @@
     /**
      * Undefined Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_UNDEFINED = Constants.FrontendAnalogSifStandard.UNDEFINED;
+    public static final int SIF_UNDEFINED = FrontendAnalogSifStandard.UNDEFINED;
     /**
      * Audo Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_AUTO = Constants.FrontendAnalogSifStandard.AUTO;
+    public static final int SIF_AUTO = FrontendAnalogSifStandard.AUTO;
      /**
      * BG Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_BG = Constants.FrontendAnalogSifStandard.BG;
+    public static final int SIF_BG = FrontendAnalogSifStandard.BG;
     /**
      * BG-A2 Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_BG_A2 = Constants.FrontendAnalogSifStandard.BG_A2;
+    public static final int SIF_BG_A2 = FrontendAnalogSifStandard.BG_A2;
     /**
      * BG-NICAM Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_BG_NICAM = Constants.FrontendAnalogSifStandard.BG_NICAM;
+    public static final int SIF_BG_NICAM = FrontendAnalogSifStandard.BG_NICAM;
     /**
      * I Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_I = Constants.FrontendAnalogSifStandard.I;
+    public static final int SIF_I = FrontendAnalogSifStandard.I;
     /**
      * DK Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_DK = Constants.FrontendAnalogSifStandard.DK;
+    public static final int SIF_DK = FrontendAnalogSifStandard.DK;
     /**
      * DK1 A2 Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_DK1_A2 = Constants.FrontendAnalogSifStandard.DK1_A2;
+    public static final int SIF_DK1_A2 = FrontendAnalogSifStandard.DK1_A2;
     /**
      * DK2 A2 Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_DK2_A2 = Constants.FrontendAnalogSifStandard.DK2_A2;
+    public static final int SIF_DK2_A2 = FrontendAnalogSifStandard.DK2_A2;
     /**
      * DK3 A2 Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_DK3_A2 = Constants.FrontendAnalogSifStandard.DK3_A2;
+    public static final int SIF_DK3_A2 = FrontendAnalogSifStandard.DK3_A2;
     /**
      * DK-NICAM Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_DK_NICAM = Constants.FrontendAnalogSifStandard.DK_NICAM;
+    public static final int SIF_DK_NICAM = FrontendAnalogSifStandard.DK_NICAM;
     /**
      * L Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_L = Constants.FrontendAnalogSifStandard.L;
+    public static final int SIF_L = FrontendAnalogSifStandard.L;
     /**
      * M Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_M = Constants.FrontendAnalogSifStandard.M;
+    public static final int SIF_M = FrontendAnalogSifStandard.M;
     /**
      * M-BTSC Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_M_BTSC = Constants.FrontendAnalogSifStandard.M_BTSC;
+    public static final int SIF_M_BTSC = FrontendAnalogSifStandard.M_BTSC;
     /**
      * M-A2 Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_M_A2 = Constants.FrontendAnalogSifStandard.M_A2;
+    public static final int SIF_M_A2 = FrontendAnalogSifStandard.M_A2;
     /**
      * M-EIAJ Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_M_EIAJ = Constants.FrontendAnalogSifStandard.M_EIAJ;
+    public static final int SIF_M_EIAJ = FrontendAnalogSifStandard.M_EIAJ;
     /**
      * I-NICAM Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_I_NICAM = Constants.FrontendAnalogSifStandard.I_NICAM;
+    public static final int SIF_I_NICAM = FrontendAnalogSifStandard.I_NICAM;
     /**
      * L-NICAM Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_L_NICAM = Constants.FrontendAnalogSifStandard.L_NICAM;
+    public static final int SIF_L_NICAM = FrontendAnalogSifStandard.L_NICAM;
     /**
      * L-PRIME Analog Standard Interchange Format (SIF).
      */
-    public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME;
+    public static final int SIF_L_PRIME = FrontendAnalogSifStandard.L_PRIME;
 
     /** @hide */
     @IntDef(prefix = "AFT_FLAG_",
@@ -174,18 +176,15 @@
     /**
      * Aft flag is not defined.
      */
-    public static final int AFT_FLAG_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.UNDEFINED;
+    public static final int AFT_FLAG_UNDEFINED = FrontendAnalogAftFlag.UNDEFINED;
     /**
      * Aft flag is set true.
      */
-    public static final int AFT_FLAG_TRUE =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_TRUE;
+    public static final int AFT_FLAG_TRUE = FrontendAnalogAftFlag.AFT_TRUE;
     /**
      * Aft flag is not set.
      */
-    public static final int AFT_FLAG_FALSE =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_FALSE;
+    public static final int AFT_FLAG_FALSE = FrontendAnalogAftFlag.AFT_FALSE;
 
 
     private final int mSignalType;
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index ed1ce2d..52a20cb 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -20,7 +20,12 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtsc3Bandwidth;
+import android.hardware.tv.tuner.FrontendAtsc3CodeRate;
+import android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat;
+import android.hardware.tv.tuner.FrontendAtsc3Fec;
+import android.hardware.tv.tuner.FrontendAtsc3Modulation;
+import android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -44,27 +49,23 @@
     /**
      * Bandwidth not defined.
      */
-    public static final int BANDWIDTH_UNDEFINED =
-            Constants.FrontendAtsc3Bandwidth.UNDEFINED;
+    public static final int BANDWIDTH_UNDEFINED = FrontendAtsc3Bandwidth.UNDEFINED;
     /**
      * Hardware is able to detect and set bandwidth automatically
      */
-    public static final int BANDWIDTH_AUTO = Constants.FrontendAtsc3Bandwidth.AUTO;
+    public static final int BANDWIDTH_AUTO = FrontendAtsc3Bandwidth.AUTO;
     /**
      * 6 MHz bandwidth.
      */
-    public static final int BANDWIDTH_BANDWIDTH_6MHZ =
-            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
+    public static final int BANDWIDTH_BANDWIDTH_6MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
     /**
      * 7 MHz bandwidth.
      */
-    public static final int BANDWIDTH_BANDWIDTH_7MHZ =
-            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
+    public static final int BANDWIDTH_BANDWIDTH_7MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
     /**
      * 8 MHz bandwidth.
      */
-    public static final int BANDWIDTH_BANDWIDTH_8MHZ =
-            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
+    public static final int BANDWIDTH_BANDWIDTH_8MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
 
 
     /** @hide */
@@ -80,35 +81,35 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendAtsc3Modulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendAtsc3Modulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically.
      */
-    public static final int MODULATION_AUTO = Constants.FrontendAtsc3Modulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendAtsc3Modulation.AUTO;
     /**
      * QPSK modulation.
      */
-    public static final int MODULATION_MOD_QPSK = Constants.FrontendAtsc3Modulation.MOD_QPSK;
+    public static final int MODULATION_MOD_QPSK = FrontendAtsc3Modulation.MOD_QPSK;
     /**
      * 16QAM modulation.
      */
-    public static final int MODULATION_MOD_16QAM = Constants.FrontendAtsc3Modulation.MOD_16QAM;
+    public static final int MODULATION_MOD_16QAM = FrontendAtsc3Modulation.MOD_16QAM;
     /**
      * 64QAM modulation.
      */
-    public static final int MODULATION_MOD_64QAM = Constants.FrontendAtsc3Modulation.MOD_64QAM;
+    public static final int MODULATION_MOD_64QAM = FrontendAtsc3Modulation.MOD_64QAM;
     /**
      * 256QAM modulation.
      */
-    public static final int MODULATION_MOD_256QAM = Constants.FrontendAtsc3Modulation.MOD_256QAM;
+    public static final int MODULATION_MOD_256QAM = FrontendAtsc3Modulation.MOD_256QAM;
     /**
      * 1024QAM modulation.
      */
-    public static final int MODULATION_MOD_1024QAM = Constants.FrontendAtsc3Modulation.MOD_1024QAM;
+    public static final int MODULATION_MOD_1024QAM = FrontendAtsc3Modulation.MOD_1024QAM;
     /**
      * 4096QAM modulation.
      */
-    public static final int MODULATION_MOD_4096QAM = Constants.FrontendAtsc3Modulation.MOD_4096QAM;
+    public static final int MODULATION_MOD_4096QAM = FrontendAtsc3Modulation.MOD_4096QAM;
 
 
     /** @hide */
@@ -123,22 +124,19 @@
      * Time interleave mode undefined.
      */
     public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
-            Constants.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+            FrontendAtsc3TimeInterleaveMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Time Interleave Mode automatically.
      */
-    public static final int TIME_INTERLEAVE_MODE_AUTO =
-            Constants.FrontendAtsc3TimeInterleaveMode.AUTO;
+    public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendAtsc3TimeInterleaveMode.AUTO;
     /**
      * CTI Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_CTI =
-            Constants.FrontendAtsc3TimeInterleaveMode.CTI;
+    public static final int TIME_INTERLEAVE_MODE_CTI = FrontendAtsc3TimeInterleaveMode.CTI;
     /**
      * HTI Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_HTI =
-            Constants.FrontendAtsc3TimeInterleaveMode.HTI;
+    public static final int TIME_INTERLEAVE_MODE_HTI = FrontendAtsc3TimeInterleaveMode.HTI;
 
 
     /** @hide */
@@ -153,59 +151,59 @@
     /**
      * Code rate undefined.
      */
-    public static final int CODERATE_UNDEFINED = Constants.FrontendAtsc3CodeRate.UNDEFINED;
+    public static final int CODERATE_UNDEFINED = FrontendAtsc3CodeRate.UNDEFINED;
     /**
      * Hardware is able to detect and set code rate automatically
      */
-    public static final int CODERATE_AUTO = Constants.FrontendAtsc3CodeRate.AUTO;
+    public static final int CODERATE_AUTO = FrontendAtsc3CodeRate.AUTO;
     /**
      * 2/15 code rate.
      */
-    public static final int CODERATE_2_15 = Constants.FrontendAtsc3CodeRate.CODERATE_2_15;
+    public static final int CODERATE_2_15 = FrontendAtsc3CodeRate.CODERATE_2_15;
     /**
      * 3/15 code rate.
      */
-    public static final int CODERATE_3_15 = Constants.FrontendAtsc3CodeRate.CODERATE_3_15;
+    public static final int CODERATE_3_15 = FrontendAtsc3CodeRate.CODERATE_3_15;
     /**
      * 4/15 code rate.
      */
-    public static final int CODERATE_4_15 = Constants.FrontendAtsc3CodeRate.CODERATE_4_15;
+    public static final int CODERATE_4_15 = FrontendAtsc3CodeRate.CODERATE_4_15;
     /**
      * 5/15 code rate.
      */
-    public static final int CODERATE_5_15 = Constants.FrontendAtsc3CodeRate.CODERATE_5_15;
+    public static final int CODERATE_5_15 = FrontendAtsc3CodeRate.CODERATE_5_15;
     /**
      * 6/15 code rate.
      */
-    public static final int CODERATE_6_15 = Constants.FrontendAtsc3CodeRate.CODERATE_6_15;
+    public static final int CODERATE_6_15 = FrontendAtsc3CodeRate.CODERATE_6_15;
     /**
      * 7/15 code rate.
      */
-    public static final int CODERATE_7_15 = Constants.FrontendAtsc3CodeRate.CODERATE_7_15;
+    public static final int CODERATE_7_15 = FrontendAtsc3CodeRate.CODERATE_7_15;
     /**
      * 8/15 code rate.
      */
-    public static final int CODERATE_8_15 = Constants.FrontendAtsc3CodeRate.CODERATE_8_15;
+    public static final int CODERATE_8_15 = FrontendAtsc3CodeRate.CODERATE_8_15;
     /**
      * 9/15 code rate.
      */
-    public static final int CODERATE_9_15 = Constants.FrontendAtsc3CodeRate.CODERATE_9_15;
+    public static final int CODERATE_9_15 = FrontendAtsc3CodeRate.CODERATE_9_15;
     /**
      * 10/15 code rate.
      */
-    public static final int CODERATE_10_15 = Constants.FrontendAtsc3CodeRate.CODERATE_10_15;
+    public static final int CODERATE_10_15 = FrontendAtsc3CodeRate.CODERATE_10_15;
     /**
      * 11/15 code rate.
      */
-    public static final int CODERATE_11_15 = Constants.FrontendAtsc3CodeRate.CODERATE_11_15;
+    public static final int CODERATE_11_15 = FrontendAtsc3CodeRate.CODERATE_11_15;
     /**
      * 12/15 code rate.
      */
-    public static final int CODERATE_12_15 = Constants.FrontendAtsc3CodeRate.CODERATE_12_15;
+    public static final int CODERATE_12_15 = FrontendAtsc3CodeRate.CODERATE_12_15;
     /**
      * 13/15 code rate.
      */
-    public static final int CODERATE_13_15 = Constants.FrontendAtsc3CodeRate.CODERATE_13_15;
+    public static final int CODERATE_13_15 = FrontendAtsc3CodeRate.CODERATE_13_15;
 
 
     /** @hide */
@@ -219,35 +217,35 @@
     /**
      * Forward Error Correction undefined.
      */
-    public static final int FEC_UNDEFINED = Constants.FrontendAtsc3Fec.UNDEFINED;
+    public static final int FEC_UNDEFINED = FrontendAtsc3Fec.UNDEFINED;
     /**
      * Hardware is able to detect and set FEC automatically
      */
-    public static final int FEC_AUTO = Constants.FrontendAtsc3Fec.AUTO;
+    public static final int FEC_AUTO = FrontendAtsc3Fec.AUTO;
     /**
      * BCH LDPC 16K Forward Error Correction
      */
-    public static final int FEC_BCH_LDPC_16K = Constants.FrontendAtsc3Fec.BCH_LDPC_16K;
+    public static final int FEC_BCH_LDPC_16K = FrontendAtsc3Fec.BCH_LDPC_16K;
     /**
      * BCH LDPC 64K Forward Error Correction
      */
-    public static final int FEC_BCH_LDPC_64K = Constants.FrontendAtsc3Fec.BCH_LDPC_64K;
+    public static final int FEC_BCH_LDPC_64K = FrontendAtsc3Fec.BCH_LDPC_64K;
     /**
      * CRC LDPC 16K Forward Error Correction
      */
-    public static final int FEC_CRC_LDPC_16K = Constants.FrontendAtsc3Fec.CRC_LDPC_16K;
+    public static final int FEC_CRC_LDPC_16K = FrontendAtsc3Fec.CRC_LDPC_16K;
     /**
      * CRC LDPC 64K Forward Error Correction
      */
-    public static final int FEC_CRC_LDPC_64K = Constants.FrontendAtsc3Fec.CRC_LDPC_64K;
+    public static final int FEC_CRC_LDPC_64K = FrontendAtsc3Fec.CRC_LDPC_64K;
     /**
      * LDPC 16K Forward Error Correction
      */
-    public static final int FEC_LDPC_16K = Constants.FrontendAtsc3Fec.LDPC_16K;
+    public static final int FEC_LDPC_16K = FrontendAtsc3Fec.LDPC_16K;
     /**
      * LDPC 64K Forward Error Correction
      */
-    public static final int FEC_LDPC_64K = Constants.FrontendAtsc3Fec.LDPC_64K;
+    public static final int FEC_LDPC_64K = FrontendAtsc3Fec.LDPC_64K;
 
 
     /** @hide */
@@ -262,17 +260,17 @@
      * Demod output format undefined.
      */
     public static final int DEMOD_OUTPUT_FORMAT_UNDEFINED =
-            Constants.FrontendAtsc3DemodOutputFormat.UNDEFINED;
+            FrontendAtsc3DemodOutputFormat.UNDEFINED;
     /**
      * ALP format. Typically used in US region.
      */
     public static final int DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET =
-            Constants.FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
+            FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
     /**
      * BaseBand packet format. Typically used in Korea region.
      */
     public static final int DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET =
-            Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
+            FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
 
     private final int mBandwidth;
     private final int mDemodOutputFormat;
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
index f7244bb..042bba8 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
@@ -20,7 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtscModulation;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -44,19 +44,19 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendAtscModulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendAtscModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically
      */
-    public static final int MODULATION_AUTO = Constants.FrontendAtscModulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendAtscModulation.AUTO;
     /**
      * 8VSB Modulation.
      */
-    public static final int MODULATION_MOD_8VSB = Constants.FrontendAtscModulation.MOD_8VSB;
+    public static final int MODULATION_MOD_8VSB = FrontendAtscModulation.MOD_8VSB;
     /**
      * 16VSB Modulation.
      */
-    public static final int MODULATION_MOD_16VSB = Constants.FrontendAtscModulation.MOD_16VSB;
+    public static final int MODULATION_MOD_16VSB = FrontendAtscModulation.MOD_16VSB;
 
 
     private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index c1d0833..9ba41d5 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -21,6 +21,12 @@
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.hardware.tv.tuner.FrontendDtmbBandwidth;
+import android.hardware.tv.tuner.FrontendDtmbCodeRate;
+import android.hardware.tv.tuner.FrontendDtmbGuardInterval;
+import android.hardware.tv.tuner.FrontendDtmbModulation;
+import android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDtmbTransmissionMode;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -46,23 +52,19 @@
     /**
      * Bandwidth not defined.
      */
-    public static final int BANDWIDTH_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.UNDEFINED;
+    public static final int BANDWIDTH_UNDEFINED = FrontendDtmbBandwidth.UNDEFINED;
     /**
      * Hardware is able to detect and set bandwidth automatically
      */
-    public static final int BANDWIDTH_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.AUTO;
+    public static final int BANDWIDTH_AUTO = FrontendDtmbBandwidth.AUTO;
     /**
      * 6 MHz bandwidth.
      */
-    public static final int BANDWIDTH_6MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
+    public static final int BANDWIDTH_6MHZ = FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
     /**
      * 8 MHz bandwidth.
      */
-    public static final int BANDWIDTH_8MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
+    public static final int BANDWIDTH_8MHZ = FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
 
 
     /** @hide */
@@ -77,22 +79,21 @@
      * Time Interleave Mode undefined.
      */
     public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.UNDEFINED;
+            FrontendDtmbTimeInterleaveMode.UNDEFINED;
     /**
      * Hardware is able to detect and set time interleave mode automatically
      */
-    public static final int TIME_INTERLEAVE_MODE_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.AUTO;
+    public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendDtmbTimeInterleaveMode.AUTO;
     /**
      * Time Interleave Mode timer int 240.
      */
     public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
+            FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
     /**
      * Time Interleave Mode timer int 720.
      */
     public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
+            FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
 
 
     /** @hide */
@@ -108,43 +109,37 @@
     /**
      * Guard Interval undefined.
      */
-    public static final int GUARD_INTERVAL_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.UNDEFINED;
+    public static final int GUARD_INTERVAL_UNDEFINED = FrontendDtmbGuardInterval.UNDEFINED;
     /**
      * Hardware is able to detect and set Guard Interval automatically.
      */
-    public static final int GUARD_INTERVAL_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.AUTO;
+    public static final int GUARD_INTERVAL_AUTO = FrontendDtmbGuardInterval.AUTO;
     /**
      * PN_420_VARIOUS Guard Interval.
      */
     public static final int GUARD_INTERVAL_PN_420_VARIOUS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_VARIOUS;
+            FrontendDtmbGuardInterval.PN_420_VARIOUS;
     /**
      * PN_595_CONST Guard Interval.
      */
-    public static final int GUARD_INTERVAL_PN_595_CONST =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_595_CONST;
+    public static final int GUARD_INTERVAL_PN_595_CONST = FrontendDtmbGuardInterval.PN_595_CONST;
     /**
      * PN_945_VARIOUS Guard Interval.
      */
     public static final int GUARD_INTERVAL_PN_945_VARIOUS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_VARIOUS;
+            FrontendDtmbGuardInterval.PN_945_VARIOUS;
     /**
      * PN_420_CONST Guard Interval.
      */
-    public static final int GUARD_INTERVAL_PN_420_CONST =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_CONST;
+    public static final int GUARD_INTERVAL_PN_420_CONST = FrontendDtmbGuardInterval.PN_420_CONST;
     /**
      * PN_945_CONST Guard Interval.
      */
-    public static final int GUARD_INTERVAL_PN_945_CONST =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_CONST;
+    public static final int GUARD_INTERVAL_PN_945_CONST = FrontendDtmbGuardInterval.PN_945_CONST;
     /**
      * PN_RESERVED Guard Interval.
      */
-    public static final int GUARD_INTERVAL_PN_RESERVED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_RESERVED;
+    public static final int GUARD_INTERVAL_PN_RESERVED = FrontendDtmbGuardInterval.PN_RESERVED;
 
 
     /** @hide */
@@ -160,38 +155,36 @@
     /**
      * Constellation not defined.
      */
-    public static final int MODULATION_CONSTELLATION_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.UNDEFINED;
+    public static final int MODULATION_CONSTELLATION_UNDEFINED = FrontendDtmbModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set Constellation automatically.
      */
-    public static final int MODULATION_CONSTELLATION_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.AUTO;
+    public static final int MODULATION_CONSTELLATION_AUTO = FrontendDtmbModulation.AUTO;
     /**
      * 4QAM Constellation.
      */
     public static final int MODULATION_CONSTELLATION_4QAM =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM;
+            FrontendDtmbModulation.CONSTELLATION_4QAM;
     /**
      * 4QAM_NR Constellation.
      */
     public static final int MODULATION_CONSTELLATION_4QAM_NR =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
+            FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
     /**
      * 16QAM Constellation.
      */
     public static final int MODULATION_CONSTELLATION_16QAM =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_16QAM;
+            FrontendDtmbModulation.CONSTELLATION_16QAM;
     /**
      * 32QAM Constellation.
      */
     public static final int MODULATION_CONSTELLATION_32QAM =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_32QAM;
+            FrontendDtmbModulation.CONSTELLATION_32QAM;
     /**
      * 64QAM Constellation.
      */
     public static final int MODULATION_CONSTELLATION_64QAM =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_64QAM;
+            FrontendDtmbModulation.CONSTELLATION_64QAM;
 
     /** @hide */
     @IntDef(flag = true,
@@ -203,28 +196,23 @@
     /**
      * Code rate undefined.
      */
-    public static final int CODERATE_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.UNDEFINED;
+    public static final int CODERATE_UNDEFINED = FrontendDtmbCodeRate.UNDEFINED;
     /**
      * Hardware is able to detect and set code rate automatically.
      */
-    public static final int CODERATE_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.AUTO;
+    public static final int CODERATE_AUTO = FrontendDtmbCodeRate.AUTO;
     /**
      * 2/5 code rate.
      */
-    public static final int CODERATE_2_5 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_2_5;
+    public static final int CODERATE_2_5 = FrontendDtmbCodeRate.CODERATE_2_5;
     /**
      * 3/5 code rate.
      */
-    public static final int CODERATE_3_5 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_3_5;
+    public static final int CODERATE_3_5 = FrontendDtmbCodeRate.CODERATE_3_5;
     /**
      * 4/5 code rate.
      */
-    public static final int CODERATE_4_5 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_4_5;
+    public static final int CODERATE_4_5 = FrontendDtmbCodeRate.CODERATE_4_5;
 
     /** @hide */
     @IntDef(flag = true,
@@ -237,23 +225,19 @@
     /**
      * Transmission Mode undefined.
      */
-    public static final int TRANSMISSION_MODE_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.UNDEFINED;
+    public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDtmbTransmissionMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Transmission Mode automatically
      */
-    public static final int TRANSMISSION_MODE_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.AUTO;
+    public static final int TRANSMISSION_MODE_AUTO = FrontendDtmbTransmissionMode.AUTO;
     /**
      * C1 Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_C1 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C1;
+    public static final int TRANSMISSION_MODE_C1 = FrontendDtmbTransmissionMode.C1;
     /**
      * C3780 Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_C3780 =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C3780;
+    public static final int TRANSMISSION_MODE_C3780 = FrontendDtmbTransmissionMode.C3780;
 
 
     private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index db28631..b209d97 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -20,7 +20,11 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendCableTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDvbcAnnex;
+import android.hardware.tv.tuner.FrontendDvbcBandwidth;
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbcOuterFec;
 import android.media.tv.tuner.TunerVersionChecker;
 import android.media.tv.tuner.frontend.FrontendSettings.FrontendSpectralInversion;
 
@@ -47,31 +51,31 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendDvbcModulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendDvbcModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically
      */
-    public static final int MODULATION_AUTO = Constants.FrontendDvbcModulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendDvbcModulation.AUTO;
     /**
      * 16QAM Modulation.
      */
-    public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbcModulation.MOD_16QAM;
+    public static final int MODULATION_MOD_16QAM = FrontendDvbcModulation.MOD_16QAM;
     /**
      * 32QAM Modulation.
      */
-    public static final int MODULATION_MOD_32QAM = Constants.FrontendDvbcModulation.MOD_32QAM;
+    public static final int MODULATION_MOD_32QAM = FrontendDvbcModulation.MOD_32QAM;
     /**
      * 64QAM Modulation.
      */
-    public static final int MODULATION_MOD_64QAM = Constants.FrontendDvbcModulation.MOD_64QAM;
+    public static final int MODULATION_MOD_64QAM = FrontendDvbcModulation.MOD_64QAM;
     /**
      * 128QAM Modulation.
      */
-    public static final int MODULATION_MOD_128QAM = Constants.FrontendDvbcModulation.MOD_128QAM;
+    public static final int MODULATION_MOD_128QAM = FrontendDvbcModulation.MOD_128QAM;
     /**
      * 256QAM Modulation.
      */
-    public static final int MODULATION_MOD_256QAM = Constants.FrontendDvbcModulation.MOD_256QAM;
+    public static final int MODULATION_MOD_256QAM = FrontendDvbcModulation.MOD_256QAM;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -82,16 +86,15 @@
     /**
      * Outer Forward Error Correction (FEC) Type undefined.
      */
-    public static final int OUTER_FEC_UNDEFINED = Constants.FrontendDvbcOuterFec.UNDEFINED;
+    public static final int OUTER_FEC_UNDEFINED = FrontendDvbcOuterFec.UNDEFINED;
     /**
      * None Outer Forward Error Correction (FEC) Type.
      */
-    public static final int OUTER_FEC_OUTER_FEC_NONE =
-            Constants.FrontendDvbcOuterFec.OUTER_FEC_NONE;
+    public static final int OUTER_FEC_OUTER_FEC_NONE = FrontendDvbcOuterFec.OUTER_FEC_NONE;
     /**
      * RS Outer Forward Error Correction (FEC) Type.
      */
-    public static final int OUTER_FEC_OUTER_FEC_RS = Constants.FrontendDvbcOuterFec.OUTER_FEC_RS;
+    public static final int OUTER_FEC_OUTER_FEC_RS = FrontendDvbcOuterFec.OUTER_FEC_RS;
 
 
     /** @hide */
@@ -104,19 +107,19 @@
     /**
      * Annex Type undefined.
      */
-    public static final int ANNEX_UNDEFINED = Constants.FrontendDvbcAnnex.UNDEFINED;
+    public static final int ANNEX_UNDEFINED = FrontendDvbcAnnex.UNDEFINED;
     /**
      * Annex Type A.
      */
-    public static final int ANNEX_A = Constants.FrontendDvbcAnnex.A;
+    public static final int ANNEX_A = FrontendDvbcAnnex.A;
     /**
      * Annex Type B.
      */
-    public static final int ANNEX_B = Constants.FrontendDvbcAnnex.B;
+    public static final int ANNEX_B = FrontendDvbcAnnex.B;
     /**
      * Annex Type C.
      */
-    public static final int ANNEX_C = Constants.FrontendDvbcAnnex.C;
+    public static final int ANNEX_C = FrontendDvbcAnnex.C;
 
 
     /**
@@ -137,7 +140,7 @@
      */
     @Deprecated
     public static final int SPECTRAL_INVERSION_UNDEFINED =
-            Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+            android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
     /**
      * Normal Spectral Inversion.
      *
@@ -145,7 +148,7 @@
      */
     @Deprecated
     public static final int SPECTRAL_INVERSION_NORMAL =
-            Constants.FrontendDvbcSpectralInversion.NORMAL;
+             android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
     /**
      * Inverted Spectral Inversion.
      *
@@ -153,7 +156,7 @@
      */
     @Deprecated
     public static final int SPECTRAL_INVERSION_INVERTED =
-            Constants.FrontendDvbcSpectralInversion.INVERTED;
+            android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
 
     /** @hide */
     @IntDef(flag = true,
@@ -171,57 +174,56 @@
      * Time interleave mode undefined.
      */
     public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.UNDEFINED;
+            FrontendCableTimeInterleaveMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Time Interleave Mode automatically.
      */
-    public static final int TIME_INTERLEAVE_MODE_AUTO =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.AUTO;
+    public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendCableTimeInterleaveMode.AUTO;
     /**
      * 128/1/0 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_128_1_0 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
+    public static final int TIME_INTERLEAVE_MODE_128_1_0 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
     /**
      * 128/1/1 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_128_1_1 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
+    public static final int TIME_INTERLEAVE_MODE_128_1_1 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
     /**
      * 64/2 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_64_2 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
+    public static final int TIME_INTERLEAVE_MODE_64_2 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
     /**
      * 32/4 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_32_4 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
+    public static final int TIME_INTERLEAVE_MODE_32_4 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
     /**
      * 16/8 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_16_8 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
+    public static final int TIME_INTERLEAVE_MODE_16_8 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
     /**
      * 8/16 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_8_16 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
+    public static final int TIME_INTERLEAVE_MODE_8_16 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
     /**
      * 128/2 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_128_2 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
+    public static final int TIME_INTERLEAVE_MODE_128_2 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
     /**
      * 128/3 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_128_3 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
+    public static final int TIME_INTERLEAVE_MODE_128_3 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
     /**
      * 128/4 Time Interleave Mode.
      */
-    public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants
-            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
+    public static final int TIME_INTERLEAVE_MODE_128_4 =
+            FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
 
     /** @hide */
     @IntDef(flag = true,
@@ -234,28 +236,23 @@
     /**
      * Bandwidth undefined.
      */
-    public static final int BANDWIDTH_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.UNDEFINED;
+    public static final int BANDWIDTH_UNDEFINED = FrontendDvbcBandwidth.UNDEFINED;
     /**
      * 5 MHz bandwidth.
      */
-    public static final int BANDWIDTH_5MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
+    public static final int BANDWIDTH_5MHZ = FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
     /**
      * 6 MHz bandwidth.
      */
-    public static final int BANDWIDTH_6MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
+    public static final int BANDWIDTH_6MHZ = FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
     /**
      * 7 MHz bandwidth.
      */
-    public static final int BANDWIDTH_7MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
+    public static final int BANDWIDTH_7MHZ = FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
     /**
      * 8 MHz bandwidth.
      */
-    public static final int BANDWIDTH_8MHZ =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
+    public static final int BANDWIDTH_8MHZ = FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
 
 
     private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index f68d554..6e3d98a 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -21,7 +21,12 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendDvbsPilot;
+import android.hardware.tv.tuner.FrontendDvbsRolloff;
+import android.hardware.tv.tuner.FrontendDvbsScanType;
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbsVcmMode;
 import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.TunerVersionChecker;
 
@@ -47,32 +52,27 @@
     /**
      * Dvbs scan type undefined.
      */
-    public static final int SCAN_TYPE_UNDEFINED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNDEFINED;
+    public static final int SCAN_TYPE_UNDEFINED = FrontendDvbsScanType.UNDEFINED;
 
     /**
      * Dvbs scan type DIRECT.
      */
-    public static final int SCAN_TYPE_DIRECT =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DIRECT;
+    public static final int SCAN_TYPE_DIRECT = FrontendDvbsScanType.DIRECT;
 
     /**
      * Dvbs scan type DISEQC.
      */
-    public static final int SCAN_TYPE_DISEQC =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DISEQC;
+    public static final int SCAN_TYPE_DISEQC = FrontendDvbsScanType.DISEQC;
 
     /**
      * Dvbs scan type UNICABLE.
      */
-    public static final int SCAN_TYPE_UNICABLE =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNICABLE;
+    public static final int SCAN_TYPE_UNICABLE = FrontendDvbsScanType.UNICABLE;
 
     /**
      * Dvbs scan type JESS.
      */
-    public static final int SCAN_TYPE_JESS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.JESS;
+    public static final int SCAN_TYPE_JESS = FrontendDvbsScanType.JESS;
 
     /** @hide */
     @IntDef(flag = true,
@@ -88,63 +88,63 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendDvbsModulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendDvbsModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically
      */
-    public static final int MODULATION_AUTO = Constants.FrontendDvbsModulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendDvbsModulation.AUTO;
     /**
      * QPSK Modulation.
      */
-    public static final int MODULATION_MOD_QPSK = Constants.FrontendDvbsModulation.MOD_QPSK;
+    public static final int MODULATION_MOD_QPSK = FrontendDvbsModulation.MOD_QPSK;
     /**
      * 8PSK Modulation.
      */
-    public static final int MODULATION_MOD_8PSK = Constants.FrontendDvbsModulation.MOD_8PSK;
+    public static final int MODULATION_MOD_8PSK = FrontendDvbsModulation.MOD_8PSK;
     /**
      * 16QAM Modulation.
      */
-    public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbsModulation.MOD_16QAM;
+    public static final int MODULATION_MOD_16QAM = FrontendDvbsModulation.MOD_16QAM;
     /**
      * 16PSK Modulation.
      */
-    public static final int MODULATION_MOD_16PSK = Constants.FrontendDvbsModulation.MOD_16PSK;
+    public static final int MODULATION_MOD_16PSK = FrontendDvbsModulation.MOD_16PSK;
     /**
      * 32PSK Modulation.
      */
-    public static final int MODULATION_MOD_32PSK = Constants.FrontendDvbsModulation.MOD_32PSK;
+    public static final int MODULATION_MOD_32PSK = FrontendDvbsModulation.MOD_32PSK;
     /**
      * ACM Modulation.
      */
-    public static final int MODULATION_MOD_ACM = Constants.FrontendDvbsModulation.MOD_ACM;
+    public static final int MODULATION_MOD_ACM = FrontendDvbsModulation.MOD_ACM;
     /**
      * 8APSK Modulation.
      */
-    public static final int MODULATION_MOD_8APSK = Constants.FrontendDvbsModulation.MOD_8APSK;
+    public static final int MODULATION_MOD_8APSK = FrontendDvbsModulation.MOD_8APSK;
     /**
      * 16APSK Modulation.
      */
-    public static final int MODULATION_MOD_16APSK = Constants.FrontendDvbsModulation.MOD_16APSK;
+    public static final int MODULATION_MOD_16APSK = FrontendDvbsModulation.MOD_16APSK;
     /**
      * 32APSK Modulation.
      */
-    public static final int MODULATION_MOD_32APSK = Constants.FrontendDvbsModulation.MOD_32APSK;
+    public static final int MODULATION_MOD_32APSK = FrontendDvbsModulation.MOD_32APSK;
     /**
      * 64APSK Modulation.
      */
-    public static final int MODULATION_MOD_64APSK = Constants.FrontendDvbsModulation.MOD_64APSK;
+    public static final int MODULATION_MOD_64APSK = FrontendDvbsModulation.MOD_64APSK;
     /**
      * 128APSK Modulation.
      */
-    public static final int MODULATION_MOD_128APSK = Constants.FrontendDvbsModulation.MOD_128APSK;
+    public static final int MODULATION_MOD_128APSK = FrontendDvbsModulation.MOD_128APSK;
     /**
      * 256APSK Modulation.
      */
-    public static final int MODULATION_MOD_256APSK = Constants.FrontendDvbsModulation.MOD_256APSK;
+    public static final int MODULATION_MOD_256APSK = FrontendDvbsModulation.MOD_256APSK;
     /**
      * Reversed Modulation.
      */
-    public static final int MODULATION_MOD_RESERVED = Constants.FrontendDvbsModulation.MOD_RESERVED;
+    public static final int MODULATION_MOD_RESERVED = FrontendDvbsModulation.MOD_RESERVED;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -156,31 +156,31 @@
     /**
      * Rolloff range undefined.
      */
-    public static final int ROLLOFF_UNDEFINED = Constants.FrontendDvbsRolloff.UNDEFINED;
+    public static final int ROLLOFF_UNDEFINED = FrontendDvbsRolloff.UNDEFINED;
     /**
      * Rolloff range 0,35.
      */
-    public static final int ROLLOFF_0_35 = Constants.FrontendDvbsRolloff.ROLLOFF_0_35;
+    public static final int ROLLOFF_0_35 = FrontendDvbsRolloff.ROLLOFF_0_35;
     /**
      * Rolloff range 0,25.
      */
-    public static final int ROLLOFF_0_25 = Constants.FrontendDvbsRolloff.ROLLOFF_0_25;
+    public static final int ROLLOFF_0_25 = FrontendDvbsRolloff.ROLLOFF_0_25;
     /**
      * Rolloff range 0,20.
      */
-    public static final int ROLLOFF_0_20 = Constants.FrontendDvbsRolloff.ROLLOFF_0_20;
+    public static final int ROLLOFF_0_20 = FrontendDvbsRolloff.ROLLOFF_0_20;
     /**
      * Rolloff range 0,15.
      */
-    public static final int ROLLOFF_0_15 = Constants.FrontendDvbsRolloff.ROLLOFF_0_15;
+    public static final int ROLLOFF_0_15 = FrontendDvbsRolloff.ROLLOFF_0_15;
     /**
      * Rolloff range 0,10.
      */
-    public static final int ROLLOFF_0_10 = Constants.FrontendDvbsRolloff.ROLLOFF_0_10;
+    public static final int ROLLOFF_0_10 = FrontendDvbsRolloff.ROLLOFF_0_10;
     /**
      * Rolloff range 0,5.
      */
-    public static final int ROLLOFF_0_5 = Constants.FrontendDvbsRolloff.ROLLOFF_0_5;
+    public static final int ROLLOFF_0_5 = FrontendDvbsRolloff.ROLLOFF_0_5;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -191,19 +191,19 @@
     /**
      * Pilot mode undefined.
      */
-    public static final int PILOT_UNDEFINED = Constants.FrontendDvbsPilot.UNDEFINED;
+    public static final int PILOT_UNDEFINED = FrontendDvbsPilot.UNDEFINED;
     /**
      * Pilot mode on.
      */
-    public static final int PILOT_ON = Constants.FrontendDvbsPilot.ON;
+    public static final int PILOT_ON = FrontendDvbsPilot.ON;
     /**
      * Pilot mode off.
      */
-    public static final int PILOT_OFF = Constants.FrontendDvbsPilot.OFF;
+    public static final int PILOT_OFF = FrontendDvbsPilot.OFF;
     /**
      * Pilot mode auto.
      */
-    public static final int PILOT_AUTO = Constants.FrontendDvbsPilot.AUTO;
+    public static final int PILOT_AUTO = FrontendDvbsPilot.AUTO;
 
 
     /** @hide */
@@ -216,19 +216,19 @@
     /**
      * Standard undefined.
      */
-    public static final int STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
+    public static final int STANDARD_AUTO = FrontendDvbsStandard.AUTO;
     /**
      * Standard S.
      */
-    public static final int STANDARD_S = Constants.FrontendDvbsStandard.S;
+    public static final int STANDARD_S = FrontendDvbsStandard.S;
     /**
      * Standard S2.
      */
-    public static final int STANDARD_S2 = Constants.FrontendDvbsStandard.S2;
+    public static final int STANDARD_S2 = FrontendDvbsStandard.S2;
     /**
      * Standard S2X.
      */
-    public static final int STANDARD_S2X = Constants.FrontendDvbsStandard.S2X;
+    public static final int STANDARD_S2X = FrontendDvbsStandard.S2X;
 
     /** @hide */
     @IntDef(prefix = "VCM_MODE_",
@@ -239,15 +239,15 @@
     /**
      * VCM mode undefined.
      */
-    public static final int VCM_MODE_UNDEFINED = Constants.FrontendDvbsVcmMode.UNDEFINED;
+    public static final int VCM_MODE_UNDEFINED = FrontendDvbsVcmMode.UNDEFINED;
     /**
      * Auto VCM mode.
      */
-    public static final int VCM_MODE_AUTO = Constants.FrontendDvbsVcmMode.AUTO;
+    public static final int VCM_MODE_AUTO = FrontendDvbsVcmMode.AUTO;
     /**
      * Manual VCM mode.
      */
-    public static final int VCM_MODE_MANUAL = Constants.FrontendDvbsVcmMode.MANUAL;
+    public static final int VCM_MODE_MANUAL = FrontendDvbsVcmMode.MANUAL;
 
 
     private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 536c7b8..5735b39 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -20,7 +20,14 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbtBandwidth;
+import android.hardware.tv.tuner.FrontendDvbtCoderate;
+import android.hardware.tv.tuner.FrontendDvbtConstellation;
+import android.hardware.tv.tuner.FrontendDvbtGuardInterval;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendDvbtPlpMode;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+import android.hardware.tv.tuner.FrontendDvbtTransmissionMode;
 import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
@@ -46,51 +53,49 @@
     /**
      * Transmission Mode undefined.
      */
-    public static final int TRANSMISSION_MODE_UNDEFINED =
-            Constants.FrontendDvbtTransmissionMode.UNDEFINED;
+    public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDvbtTransmissionMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Transmission Mode automatically
      */
-    public static final int TRANSMISSION_MODE_AUTO = Constants.FrontendDvbtTransmissionMode.AUTO;
+    public static final int TRANSMISSION_MODE_AUTO = FrontendDvbtTransmissionMode.AUTO;
     /**
      * 2K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_2K = Constants.FrontendDvbtTransmissionMode.MODE_2K;
+    public static final int TRANSMISSION_MODE_2K = FrontendDvbtTransmissionMode.MODE_2K;
     /**
      * 8K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_8K = Constants.FrontendDvbtTransmissionMode.MODE_8K;
+    public static final int TRANSMISSION_MODE_8K = FrontendDvbtTransmissionMode.MODE_8K;
     /**
      * 4K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_4K = Constants.FrontendDvbtTransmissionMode.MODE_4K;
+    public static final int TRANSMISSION_MODE_4K = FrontendDvbtTransmissionMode.MODE_4K;
     /**
      * 1K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_1K = Constants.FrontendDvbtTransmissionMode.MODE_1K;
+    public static final int TRANSMISSION_MODE_1K = FrontendDvbtTransmissionMode.MODE_1K;
     /**
      * 16K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_16K = Constants.FrontendDvbtTransmissionMode.MODE_16K;
+    public static final int TRANSMISSION_MODE_16K = FrontendDvbtTransmissionMode.MODE_16K;
     /**
      * 32K Transmission Mode.
      */
-    public static final int TRANSMISSION_MODE_32K = Constants.FrontendDvbtTransmissionMode.MODE_32K;
+    public static final int TRANSMISSION_MODE_32K = FrontendDvbtTransmissionMode.MODE_32K;
     /**
      * 8K Transmission Extended Mode.
      */
-    public static final int TRANSMISSION_MODE_EXTENDED_8K =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_8K_E;
+    public static final int TRANSMISSION_MODE_EXTENDED_8K = FrontendDvbtTransmissionMode.MODE_8K_E;
     /**
      * 16K Transmission Extended Mode.
      */
     public static final int TRANSMISSION_MODE_EXTENDED_16K =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_16K_E;
+            FrontendDvbtTransmissionMode.MODE_16K_E;
     /**
      * 32K Transmission Extended Mode.
      */
     public static final int TRANSMISSION_MODE_EXTENDED_32K =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_32K_E;
+            FrontendDvbtTransmissionMode.MODE_32K_E;
 
     /** @hide */
     @IntDef(flag = true,
@@ -103,35 +108,35 @@
     /**
      * Bandwidth undefined.
      */
-    public static final int BANDWIDTH_UNDEFINED = Constants.FrontendDvbtBandwidth.UNDEFINED;
+    public static final int BANDWIDTH_UNDEFINED = FrontendDvbtBandwidth.UNDEFINED;
     /**
      * Hardware is able to detect and set Bandwidth automatically.
      */
-    public static final int BANDWIDTH_AUTO = Constants.FrontendDvbtBandwidth.AUTO;
+    public static final int BANDWIDTH_AUTO = FrontendDvbtBandwidth.AUTO;
     /**
      * 8 MHz bandwidth.
      */
-    public static final int BANDWIDTH_8MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
+    public static final int BANDWIDTH_8MHZ = FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
     /**
      * 7 MHz bandwidth.
      */
-    public static final int BANDWIDTH_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
+    public static final int BANDWIDTH_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
     /**
      * 6 MHz bandwidth.
      */
-    public static final int BANDWIDTH_6MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
+    public static final int BANDWIDTH_6MHZ = FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
     /**
      * 5 MHz bandwidth.
      */
-    public static final int BANDWIDTH_5MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
+    public static final int BANDWIDTH_5MHZ = FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
     /**
      * 1,7 MHz bandwidth.
      */
-    public static final int BANDWIDTH_1_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
+    public static final int BANDWIDTH_1_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
     /**
      * 10 MHz bandwidth.
      */
-    public static final int BANDWIDTH_10MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
+    public static final int BANDWIDTH_10MHZ = FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
 
 
     /** @hide */
@@ -147,55 +152,44 @@
     /**
      * Constellation not defined.
      */
-    public static final int CONSTELLATION_UNDEFINED = Constants.FrontendDvbtConstellation.UNDEFINED;
+    public static final int CONSTELLATION_UNDEFINED = FrontendDvbtConstellation.UNDEFINED;
     /**
      * Hardware is able to detect and set Constellation automatically.
      */
-    public static final int CONSTELLATION_AUTO = Constants.FrontendDvbtConstellation.AUTO;
+    public static final int CONSTELLATION_AUTO = FrontendDvbtConstellation.AUTO;
     /**
      * QPSK Constellation.
      */
-    public static final int CONSTELLATION_QPSK =
-            Constants.FrontendDvbtConstellation.CONSTELLATION_QPSK;
+    public static final int CONSTELLATION_QPSK = FrontendDvbtConstellation.CONSTELLATION_QPSK;
     /**
      * 16QAM Constellation.
      */
-    public static final int CONSTELLATION_16QAM =
-            Constants.FrontendDvbtConstellation.CONSTELLATION_16QAM;
+    public static final int CONSTELLATION_16QAM = FrontendDvbtConstellation.CONSTELLATION_16QAM;
     /**
      * 64QAM Constellation.
      */
-    public static final int CONSTELLATION_64QAM =
-            Constants.FrontendDvbtConstellation.CONSTELLATION_64QAM;
+    public static final int CONSTELLATION_64QAM = FrontendDvbtConstellation.CONSTELLATION_64QAM;
     /**
      * 256QAM Constellation.
      */
-    public static final int CONSTELLATION_256QAM =
-            Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
+    public static final int CONSTELLATION_256QAM = FrontendDvbtConstellation.CONSTELLATION_256QAM;
     /**
      * QPSK Rotated Constellation.
      */
-    public static final int CONSTELLATION_QPSK_R =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
-                    .CONSTELLATION_QPSK_R;
+    public static final int CONSTELLATION_QPSK_R = FrontendDvbtConstellation.CONSTELLATION_QPSK_R;
     /**
      * 16QAM Rotated Constellation.
      */
-    public static final int CONSTELLATION_16QAM_R =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
-                    .CONSTELLATION_16QAM_R;
+    public static final int CONSTELLATION_16QAM_R = FrontendDvbtConstellation.CONSTELLATION_16QAM_R;
     /**
      * 64QAM Rotated Constellation.
      */
-    public static final int CONSTELLATION_64QAM_R =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
-                    .CONSTELLATION_64QAM_R;
+    public static final int CONSTELLATION_64QAM_R = FrontendDvbtConstellation.CONSTELLATION_64QAM_R;
     /**
      * 256QAM Rotated Constellation.
      */
     public static final int CONSTELLATION_256QAM_R =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
-                    .CONSTELLATION_256QAM_R;
+            FrontendDvbtConstellation.CONSTELLATION_256QAM_R;
 
     /** @hide */
     @IntDef(flag = true,
@@ -209,48 +203,43 @@
     /**
      * Hierarchy undefined.
      */
-    public static final int HIERARCHY_UNDEFINED = Constants.FrontendDvbtHierarchy.UNDEFINED;
+    public static final int HIERARCHY_UNDEFINED = FrontendDvbtHierarchy.UNDEFINED;
     /**
      * Hardware is able to detect and set Hierarchy automatically.
      */
-    public static final int HIERARCHY_AUTO = Constants.FrontendDvbtHierarchy.AUTO;
+    public static final int HIERARCHY_AUTO = FrontendDvbtHierarchy.AUTO;
     /**
      * Non-native Hierarchy
      */
-    public static final int HIERARCHY_NON_NATIVE =
-            Constants.FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
+    public static final int HIERARCHY_NON_NATIVE = FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
     /**
      * 1-native Hierarchy
      */
-    public static final int HIERARCHY_1_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
+    public static final int HIERARCHY_1_NATIVE = FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
     /**
      * 2-native Hierarchy
      */
-    public static final int HIERARCHY_2_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
+    public static final int HIERARCHY_2_NATIVE = FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
     /**
      * 4-native Hierarchy
      */
-    public static final int HIERARCHY_4_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
+    public static final int HIERARCHY_4_NATIVE = FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
     /**
      * Non-indepth Hierarchy
      */
-    public static final int HIERARCHY_NON_INDEPTH =
-            Constants.FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
+    public static final int HIERARCHY_NON_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
     /**
      * 1-indepth Hierarchy
      */
-    public static final int HIERARCHY_1_INDEPTH =
-            Constants.FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
+    public static final int HIERARCHY_1_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
     /**
      * 2-indepth Hierarchy
      */
-    public static final int HIERARCHY_2_INDEPTH =
-            Constants.FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
+    public static final int HIERARCHY_2_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
     /**
      * 4-indepth Hierarchy
      */
-    public static final int HIERARCHY_4_INDEPTH =
-            Constants.FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
+    public static final int HIERARCHY_4_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
 
 
     /** @hide */
@@ -264,48 +253,47 @@
     /**
      * Code rate undefined.
      */
-    public static final int CODERATE_UNDEFINED =
-            Constants.FrontendDvbtCoderate.UNDEFINED;
+    public static final int CODERATE_UNDEFINED = FrontendDvbtCoderate.UNDEFINED;
     /**
      * Hardware is able to detect and set code rate automatically.
      */
-    public static final int CODERATE_AUTO = Constants.FrontendDvbtCoderate.AUTO;
+    public static final int CODERATE_AUTO = FrontendDvbtCoderate.AUTO;
     /**
      * 1/2 code rate.
      */
-    public static final int CODERATE_1_2 = Constants.FrontendDvbtCoderate.CODERATE_1_2;
+    public static final int CODERATE_1_2 = FrontendDvbtCoderate.CODERATE_1_2;
     /**
      * 2/3 code rate.
      */
-    public static final int CODERATE_2_3 = Constants.FrontendDvbtCoderate.CODERATE_2_3;
+    public static final int CODERATE_2_3 = FrontendDvbtCoderate.CODERATE_2_3;
     /**
      * 3/4 code rate.
      */
-    public static final int CODERATE_3_4 = Constants.FrontendDvbtCoderate.CODERATE_3_4;
+    public static final int CODERATE_3_4 = FrontendDvbtCoderate.CODERATE_3_4;
     /**
      * 5/6 code rate.
      */
-    public static final int CODERATE_5_6 = Constants.FrontendDvbtCoderate.CODERATE_5_6;
+    public static final int CODERATE_5_6 = FrontendDvbtCoderate.CODERATE_5_6;
     /**
      * 7/8 code rate.
      */
-    public static final int CODERATE_7_8 = Constants.FrontendDvbtCoderate.CODERATE_7_8;
+    public static final int CODERATE_7_8 = FrontendDvbtCoderate.CODERATE_7_8;
     /**
      * 4/5 code rate.
      */
-    public static final int CODERATE_3_5 = Constants.FrontendDvbtCoderate.CODERATE_3_5;
+    public static final int CODERATE_3_5 = FrontendDvbtCoderate.CODERATE_3_5;
     /**
      * 4/5 code rate.
      */
-    public static final int CODERATE_4_5 = Constants.FrontendDvbtCoderate.CODERATE_4_5;
+    public static final int CODERATE_4_5 = FrontendDvbtCoderate.CODERATE_4_5;
     /**
      * 6/7 code rate.
      */
-    public static final int CODERATE_6_7 = Constants.FrontendDvbtCoderate.CODERATE_6_7;
+    public static final int CODERATE_6_7 = FrontendDvbtCoderate.CODERATE_6_7;
     /**
      * 8/9 code rate.
      */
-    public static final int CODERATE_8_9 = Constants.FrontendDvbtCoderate.CODERATE_8_9;
+    public static final int CODERATE_8_9 = FrontendDvbtCoderate.CODERATE_8_9;
 
     /** @hide */
     @IntDef(flag = true,
@@ -323,46 +311,39 @@
      * Guard Interval undefined.
      */
     public static final int GUARD_INTERVAL_UNDEFINED =
-            Constants.FrontendDvbtGuardInterval.UNDEFINED;
+            FrontendDvbtGuardInterval.UNDEFINED;
     /**
      * Hardware is able to detect and set Guard Interval automatically.
      */
-    public static final int GUARD_INTERVAL_AUTO = Constants.FrontendDvbtGuardInterval.AUTO;
+    public static final int GUARD_INTERVAL_AUTO = FrontendDvbtGuardInterval.AUTO;
     /**
      * 1/32 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_1_32 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_1_32;
+    public static final int GUARD_INTERVAL_1_32 = FrontendDvbtGuardInterval.INTERVAL_1_32;
     /**
      * 1/16 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_1_16 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_1_16;
+    public static final int GUARD_INTERVAL_1_16 = FrontendDvbtGuardInterval.INTERVAL_1_16;
     /**
      * 1/8 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_1_8 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_1_8;
+    public static final int GUARD_INTERVAL_1_8 = FrontendDvbtGuardInterval.INTERVAL_1_8;
     /**
      * 1/4 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_1_4 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_1_4;
+    public static final int GUARD_INTERVAL_1_4 = FrontendDvbtGuardInterval.INTERVAL_1_4;
     /**
      * 1/128 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_1_128 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_1_128;
+    public static final int GUARD_INTERVAL_1_128 = FrontendDvbtGuardInterval.INTERVAL_1_128;
     /**
      * 19/128 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_19_128 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_19_128;
+    public static final int GUARD_INTERVAL_19_128 = FrontendDvbtGuardInterval.INTERVAL_19_128;
     /**
      * 19/256 Guard Interval.
      */
-    public static final int GUARD_INTERVAL_19_256 =
-            Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
+    public static final int GUARD_INTERVAL_19_256 = FrontendDvbtGuardInterval.INTERVAL_19_256;
 
     /** @hide */
     @IntDef(flag = true,
@@ -375,15 +356,15 @@
     /**
      * Hardware is able to detect and set Standard automatically.
      */
-    public static final int STANDARD_AUTO = Constants.FrontendDvbtStandard.AUTO;
+    public static final int STANDARD_AUTO = FrontendDvbtStandard.AUTO;
     /**
      * T standard.
      */
-    public static final int STANDARD_T = Constants.FrontendDvbtStandard.T;
+    public static final int STANDARD_T = FrontendDvbtStandard.T;
     /**
      * T2 standard.
      */
-    public static final int STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
+    public static final int STANDARD_T2 = FrontendDvbtStandard.T2;
 
     /** @hide */
     @IntDef(prefix = "PLP_MODE_",
@@ -394,15 +375,15 @@
     /**
      * Physical Layer Pipe (PLP) Mode undefined.
      */
-    public static final int PLP_MODE_UNDEFINED = Constants.FrontendDvbtPlpMode.UNDEFINED;
+    public static final int PLP_MODE_UNDEFINED = FrontendDvbtPlpMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Physical Layer Pipe (PLP) Mode automatically.
      */
-    public static final int PLP_MODE_AUTO = Constants.FrontendDvbtPlpMode.AUTO;
+    public static final int PLP_MODE_AUTO = FrontendDvbtPlpMode.AUTO;
     /**
      * Physical Layer Pipe (PLP) manual Mode.
      */
-    public static final int PLP_MODE_MANUAL = Constants.FrontendDvbtPlpMode.MANUAL;
+    public static final int PLP_MODE_MANUAL = FrontendDvbtPlpMode.MANUAL;
 
     private int mTransmissionMode;
     private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index 4bfe807..4a31686 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -20,7 +20,8 @@
 import android.annotation.IntRange;
 import android.annotation.LongDef;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendInnerFec;
+import android.hardware.tv.tuner.FrontendType;
 import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.TunerVersionChecker;
 
@@ -44,47 +45,47 @@
     /**
      * Undefined frontend type.
      */
-    public static final int TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+    public static final int TYPE_UNDEFINED = FrontendType.UNDEFINED;
     /**
      * Analog frontend type.
      */
-    public static final int TYPE_ANALOG = Constants.FrontendType.ANALOG;
+    public static final int TYPE_ANALOG = FrontendType.ANALOG;
     /**
      * Advanced Television Systems Committee (ATSC) frontend type.
      */
-    public static final int TYPE_ATSC = Constants.FrontendType.ATSC;
+    public static final int TYPE_ATSC = FrontendType.ATSC;
     /**
      * Advanced Television Systems Committee 3.0 (ATSC-3) frontend type.
      */
-    public static final int TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+    public static final int TYPE_ATSC3 = FrontendType.ATSC3;
     /**
      * Digital Video Broadcasting-Cable (DVB-C) frontend type.
      */
-    public static final int TYPE_DVBC = Constants.FrontendType.DVBC;
+    public static final int TYPE_DVBC = FrontendType.DVBC;
     /**
      * Digital Video Broadcasting-Satellite (DVB-S) frontend type.
      */
-    public static final int TYPE_DVBS = Constants.FrontendType.DVBS;
+    public static final int TYPE_DVBS = FrontendType.DVBS;
     /**
      * Digital Video Broadcasting-Terrestrial (DVB-T) frontend type.
      */
-    public static final int TYPE_DVBT = Constants.FrontendType.DVBT;
+    public static final int TYPE_DVBT = FrontendType.DVBT;
     /**
      * Integrated Services Digital Broadcasting-Satellite (ISDB-S) frontend type.
      */
-    public static final int TYPE_ISDBS = Constants.FrontendType.ISDBS;
+    public static final int TYPE_ISDBS = FrontendType.ISDBS;
     /**
      * Integrated Services Digital Broadcasting-Satellite 3 (ISDB-S3) frontend type.
      */
-    public static final int TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+    public static final int TYPE_ISDBS3 = FrontendType.ISDBS3;
     /**
      * Integrated Services Digital Broadcasting-Terrestrial (ISDB-T) frontend type.
      */
-    public static final int TYPE_ISDBT = Constants.FrontendType.ISDBT;
+    public static final int TYPE_ISDBT = FrontendType.ISDBT;
     /**
      * Digital Terrestrial Multimedia Broadcast standard (DTMB) frontend type.
      */
-    public static final int TYPE_DTMB = android.hardware.tv.tuner.V1_1.Constants.FrontendType.DTMB;
+    public static final int TYPE_DTMB = FrontendType.DTMB;
 
 
     /** @hide */
@@ -101,151 +102,151 @@
     /**
      * FEC not defined.
      */
-    public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
+    public static final long FEC_UNDEFINED = FrontendInnerFec.FEC_UNDEFINED;
     /**
      * hardware is able to detect and set FEC automatically.
      */
-    public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
+    public static final long FEC_AUTO = FrontendInnerFec.AUTO;
     /**
      * 1/2 conv. code rate.
      */
-    public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
+    public static final long FEC_1_2 = FrontendInnerFec.FEC_1_2;
     /**
      * 1/3 conv. code rate.
      */
-    public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
+    public static final long FEC_1_3 = FrontendInnerFec.FEC_1_3;
     /**
      * 1/4 conv. code rate.
      */
-    public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
+    public static final long FEC_1_4 = FrontendInnerFec.FEC_1_4;
     /**
      * 1/5 conv. code rate.
      */
-    public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
+    public static final long FEC_1_5 = FrontendInnerFec.FEC_1_5;
     /**
      * 2/3 conv. code rate.
      */
-    public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
+    public static final long FEC_2_3 = FrontendInnerFec.FEC_2_3;
     /**
      * 2/5 conv. code rate.
      */
-    public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
+    public static final long FEC_2_5 = FrontendInnerFec.FEC_2_5;
     /**
      * 2/9 conv. code rate.
      */
-    public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
+    public static final long FEC_2_9 = FrontendInnerFec.FEC_2_9;
     /**
      * 3/4 conv. code rate.
      */
-    public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
+    public static final long FEC_3_4 = FrontendInnerFec.FEC_3_4;
     /**
      * 3/5 conv. code rate.
      */
-    public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
+    public static final long FEC_3_5 = FrontendInnerFec.FEC_3_5;
     /**
      * 4/5 conv. code rate.
      */
-    public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
+    public static final long FEC_4_5 = FrontendInnerFec.FEC_4_5;
     /**
      * 4/15 conv. code rate.
      */
-    public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
+    public static final long FEC_4_15 = FrontendInnerFec.FEC_4_15;
     /**
      * 5/6 conv. code rate.
      */
-    public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
+    public static final long FEC_5_6 = FrontendInnerFec.FEC_5_6;
     /**
      * 5/9 conv. code rate.
      */
-    public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
+    public static final long FEC_5_9 = FrontendInnerFec.FEC_5_9;
     /**
      * 6/7 conv. code rate.
      */
-    public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
+    public static final long FEC_6_7 = FrontendInnerFec.FEC_6_7;
     /**
      * 7/8 conv. code rate.
      */
-    public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
+    public static final long FEC_7_8 = FrontendInnerFec.FEC_7_8;
     /**
      * 7/9 conv. code rate.
      */
-    public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
+    public static final long FEC_7_9 = FrontendInnerFec.FEC_7_9;
     /**
      * 7/15 conv. code rate.
      */
-    public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
+    public static final long FEC_7_15 = FrontendInnerFec.FEC_7_15;
     /**
      * 8/9 conv. code rate.
      */
-    public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
+    public static final long FEC_8_9 = FrontendInnerFec.FEC_8_9;
     /**
      * 8/15 conv. code rate.
      */
-    public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
+    public static final long FEC_8_15 = FrontendInnerFec.FEC_8_15;
     /**
      * 9/10 conv. code rate.
      */
-    public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
+    public static final long FEC_9_10 = FrontendInnerFec.FEC_9_10;
     /**
      * 9/20 conv. code rate.
      */
-    public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
+    public static final long FEC_9_20 = FrontendInnerFec.FEC_9_20;
     /**
      * 11/15 conv. code rate.
      */
-    public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
+    public static final long FEC_11_15 = FrontendInnerFec.FEC_11_15;
     /**
      * 11/20 conv. code rate.
      */
-    public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
+    public static final long FEC_11_20 = FrontendInnerFec.FEC_11_20;
     /**
      * 11/45 conv. code rate.
      */
-    public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
+    public static final long FEC_11_45 = FrontendInnerFec.FEC_11_45;
     /**
      * 13/18 conv. code rate.
      */
-    public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
+    public static final long FEC_13_18 = FrontendInnerFec.FEC_13_18;
     /**
      * 13/45 conv. code rate.
      */
-    public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
+    public static final long FEC_13_45 = FrontendInnerFec.FEC_13_45;
     /**
      * 14/45 conv. code rate.
      */
-    public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
+    public static final long FEC_14_45 = FrontendInnerFec.FEC_14_45;
     /**
      * 23/36 conv. code rate.
      */
-    public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
+    public static final long FEC_23_36 = FrontendInnerFec.FEC_23_36;
     /**
      * 25/36 conv. code rate.
      */
-    public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
+    public static final long FEC_25_36 = FrontendInnerFec.FEC_25_36;
     /**
      * 26/45 conv. code rate.
      */
-    public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
+    public static final long FEC_26_45 = FrontendInnerFec.FEC_26_45;
     /**
      * 28/45 conv. code rate.
      */
-    public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
+    public static final long FEC_28_45 = FrontendInnerFec.FEC_28_45;
     /**
      * 29/45 conv. code rate.
      */
-    public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
+    public static final long FEC_29_45 = FrontendInnerFec.FEC_29_45;
     /**
      * 31/45 conv. code rate.
      */
-    public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
+    public static final long FEC_31_45 = FrontendInnerFec.FEC_31_45;
     /**
      * 32/45 conv. code rate.
      */
-    public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
+    public static final long FEC_32_45 = FrontendInnerFec.FEC_32_45;
     /**
      * 77/90 conv. code rate.
      */
-    public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
+    public static final long FEC_77_90 = FrontendInnerFec.FEC_77_90;
 
     /** @hide */
     @IntDef(prefix = "FRONTEND_SPECTRAL_INVERSION_",
@@ -258,17 +259,17 @@
      * Spectral Inversion Type undefined.
      */
     public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED =
-            Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+            android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
     /**
      * Normal Spectral Inversion.
      */
     public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL =
-            Constants.FrontendDvbcSpectralInversion.NORMAL;
+            android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
     /**
      * Inverted Spectral Inversion.
      */
     public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED =
-            Constants.FrontendDvbcSpectralInversion.INVERTED;
+            android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
 
 
 
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index b82a5a9..36fd942 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -20,7 +20,6 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Lnb;
 import android.media.tv.tuner.TunerVersionChecker;
 
@@ -61,175 +60,188 @@
      * Lock status for Demod.
      */
     public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK =
-            Constants.FrontendStatusType.DEMOD_LOCK;
+            android.hardware.tv.tuner.FrontendStatusType.DEMOD_LOCK;
     /**
      * Signal to Noise Ratio.
      */
-    public static final int FRONTEND_STATUS_TYPE_SNR = Constants.FrontendStatusType.SNR;
+    public static final int FRONTEND_STATUS_TYPE_SNR =
+            android.hardware.tv.tuner.FrontendStatusType.SNR;
     /**
      * Bit Error Ratio.
      */
-    public static final int FRONTEND_STATUS_TYPE_BER = Constants.FrontendStatusType.BER;
+    public static final int FRONTEND_STATUS_TYPE_BER =
+            android.hardware.tv.tuner.FrontendStatusType.BER;
     /**
      * Packages Error Ratio.
      */
-    public static final int FRONTEND_STATUS_TYPE_PER = Constants.FrontendStatusType.PER;
+    public static final int FRONTEND_STATUS_TYPE_PER =
+            android.hardware.tv.tuner.FrontendStatusType.PER;
     /**
      * Bit Error Ratio before FEC.
      */
-    public static final int FRONTEND_STATUS_TYPE_PRE_BER = Constants.FrontendStatusType.PRE_BER;
+    public static final int FRONTEND_STATUS_TYPE_PRE_BER =
+            android.hardware.tv.tuner.FrontendStatusType.PRE_BER;
     /**
      * Signal Quality (0..100). Good data over total data in percent can be
      * used as a way to present Signal Quality.
      */
     public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY =
-            Constants.FrontendStatusType.SIGNAL_QUALITY;
+            android.hardware.tv.tuner.FrontendStatusType.SIGNAL_QUALITY;
     /**
      * Signal Strength.
      */
     public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH =
-            Constants.FrontendStatusType.SIGNAL_STRENGTH;
+            android.hardware.tv.tuner.FrontendStatusType.SIGNAL_STRENGTH;
     /**
      * Symbol Rate in symbols per second.
      */
     public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE =
-            Constants.FrontendStatusType.SYMBOL_RATE;
+            android.hardware.tv.tuner.FrontendStatusType.SYMBOL_RATE;
     /**
      * Forward Error Correction Type.
      */
-    public static final int FRONTEND_STATUS_TYPE_FEC = Constants.FrontendStatusType.FEC;
+    public static final int FRONTEND_STATUS_TYPE_FEC =
+            android.hardware.tv.tuner.FrontendStatusType.FEC;
     /**
      * Modulation Type.
      */
     public static final int FRONTEND_STATUS_TYPE_MODULATION =
-            Constants.FrontendStatusType.MODULATION;
+            android.hardware.tv.tuner.FrontendStatusType.MODULATION;
     /**
      * Spectral Inversion Type.
      */
-    public static final int FRONTEND_STATUS_TYPE_SPECTRAL = Constants.FrontendStatusType.SPECTRAL;
+    public static final int FRONTEND_STATUS_TYPE_SPECTRAL =
+            android.hardware.tv.tuner.FrontendStatusType.SPECTRAL;
     /**
      * LNB Voltage.
      */
     public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE =
-            Constants.FrontendStatusType.LNB_VOLTAGE;
+            android.hardware.tv.tuner.FrontendStatusType.LNB_VOLTAGE;
     /**
      * Physical Layer Pipe ID.
      */
-    public static final int FRONTEND_STATUS_TYPE_PLP_ID = Constants.FrontendStatusType.PLP_ID;
+    public static final int FRONTEND_STATUS_TYPE_PLP_ID =
+            android.hardware.tv.tuner.FrontendStatusType.PLP_ID;
     /**
      * Status for Emergency Warning Broadcasting System.
      */
-    public static final int FRONTEND_STATUS_TYPE_EWBS = Constants.FrontendStatusType.EWBS;
+    public static final int FRONTEND_STATUS_TYPE_EWBS =
+            android.hardware.tv.tuner.FrontendStatusType.EWBS;
     /**
      * Automatic Gain Control.
      */
-    public static final int FRONTEND_STATUS_TYPE_AGC = Constants.FrontendStatusType.AGC;
+    public static final int FRONTEND_STATUS_TYPE_AGC =
+            android.hardware.tv.tuner.FrontendStatusType.AGC;
     /**
      * Low Noise Amplifier.
      */
-    public static final int FRONTEND_STATUS_TYPE_LNA = Constants.FrontendStatusType.LNA;
+    public static final int FRONTEND_STATUS_TYPE_LNA =
+            android.hardware.tv.tuner.FrontendStatusType.LNA;
     /**
      * Error status by layer.
      */
     public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
-            Constants.FrontendStatusType.LAYER_ERROR;
+            android.hardware.tv.tuner.FrontendStatusType.LAYER_ERROR;
     /**
      * Modulation Error Ratio.
      */
-    public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
+    public static final int FRONTEND_STATUS_TYPE_MER =
+            android.hardware.tv.tuner.FrontendStatusType.MER;
     /**
      * Difference between tuning frequency and actual locked frequency.
      */
     public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET =
-            Constants.FrontendStatusType.FREQ_OFFSET;
+            android.hardware.tv.tuner.FrontendStatusType.FREQ_OFFSET;
     /**
      * Hierarchy for DVBT.
      */
-    public static final int FRONTEND_STATUS_TYPE_HIERARCHY = Constants.FrontendStatusType.HIERARCHY;
+    public static final int FRONTEND_STATUS_TYPE_HIERARCHY =
+            android.hardware.tv.tuner.FrontendStatusType.HIERARCHY;
     /**
      * Lock status for RF.
      */
-    public static final int FRONTEND_STATUS_TYPE_RF_LOCK = Constants.FrontendStatusType.RF_LOCK;
+    public static final int FRONTEND_STATUS_TYPE_RF_LOCK =
+            android.hardware.tv.tuner.FrontendStatusType.RF_LOCK;
     /**
      * PLP information in a frequency band for ATSC-3.0 frontend.
      */
     public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
-            Constants.FrontendStatusType.ATSC3_PLP_INFO;
+            android.hardware.tv.tuner.FrontendStatusType.ATSC3_PLP_INFO;
     /**
      * BERS Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_BERS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BERS;
+            android.hardware.tv.tuner.FrontendStatusType.BERS;
     /**
      * Coderate Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_CODERATES =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.CODERATES;
+            android.hardware.tv.tuner.FrontendStatusType.CODERATES;
     /**
      * Bandwidth Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_BANDWIDTH =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BANDWIDTH;
+            android.hardware.tv.tuner.FrontendStatusType.BANDWIDTH;
     /**
      * Guard Interval Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.GUARD_INTERVAL;
+            android.hardware.tv.tuner.FrontendStatusType.GUARD_INTERVAL;
     /**
      * Transmission Mode Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TRANSMISSION_MODE;
+            android.hardware.tv.tuner.FrontendStatusType.TRANSMISSION_MODE;
     /**
      * UEC Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_UEC =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.UEC;
+            android.hardware.tv.tuner.FrontendStatusType.UEC;
     /**
      * T2 System Id Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.T2_SYSTEM_ID;
+            android.hardware.tv.tuner.FrontendStatusType.T2_SYSTEM_ID;
     /**
      * Interleavings Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.INTERLEAVINGS;
+            android.hardware.tv.tuner.FrontendStatusType.INTERLEAVINGS;
     /**
      * ISDBT Segments Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ISDBT_SEGMENTS;
+            android.hardware.tv.tuner.FrontendStatusType.ISDBT_SEGMENTS;
     /**
      * TS Data Rates Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TS_DATA_RATES;
+            android.hardware.tv.tuner.FrontendStatusType.TS_DATA_RATES;
     /**
      * Extended Modulations Type. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.MODULATIONS;
+            android.hardware.tv.tuner.FrontendStatusType.MODULATIONS;
     /**
      * Roll Off Type status of the frontend. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_ROLL_OFF =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ROLL_OFF;
+            android.hardware.tv.tuner.FrontendStatusType.ROLL_OFF;
     /**
      * If the frontend currently supports MISO or not. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_IS_MISO_ENABLED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_MISO;
+            android.hardware.tv.tuner.FrontendStatusType.IS_MISO;
     /**
      * If the frontend code rate is linear or not. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_IS_LINEAR =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_LINEAR;
+            android.hardware.tv.tuner.FrontendStatusType.IS_LINEAR;
     /**
      * If short frames is enabled or not. Only supported in Tuner HAL 1.1 or higher.
      */
     public static final int FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED =
-            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_SHORT_FRAMES;
+            android.hardware.tv.tuner.FrontendStatusType.IS_SHORT_FRAMES;
 
     /** @hide */
     @IntDef(value = {
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index 02cdb96..14b0b02 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -20,7 +20,9 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbs3Coderate;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Rolloff;
 import android.media.tv.tuner.Tuner;
 
 import java.lang.annotation.Retention;
@@ -45,31 +47,31 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbs3Modulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendIsdbs3Modulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically.
      */
-    public static final int MODULATION_AUTO = Constants.FrontendIsdbs3Modulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendIsdbs3Modulation.AUTO;
     /**
      * BPSK Modulation.
      */
-    public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbs3Modulation.MOD_BPSK;
+    public static final int MODULATION_MOD_BPSK = FrontendIsdbs3Modulation.MOD_BPSK;
     /**
      * QPSK Modulation.
      */
-    public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbs3Modulation.MOD_QPSK;
+    public static final int MODULATION_MOD_QPSK = FrontendIsdbs3Modulation.MOD_QPSK;
     /**
      * 8PSK Modulation.
      */
-    public static final int MODULATION_MOD_8PSK = Constants.FrontendIsdbs3Modulation.MOD_8PSK;
+    public static final int MODULATION_MOD_8PSK = FrontendIsdbs3Modulation.MOD_8PSK;
     /**
      * 16APSK Modulation.
      */
-    public static final int MODULATION_MOD_16APSK = Constants.FrontendIsdbs3Modulation.MOD_16APSK;
+    public static final int MODULATION_MOD_16APSK = FrontendIsdbs3Modulation.MOD_16APSK;
     /**
      * 32APSK Modulation.
      */
-    public static final int MODULATION_MOD_32APSK = Constants.FrontendIsdbs3Modulation.MOD_32APSK;
+    public static final int MODULATION_MOD_32APSK = FrontendIsdbs3Modulation.MOD_32APSK;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -83,55 +85,55 @@
     /**
      * Code rate undefined.
      */
-    public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbs3Coderate.UNDEFINED;
+    public static final int CODERATE_UNDEFINED = FrontendIsdbs3Coderate.UNDEFINED;
     /**
      * Hardware is able to detect and set code rate automatically.
      */
-    public static final int CODERATE_AUTO = Constants.FrontendIsdbs3Coderate.AUTO;
+    public static final int CODERATE_AUTO = FrontendIsdbs3Coderate.AUTO;
     /**
      * 1/3 code rate.
      */
-    public static final int CODERATE_1_3 = Constants.FrontendIsdbs3Coderate.CODERATE_1_3;
+    public static final int CODERATE_1_3 = FrontendIsdbs3Coderate.CODERATE_1_3;
     /**
      * 2/5 code rate.
      */
-    public static final int CODERATE_2_5 = Constants.FrontendIsdbs3Coderate.CODERATE_2_5;
+    public static final int CODERATE_2_5 = FrontendIsdbs3Coderate.CODERATE_2_5;
     /**
      * 1/2 code rate.
      */
-    public static final int CODERATE_1_2 = Constants.FrontendIsdbs3Coderate.CODERATE_1_2;
+    public static final int CODERATE_1_2 = FrontendIsdbs3Coderate.CODERATE_1_2;
     /**
      * 3/5 code rate.
      */
-    public static final int CODERATE_3_5 = Constants.FrontendIsdbs3Coderate.CODERATE_3_5;
+    public static final int CODERATE_3_5 = FrontendIsdbs3Coderate.CODERATE_3_5;
     /**
      * 2/3 code rate.
      */
-    public static final int CODERATE_2_3 = Constants.FrontendIsdbs3Coderate.CODERATE_2_3;
+    public static final int CODERATE_2_3 = FrontendIsdbs3Coderate.CODERATE_2_3;
     /**
      * 3/4 code rate.
      */
-    public static final int CODERATE_3_4 = Constants.FrontendIsdbs3Coderate.CODERATE_3_4;
+    public static final int CODERATE_3_4 = FrontendIsdbs3Coderate.CODERATE_3_4;
     /**
      * 7/9 code rate.
      */
-    public static final int CODERATE_7_9 = Constants.FrontendIsdbs3Coderate.CODERATE_7_9;
+    public static final int CODERATE_7_9 = FrontendIsdbs3Coderate.CODERATE_7_9;
     /**
      * 4/5 code rate.
      */
-    public static final int CODERATE_4_5 = Constants.FrontendIsdbs3Coderate.CODERATE_4_5;
+    public static final int CODERATE_4_5 = FrontendIsdbs3Coderate.CODERATE_4_5;
     /**
      * 5/6 code rate.
      */
-    public static final int CODERATE_5_6 = Constants.FrontendIsdbs3Coderate.CODERATE_5_6;
+    public static final int CODERATE_5_6 = FrontendIsdbs3Coderate.CODERATE_5_6;
     /**
      * 7/8 code rate.
      */
-    public static final int CODERATE_7_8 = Constants.FrontendIsdbs3Coderate.CODERATE_7_8;
+    public static final int CODERATE_7_8 = FrontendIsdbs3Coderate.CODERATE_7_8;
     /**
      * 9/10 code rate.
      */
-    public static final int CODERATE_9_10 = Constants.FrontendIsdbs3Coderate.CODERATE_9_10;
+    public static final int CODERATE_9_10 = FrontendIsdbs3Coderate.CODERATE_9_10;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -142,11 +144,11 @@
     /**
      * Rolloff type undefined.
      */
-    public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
+    public static final int ROLLOFF_UNDEFINED = FrontendIsdbs3Rolloff.UNDEFINED;
     /**
      * 0,03 Rolloff.
      */
-    public static final int ROLLOFF_0_03 = Constants.FrontendIsdbs3Rolloff.ROLLOFF_0_03;
+    public static final int ROLLOFF_0_03 = FrontendIsdbs3Rolloff.ROLLOFF_0_03;
 
 
     private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index 3cc1aab..aab6408 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -20,7 +20,10 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbsCoderate;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbsRolloff;
+import android.hardware.tv.tuner.FrontendIsdbsStreamIdType;
 import android.media.tv.tuner.Tuner;
 
 import java.lang.annotation.Retention;
@@ -42,12 +45,12 @@
     /**
      * Uses stream ID.
      */
-    public static final int STREAM_ID_TYPE_ID = Constants.FrontendIsdbsStreamIdType.STREAM_ID;
+    public static final int STREAM_ID_TYPE_ID = FrontendIsdbsStreamIdType.STREAM_ID;
     /**
      * Uses relative number.
      */
     public static final int STREAM_ID_TYPE_RELATIVE_NUMBER =
-            Constants.FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
+            FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
 
 
     /** @hide */
@@ -61,23 +64,23 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbsModulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendIsdbsModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically
      */
-    public static final int MODULATION_AUTO = Constants.FrontendIsdbsModulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendIsdbsModulation.AUTO;
     /**
      * BPSK Modulation.
      */
-    public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbsModulation.MOD_BPSK;
+    public static final int MODULATION_MOD_BPSK = FrontendIsdbsModulation.MOD_BPSK;
     /**
      * QPSK Modulation.
      */
-    public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbsModulation.MOD_QPSK;
+    public static final int MODULATION_MOD_QPSK = FrontendIsdbsModulation.MOD_QPSK;
     /**
      * TC8PSK Modulation.
      */
-    public static final int MODULATION_MOD_TC8PSK = Constants.FrontendIsdbsModulation.MOD_TC8PSK;
+    public static final int MODULATION_MOD_TC8PSK = FrontendIsdbsModulation.MOD_TC8PSK;
 
 
     /** @hide */
@@ -91,31 +94,31 @@
     /**
      * Code rate undefined.
      */
-    public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbsCoderate.UNDEFINED;
+    public static final int CODERATE_UNDEFINED = FrontendIsdbsCoderate.UNDEFINED;
     /**
      * Hardware is able to detect and set code rate automatically.
      */
-    public static final int CODERATE_AUTO = Constants.FrontendIsdbsCoderate.AUTO;
+    public static final int CODERATE_AUTO = FrontendIsdbsCoderate.AUTO;
     /**
      * 1/2 code rate.
      */
-    public static final int CODERATE_1_2 = Constants.FrontendIsdbsCoderate.CODERATE_1_2;
+    public static final int CODERATE_1_2 = FrontendIsdbsCoderate.CODERATE_1_2;
     /**
      * 2/3 code rate.
      */
-    public static final int CODERATE_2_3 = Constants.FrontendIsdbsCoderate.CODERATE_2_3;
+    public static final int CODERATE_2_3 = FrontendIsdbsCoderate.CODERATE_2_3;
     /**
      * 3/4 code rate.
      */
-    public static final int CODERATE_3_4 = Constants.FrontendIsdbsCoderate.CODERATE_3_4;
+    public static final int CODERATE_3_4 = FrontendIsdbsCoderate.CODERATE_3_4;
     /**
      * 5/6 code rate.
      */
-    public static final int CODERATE_5_6 = Constants.FrontendIsdbsCoderate.CODERATE_5_6;
+    public static final int CODERATE_5_6 = FrontendIsdbsCoderate.CODERATE_5_6;
     /**
      * 7/8 code rate.
      */
-    public static final int CODERATE_7_8 = Constants.FrontendIsdbsCoderate.CODERATE_7_8;
+    public static final int CODERATE_7_8 = FrontendIsdbsCoderate.CODERATE_7_8;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -126,11 +129,11 @@
     /**
      * Rolloff type undefined.
      */
-    public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbsRolloff.UNDEFINED;
+    public static final int ROLLOFF_UNDEFINED = FrontendIsdbsRolloff.UNDEFINED;
     /**
      * 0,35 rolloff.
      */
-    public static final int ROLLOFF_0_35 = Constants.FrontendIsdbsRolloff.ROLLOFF_0_35;
+    public static final int ROLLOFF_0_35 = FrontendIsdbsRolloff.ROLLOFF_0_35;
 
 
     private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 6a14d08..de2476a 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -20,7 +20,9 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbtBandwidth;
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
 import android.media.tv.tuner.frontend.DvbtFrontendSettings.CodeRate;
 
 import java.lang.annotation.Retention;
@@ -44,27 +46,27 @@
     /**
      * Modulation undefined.
      */
-    public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbtModulation.UNDEFINED;
+    public static final int MODULATION_UNDEFINED = FrontendIsdbtModulation.UNDEFINED;
     /**
      * Hardware is able to detect and set modulation automatically
      */
-    public static final int MODULATION_AUTO = Constants.FrontendIsdbtModulation.AUTO;
+    public static final int MODULATION_AUTO = FrontendIsdbtModulation.AUTO;
     /**
      * DQPSK Modulation.
      */
-    public static final int MODULATION_MOD_DQPSK = Constants.FrontendIsdbtModulation.MOD_DQPSK;
+    public static final int MODULATION_MOD_DQPSK = FrontendIsdbtModulation.MOD_DQPSK;
     /**
      * QPSK Modulation.
      */
-    public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbtModulation.MOD_QPSK;
+    public static final int MODULATION_MOD_QPSK = FrontendIsdbtModulation.MOD_QPSK;
     /**
      * 16QAM Modulation.
      */
-    public static final int MODULATION_MOD_16QAM = Constants.FrontendIsdbtModulation.MOD_16QAM;
+    public static final int MODULATION_MOD_16QAM = FrontendIsdbtModulation.MOD_16QAM;
     /**
      * 64QAM Modulation.
      */
-    public static final int MODULATION_MOD_64QAM = Constants.FrontendIsdbtModulation.MOD_64QAM;
+    public static final int MODULATION_MOD_64QAM = FrontendIsdbtModulation.MOD_64QAM;
 
 
     /** @hide */
@@ -77,23 +79,23 @@
     /**
      * Mode undefined.
      */
-    public static final int MODE_UNDEFINED = Constants.FrontendIsdbtMode.UNDEFINED;
+    public static final int MODE_UNDEFINED = FrontendIsdbtMode.UNDEFINED;
     /**
      * Hardware is able to detect and set Mode automatically.
      */
-    public static final int MODE_AUTO = Constants.FrontendIsdbtMode.AUTO;
+    public static final int MODE_AUTO = FrontendIsdbtMode.AUTO;
     /**
      * Mode 1
      */
-    public static final int MODE_1 = Constants.FrontendIsdbtMode.MODE_1;
+    public static final int MODE_1 = FrontendIsdbtMode.MODE_1;
     /**
      * Mode 2
      */
-    public static final int MODE_2 = Constants.FrontendIsdbtMode.MODE_2;
+    public static final int MODE_2 = FrontendIsdbtMode.MODE_2;
     /**
      * Mode 3
      */
-    public static final int MODE_3 = Constants.FrontendIsdbtMode.MODE_3;
+    public static final int MODE_3 = FrontendIsdbtMode.MODE_3;
 
 
     /** @hide */
@@ -107,23 +109,23 @@
     /**
      * Bandwidth undefined.
      */
-    public static final int BANDWIDTH_UNDEFINED = Constants.FrontendIsdbtBandwidth.UNDEFINED;
+    public static final int BANDWIDTH_UNDEFINED = FrontendIsdbtBandwidth.UNDEFINED;
     /**
      * Hardware is able to detect and set Bandwidth automatically.
      */
-    public static final int BANDWIDTH_AUTO = Constants.FrontendIsdbtBandwidth.AUTO;
+    public static final int BANDWIDTH_AUTO = FrontendIsdbtBandwidth.AUTO;
     /**
      * 8 MHz bandwidth.
      */
-    public static final int BANDWIDTH_8MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
+    public static final int BANDWIDTH_8MHZ = FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
     /**
      * 7 MHz bandwidth.
      */
-    public static final int BANDWIDTH_7MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
+    public static final int BANDWIDTH_7MHZ = FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
     /**
      * 6 MHz bandwidth.
      */
-    public static final int BANDWIDTH_6MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
+    public static final int BANDWIDTH_6MHZ = FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
 
     private final int mModulation;
     private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
index 5cf0d31..3b5419e 100644
--- a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
+++ b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
@@ -18,7 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendEventType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -37,11 +37,11 @@
     @interface TuneEvent {}
 
     /** The frontend has locked to the signal specified by the tune method. */
-    int SIGNAL_LOCKED = Constants.FrontendEventType.LOCKED;
+    int SIGNAL_LOCKED = FrontendEventType.LOCKED;
     /** The frontend is unable to lock to the signal specified by the tune method. */
-    int SIGNAL_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+    int SIGNAL_NO_SIGNAL = FrontendEventType.NO_SIGNAL;
     /** The frontend has lost the lock to the signal specified by the tune method. */
-    int SIGNAL_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+    int SIGNAL_LOST_LOCK = FrontendEventType.LOST_LOCK;
 
     /** Tune Event from the frontend */
     void onTuneEvent(@TuneEvent int tuneEvent);
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index bc73f6a..c775b6f 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -183,8 +183,8 @@
         "libmedia",
         "libnativehelper",
         "libutils",
-        "tv_tuner_aidl_interface-ndk_platform",
-        "tv_tuner_resource_manager_aidl_interface-ndk_platform",
+        "tv_tuner_aidl_interface-ndk",
+        "tv_tuner_resource_manager_aidl_interface-ndk",
     ],
 
     static_libs: [
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e4f3f33..698fb5a5 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1245,7 +1245,8 @@
         return NULL;
     }
 
-    sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
+    sp<FrontendClientCallbackImpl> feClientCb =
+            new FrontendClientCallbackImpl(env->NewWeakGlobalRef(mObject));
     mFeClient->setCallback(feClientCb);
     // TODO: add more fields to frontend
     return env->NewObject(
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
new file mode 100644
index 0000000..064f14a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Ayarlar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..d51823f
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Podešavanja"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
new file mode 100644
index 0000000..df46ee7
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Настройки"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
new file mode 100644
index 0000000..442217a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..d5c868b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎Settings‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
new file mode 100644
index 0000000..64dddc9
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Ajustes"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
new file mode 100644
index 0000000..76a8bd7
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"تنظیمات"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
new file mode 100644
index 0000000..442217a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
new file mode 100644
index 0000000..bdab372
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Beállítások"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
new file mode 100644
index 0000000..d91474a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Կարգավորումներ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
new file mode 100644
index 0000000..1c0204d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Impostazioni"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
new file mode 100644
index 0000000..28ff3e72
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"הגדרות"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
new file mode 100644
index 0000000..671fc1c
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"პარამეტრები"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
new file mode 100644
index 0000000..bcd6784b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Параметрлер"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
new file mode 100644
index 0000000..df2c7d0
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"ការកំណត់"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
new file mode 100644
index 0000000..8a54318
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"설정"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
new file mode 100644
index 0000000..f4a893a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Жөндөөлөр"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
new file mode 100644
index 0000000..2a91bc3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"ການຕັ້ງຄ່າ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
new file mode 100644
index 0000000..194aa02
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Тохиргоо"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
new file mode 100644
index 0000000..9a7365d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Instellingen"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..87dbe7d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..5ac7278
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Definições"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
new file mode 100644
index 0000000..87dbe7d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
new file mode 100644
index 0000000..10f8475
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"සැකසීම්"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
new file mode 100644
index 0000000..41b33fe
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Nastavitve"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
new file mode 100644
index 0000000..1478a00
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Подешавања"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
new file mode 100644
index 0000000..ef54206
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Inställningar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
new file mode 100644
index 0000000..d5dbf19
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Mipangilio"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
new file mode 100644
index 0000000..f923a18
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Mga Setting"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
new file mode 100644
index 0000000..8f03a19
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Налаштування"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
new file mode 100644
index 0000000..e8fb658
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Sozlamalar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
new file mode 100644
index 0000000..ab7136b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Cài đặt"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
new file mode 100644
index 0000000..bb87ec2
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="settings_label" msgid="5948970810295631236">"Amasethingi"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 0fd9ae5..5c9a3e0 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -252,8 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"ওয়াই-ফাই ভারবোস লগিং চালু করুন"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"ওয়াই-ফাই স্ক্যান থ্রোটলিং"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"অল্প সময় ওয়াই-ফাই নেটওয়ার্কে যুক্ত থাকে এমন MAC অ্যাড্রেসের র‍্যান্ডমাইজেশন"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
@@ -285,8 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ব্যাটারির খরচ কমায় এবং নেটওয়ার্কের পারফর্ম্যান্স উন্নত করে"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"এই মোডটি চালু থাকলে, MAC অ্যাড্রেসের র‍্যান্ডমাইজেশনের সুবিধা চালু আছে এমন কোনও নেটওয়ার্কে প্রত্যেকবার কানেক্ট করার সময় ডিভাইসের MAC অ্যাড্রেস পরিবর্তিত হতে পারে।"</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"মিটার্ড"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"পরিমাপ করা নয়"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"লগার বাফারের আকারগুলি"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 3abd211..a225b74 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -284,7 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Afficher les options pour la certification de l\'affichage sans fil"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Détailler les infos Wi-Fi, afficher par RSSI de SSID dans l\'outil de sélection Wi-Fi"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Réduit la décharge de la batterie et améliore les performances du réseau"</string>
-    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau Wi-Fi où le changement aléatoire d\'adresse MAC est activé."</string>
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau où le changement aléatoire d\'adresse MAC est activé."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"Facturé à l\'usage"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Non facturé à l\'usage"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"Tailles des tampons de l\'enregistreur"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 9fc70cf..eedadc9 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -252,8 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ ચાલુ કરો"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"વાઇ-ફાઇ સ્કૅનની ક્ષમતા મર્યાદિત કરવી"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"વાઇ-ફાઇ માટે સતત બદલાતું MAC રેન્ડમાઇઝેશન"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"નામ વિનાના બ્લૂટૂથ ડિવાઇસ બતાવો"</string>
@@ -285,8 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"બૅટરીનો ચાર્જ ઝડપથી ઓછો થવાનું ટાળે છે અને નેટવર્કના કાર્યપ્રદર્શનમાં સુધારો કરે છે"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"આ મોડ ચાલુ કરેલો હોય ત્યારે MAC રેન્ડમાઇઝેશન ચાલુ કરેલું હોય તેવા નેટવર્ક સાથે આ ડિવાઇસ કનેક્ટ થશે, ત્યારે દર વખતે તેનું MAC ઍડ્રેસ બદલાય તેવું બની શકે છે."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"મીટર કરેલું"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"મીટર ન કરેલ"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"લોગર બફર કદ"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index fba3aeb..67247ea 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -252,7 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"‏אישור של תצוגת Wi-Fi"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"‏הפעלת רישום מפורט של Wi‑Fi ביומן"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"‏ויסות סריקה לנקודות Wi-Fi"</string>
-    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"‏רנדומיזציה של כתובות MAC בלי חיבור יציב ל-Wi-Fi"</string>
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"‏רנדומיזציה של כתובות MAC משתנות ברשתות Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"חבילת הגלישה פעילה תמיד"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"‏הצגת מכשירי Bluetooth ללא שמות"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 99fd1d3..3af8728 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -252,8 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"ವೈರ್‌ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"ವೈ-ಫೈ ಸ್ಕ್ಯಾನ್ ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತಿದೆ"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ವೈ-ಫೈ ನಿರಂತರವಲ್ಲದ MAC ಯಾದೃಚ್ಛಿಕರಣ"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"ಟೆಥರಿಂಗ್‍‍ಗಾಗಿ ಹಾರ್ಡ್‍ವೇರ್ ವೇಗವರ್ಧನೆ"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"ಹೆಸರುಗಳಿಲ್ಲದ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ತೋರಿಸಿ"</string>
@@ -285,8 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"ವೈರ್‌ಲೆಸ್‌‌‌ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ಬ್ಯಾಟರಿ ಹೆಚ್ಚು ಬಾಳಿಕೆ ಬರುವಂತೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನೆಟ್‌ವರ್ಕ್‌ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ಈ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ ಈ ಸಾಧನದ MAC ವಿಳಾಸವು ಪ್ರತಿ ಬಾರಿಯೂ ಬದಲಾಗಬಹುದು."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0b0a4a6..95e6f63 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -252,8 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"वाय-फाय व्हर्बोझ लॉगिंग सुरू करा"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"वाय-फाय स्कॅन थ्रॉटलिंग"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"वाय-फायचे सातत्याने न होणारे MAC रँडमायझेशन"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा नेहमी सक्रिय"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"टेदरिंग हार्डवेअर अ‍ॅक्सिलरेशन"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नावांशिवाय ब्‍लूटूथ डिव्‍हाइस दाखवा"</string>
@@ -285,8 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाय-फाय लॉगिंग स्‍तर वाढवा, वाय-फाय सिलेक्टरमध्‍ये प्रति SSID RSSI दर्शवा"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"बॅटरी जलदरीतीने संपण्यापासून रोखते आणि नेटवर्क परफॉर्मन्समध्ये सुधारणा करते"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"हा मोड सुरू केलेला असले तेव्हा, हे डिव्हाइस MAC रँडमायझेशन सुरू केलेल्या नेटवर्कशी कनेक्ट होताना प्रत्येक वेळी त्याचा MAC अ‍ॅड्रेस बदलू शकतो."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"मीटरने मोजलेले"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"मीटरने न मोजलेले"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफर आकार"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b004082..c088d85 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -252,8 +252,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"Certifikimi i ekranit pa tel"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivizo hyrjen Wi-Fi Verbose"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Përshpejtimi i skanimit të Wi‑Fi"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Renditje e rastësishme jo e përhershme e MAC për Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"Të dhënat celulare gjithmonë aktive"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"Përshpejtimi i harduerit për ndarjen e lidhjes (internet)"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Shfaq pajisjet me Bluetooth pa emra"</string>
@@ -285,8 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Shfaq opsionet për certifikimin e ekranit pa tel"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Zvogëlon shkarkimin e baterisë dhe përmirëson cilësinë e funksionimit të rrjetit"</string>
-    <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
-    <skip />
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Kur ky modalitet është i aktivizuar, adresa MAC e kësaj pajisjeje mund të ndryshojë çdo herë që lidhet me një rrjet që ka të aktivizuar renditjen e rastësishme të adresave MAC."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"Me matje"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Pa matje"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"Madhësitë e regjistruesit"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 71e4fe2..db8edf7 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -489,7 +489,7 @@
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"సక్రియ ఇన్‌పుట్ పద్ధతులు"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"సిస్టమ్ భాషలను ఉపయోగించు"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> యొక్క సెట్టింగ్‌లను తెరవడం విఫలమైంది"</string>
-    <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్‌పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్‌వర్డ్‌లు మరియు క్రెడిట్ కార్డు నంబర్‌ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> అనువర్తనంలో అందించబడుతుంది. ఈ ఇన్‌పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
+    <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్‌పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్‌వర్డ్‌లు మరియు క్రెడిట్ కార్డు నంబర్‌ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> యాప్‌లో అందించబడుతుంది. ఈ ఇన్‌పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్‌ను అన్‌లాక్ చేసే వరకు ఈ యాప్ ప్రారంభం కాదు"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS నమోదు స్థితి"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"నమోదు చేయబడింది"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 79446e4..ed8d524 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -44,6 +44,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.RequiresApi;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -56,6 +58,7 @@
 /**
  * InfoMediaManager provide interface to get InfoMediaDevice list.
  */
+@RequiresApi(Build.VERSION_CODES.R)
 public class InfoMediaManager extends MediaManager {
 
     private static final String TAG = "InfoMediaManager";
@@ -145,9 +148,16 @@
     }
 
     private RoutingSessionInfo getRoutingSessionInfo() {
-        final List<RoutingSessionInfo> sessionInfos =
-                mRouterManager.getRoutingSessions(mPackageName);
+        return getRoutingSessionInfo(mPackageName);
+    }
 
+    private RoutingSessionInfo getRoutingSessionInfo(String packageName) {
+        final List<RoutingSessionInfo> sessionInfos =
+                mRouterManager.getRoutingSessions(packageName);
+
+        if (sessionInfos == null || sessionInfos.isEmpty()) {
+            return null;
+        }
         return sessionInfos.get(sessionInfos.size() - 1);
     }
 
@@ -367,33 +377,13 @@
     }
 
     boolean shouldDisableMediaOutput(String packageName) {
-        boolean shouldDisableMediaOutput = false;
         if (TextUtils.isEmpty(packageName)) {
             Log.w(TAG, "shouldDisableMediaOutput() package name is null or empty!");
-            return false;
+            return true;
         }
-        final List<MediaRoute2Info> infos = mRouterManager.getTransferableRoutes(packageName);
-        if (infos.size() == 1) {
-            final MediaRoute2Info info = infos.get(0);
-            final int deviceType = info.getType();
-            switch (deviceType) {
-                case TYPE_UNKNOWN:
-                case TYPE_REMOTE_TV:
-                case TYPE_REMOTE_SPEAKER:
-                case TYPE_GROUP:
-                    shouldDisableMediaOutput = true;
-                    break;
-                default:
-                    shouldDisableMediaOutput = false;
-                    break;
-            }
-        }
-        if (DEBUG) {
-            Log.d(TAG, "shouldDisableMediaOutput() MediaRoute2Info size : " + infos.size()
-                    + ", package name : " + packageName + ", shouldDisableMediaOutput : "
-                    + shouldDisableMediaOutput);
-        }
-        return shouldDisableMediaOutput;
+
+        // Disable when there is no transferable route
+        return mRouterManager.getTransferableRoutes(packageName).isEmpty();
     }
 
     @TargetApi(Build.VERSION_CODES.R)
@@ -456,7 +446,7 @@
     }
 
     private void buildAvailableRoutes() {
-        for (MediaRoute2Info route : mRouterManager.getTransferableRoutes(mPackageName)) {
+        for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
             if (DEBUG) {
                 Log.d(TAG, "buildAvailableRoutes() route : " + route.getName() + ", volume : "
                         + route.getVolume() + ", type : " + route.getType());
@@ -465,6 +455,29 @@
         }
     }
 
+    private List<MediaRoute2Info> getAvailableRoutes(String packageName) {
+        final List<MediaRoute2Info> infos = new ArrayList<>();
+        RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo(packageName);
+        if (routingSessionInfo != null) {
+            infos.addAll(mRouterManager.getSelectedRoutes(routingSessionInfo));
+        }
+        final List<MediaRoute2Info> transferableRoutes =
+                mRouterManager.getTransferableRoutes(packageName);
+        for (MediaRoute2Info transferableRoute : transferableRoutes) {
+            boolean alreadyAdded = false;
+            for (MediaRoute2Info mediaRoute2Info : infos) {
+                if (TextUtils.equals(transferableRoute.getId(), mediaRoute2Info.getId())) {
+                    alreadyAdded = true;
+                    break;
+                }
+            }
+            if (!alreadyAdded) {
+                infos.add(transferableRoute);
+            }
+        }
+        return infos;
+    }
+
     @VisibleForTesting
     void addMediaDevice(MediaRoute2Info route) {
         final int deviceType = route.getType();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index a8da2c0..22001c9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -22,11 +22,13 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 import android.media.RoutingSessionInfo;
+import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.bluetooth.A2dpProfile;
@@ -49,6 +51,7 @@
 /**
  * LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
  */
+@RequiresApi(Build.VERSION_CODES.R)
 public class LocalMediaManager implements BluetoothCallback {
     private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
     private static final String TAG = "LocalMediaManager";
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 294399e..6bb125b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3588,7 +3588,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 204;
+            private static final int SETTINGS_VERSION = 205;
 
             private final int mUserId;
 
@@ -5399,6 +5399,44 @@
                         currentVersion = 204;
                 }
 
+                if (currentVersion == 204) {
+                    // Version 204: Replace 'wifi' or 'cell' tiles with 'internet' if existed.
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    final Setting currentValue = secureSettings.getSettingLocked(Secure.QS_TILES);
+                    if (!currentValue.isNull()) {
+                        String tileList = currentValue.getValue();
+                        String[] tileSplit = tileList.split(",");
+                        final ArrayList<String> tiles = new ArrayList<String>();
+                        boolean hasInternetTile = false;
+                        for (int i = 0; i < tileSplit.length; i++) {
+                            String tile = tileSplit[i].trim();
+                            if (tile.isEmpty()) continue;
+                            tiles.add(tile);
+                            if (tile.equals("internet")) hasInternetTile = true;
+                        }
+                        if (!hasInternetTile) {
+                            if (tiles.contains("wifi")) {
+                                // Replace the WiFi with Internet, and remove the Cell
+                                tiles.set(tiles.indexOf("wifi"), "internet");
+                                tiles.remove("cell");
+                            } else if (tiles.contains("cell")) {
+                                // Replace the Cell with Internet
+                                tiles.set(tiles.indexOf("cell"), "internet");
+                            }
+                        } else {
+                            tiles.remove("wifi");
+                            tiles.remove("cell");
+                        }
+                        secureSettings.insertSettingOverrideableByRestoreLocked(
+                                Secure.QS_TILES,
+                                TextUtils.join(",", tiles),
+                                null /* tag */,
+                                true /* makeDefault */,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 205;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml b/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml
new file mode 100644
index 0000000..181ba07
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+-->
+<com.android.systemui.qs.QSFooterActionsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/qs_footer_actions_container"
+    android:layout_width="match_parent"
+    android:layout_height="48dp"
+    android:gravity="center_vertical">
+
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:id="@android:id/edit"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/qs_footer_action_button_size"
+        android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+        android:layout_weight="1"
+        android:background="@drawable/qs_footer_action_chip_background"
+        android:clickable="true"
+        android:clipToPadding="false"
+        android:contentDescription="@string/accessibility_quick_settings_edit"
+        android:focusable="true"
+        android:padding="@dimen/qs_footer_icon_padding"
+        android:src="@*android:drawable/ic_mode_edit"
+        android:tint="?android:attr/textColorPrimary" />
+
+    <com.android.systemui.statusbar.phone.MultiUserSwitch
+        android:id="@+id/multi_user_switch"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/qs_footer_action_button_size"
+        android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+        android:layout_weight="1"
+        android:background="@drawable/qs_footer_action_chip_background"
+        android:focusable="true">
+
+        <ImageView
+            android:id="@+id/multi_user_avatar"
+            android:layout_width="@dimen/multi_user_avatar_expanded_size"
+            android:layout_height="@dimen/multi_user_avatar_expanded_size"
+            android:layout_gravity="center"
+            android:scaleType="centerInside" />
+    </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:id="@+id/pm_lite"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/qs_footer_action_button_size"
+        android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+        android:layout_weight="1"
+        android:background="@drawable/qs_footer_action_chip_background"
+        android:clickable="true"
+        android:clipToPadding="false"
+        android:focusable="true"
+        android:padding="@dimen/qs_footer_icon_padding"
+        android:src="@*android:drawable/ic_lock_power_off"
+        android:contentDescription="@string/accessibility_quick_settings_power_menu"
+        android:tint="?android:attr/textColorPrimary" />
+
+    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+        android:id="@+id/settings_button_container"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/qs_footer_action_button_size"
+        android:background="@drawable/qs_footer_action_chip_background"
+        android:layout_weight="1"
+        android:clipChildren="false"
+        android:clipToPadding="false">
+
+        <com.android.systemui.statusbar.phone.SettingsButton
+            android:id="@+id/settings_button"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/qs_footer_action_button_size"
+            android:layout_gravity="center"
+            android:contentDescription="@string/accessibility_quick_settings_settings"
+            android:background="@drawable/qs_footer_action_chip_background_borderless"
+            android:padding="@dimen/qs_footer_icon_padding"
+            android:scaleType="centerInside"
+            android:src="@drawable/ic_settings"
+            android:tint="?android:attr/textColorPrimary" />
+
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:id="@+id/tuner_icon"
+            android:layout_width="8dp"
+            android:layout_height="8dp"
+            android:layout_gravity="center_horizontal|bottom"
+            android:layout_marginBottom="@dimen/qs_footer_icon_padding"
+            android:src="@drawable/tuner"
+            android:tint="?android:attr/textColorTertiary"
+            android:visibility="invisible" />
+
+    </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+</com.android.systemui.qs.QSFooterActionsView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/fp_to_unlock.xml b/packages/SystemUI/res/anim/fp_to_unlock.xml
index a348208..a5f75b6 100644
--- a/packages/SystemUI/res/anim/fp_to_unlock.xml
+++ b/packages/SystemUI/res/anim/fp_to_unlock.xml
@@ -19,10 +19,10 @@
       <group android:name="_R_G">
         <group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
           <group android:name="_R_G_L_1_G" android:translateX="30.75" android:translateY="25.75">
-            <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
-            <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
-            <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
-            <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
+            <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
+            <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
+            <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
+            <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
           </group>
         </group>
         <group android:name="_R_G_L_0_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
diff --git a/packages/SystemUI/res/anim/lock_to_unlock.xml b/packages/SystemUI/res/anim/lock_to_unlock.xml
index ec51c01..76f7a05 100644
--- a/packages/SystemUI/res/anim/lock_to_unlock.xml
+++ b/packages/SystemUI/res/anim/lock_to_unlock.xml
@@ -21,7 +21,7 @@
           <group android:name="_R_G_L_2_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
             <group android:name="_R_G_L_2_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
               <group android:name="_R_G_L_2_G" android:translateX="-0.375" android:translateY="-22.375">
-                <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
+                <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
               </group>
             </group>
           </group>
@@ -30,7 +30,7 @@
           <group android:name="_R_G_L_1_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
             <group android:name="_R_G_L_1_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
               <group android:name="_R_G_L_1_G" android:translateX="5" android:translateY="-22.5">
-                <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
+                <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
               </group>
             </group>
           </group>
diff --git a/packages/SystemUI/res/drawable/ic_unlock.xml b/packages/SystemUI/res/drawable/ic_unlock.xml
index c3b3469..46023e6 100644
--- a/packages/SystemUI/res/drawable/ic_unlock.xml
+++ b/packages/SystemUI/res/drawable/ic_unlock.xml
@@ -21,7 +21,7 @@
             android:strokeColor="#FF000000"
             android:strokeLineCap="round"
             android:strokeLineJoin="round"
-            android:strokeWidth="2.5"
+            android:strokeWidth="2"
             android:pathData="M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
     </group>
     <group android:translateX="14" android:translateY="13.5">
@@ -29,7 +29,7 @@
             android:strokeColor="#FF000000"
             android:strokeLineCap="round"
             android:strokeLineJoin="round"
-            android:strokeWidth="2.5"
+            android:strokeWidth="2"
             android:pathData="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
     </group>
     <group android:translateX="20" android:translateY="35.75">
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 317dbc0..fe0b14a 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -68,93 +68,8 @@
 
         </LinearLayout>
 
-        <LinearLayout
-            android:id="@+id/qs_footer_actions_container"
-            android:layout_width="match_parent"
-            android:layout_height="48dp"
-            android:gravity="center_vertical">
+        <include layout="@layout/qs_footer_actions"/>
 
-            <com.android.systemui.statusbar.AlphaOptimizedImageView
-                android:id="@android:id/edit"
-                android:layout_width="0dp"
-                android:layout_height="@dimen/qs_footer_action_button_size"
-                android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
-                android:layout_weight="1"
-                android:background="@drawable/qs_footer_action_chip_background"
-                android:clickable="true"
-                android:clipToPadding="false"
-                android:contentDescription="@string/accessibility_quick_settings_edit"
-                android:focusable="true"
-                android:padding="@dimen/qs_footer_icon_padding"
-                android:src="@*android:drawable/ic_mode_edit"
-                android:tint="?android:attr/textColorPrimary" />
-
-            <com.android.systemui.statusbar.phone.MultiUserSwitch
-                android:id="@+id/multi_user_switch"
-                android:layout_width="0dp"
-                android:layout_height="@dimen/qs_footer_action_button_size"
-                android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
-                android:layout_weight="1"
-                android:background="@drawable/qs_footer_action_chip_background"
-                android:focusable="true">
-
-                <ImageView
-                    android:id="@+id/multi_user_avatar"
-                    android:layout_width="@dimen/multi_user_avatar_expanded_size"
-                    android:layout_height="@dimen/multi_user_avatar_expanded_size"
-                    android:layout_gravity="center"
-                    android:scaleType="centerInside" />
-            </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
-            <com.android.systemui.statusbar.AlphaOptimizedImageView
-                android:id="@+id/pm_lite"
-                android:layout_width="0dp"
-                android:layout_height="@dimen/qs_footer_action_button_size"
-                android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
-                android:layout_weight="1"
-                android:background="@drawable/qs_footer_action_chip_background"
-                android:clickable="true"
-                android:clipToPadding="false"
-                android:focusable="true"
-                android:padding="@dimen/qs_footer_icon_padding"
-                android:src="@*android:drawable/ic_lock_power_off"
-                android:contentDescription="@string/accessibility_quick_settings_power_menu"
-                android:tint="?android:attr/textColorPrimary" />
-
-            <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
-                android:id="@+id/settings_button_container"
-                android:layout_width="0dp"
-                android:layout_height="@dimen/qs_footer_action_button_size"
-                android:background="@drawable/qs_footer_action_chip_background"
-                android:layout_weight="1"
-                android:clipChildren="false"
-                android:clipToPadding="false">
-
-                <com.android.systemui.statusbar.phone.SettingsButton
-                    android:id="@+id/settings_button"
-                    android:layout_width="match_parent"
-                    android:layout_height="@dimen/qs_footer_action_button_size"
-                    android:layout_gravity="center"
-                    android:contentDescription="@string/accessibility_quick_settings_settings"
-                    android:background="@drawable/qs_footer_action_chip_background_borderless"
-                    android:padding="@dimen/qs_footer_icon_padding"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_settings"
-                    android:tint="?android:attr/textColorPrimary" />
-
-                <com.android.systemui.statusbar.AlphaOptimizedImageView
-                    android:id="@+id/tuner_icon"
-                    android:layout_width="8dp"
-                    android:layout_height="8dp"
-                    android:layout_gravity="center_horizontal|bottom"
-                    android:layout_marginBottom="@dimen/qs_footer_icon_padding"
-                    android:src="@drawable/tuner"
-                    android:tint="?android:attr/textColorTertiary"
-                    android:visibility="invisible" />
-
-            </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
-        </LinearLayout>
     </LinearLayout>
 
 </com.android.systemui.qs.QSFooterView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index e37a3f0..0c3c602 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -68,7 +68,7 @@
             android:id="@+id/lock_icon"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:padding="48px"
+            android:padding="@dimen/lock_icon_padding"
             android:layout_gravity="center"
             android:scaleType="centerCrop"/>
     </com.android.keyguard.LockIconView>
diff --git a/packages/SystemUI/res/layout/udfps_keyguard_view.xml b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
index 18517906..a9eb27a 100644
--- a/packages/SystemUI/res/layout/udfps_keyguard_view.xml
+++ b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
@@ -34,7 +34,7 @@
         android:id="@+id/udfps_aod_fp"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:padding="48px"
+        android:padding="@dimen/lock_icon_padding"
         android:layout_gravity="center"
         android:scaleType="centerCrop"
         app:lottie_autoPlay="false"
@@ -46,7 +46,7 @@
         android:id="@+id/udfps_lockscreen_fp"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:padding="48px"
+        android:padding="@dimen/lock_icon_padding"
         android:layout_gravity="center"
         android:scaleType="centerCrop"
         app:lottie_autoPlay="false"
diff --git a/packages/SystemUI/res/raw/udfps_aod_fp.json b/packages/SystemUI/res/raw/udfps_aod_fp.json
index 3247fe7..3b273ff 100644
--- a/packages/SystemUI/res/raw/udfps_aod_fp.json
+++ b/packages/SystemUI/res/raw/udfps_aod_fp.json
@@ -164,7 +164,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -526,7 +526,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -829,7 +829,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -1132,7 +1132,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -1507,7 +1507,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -1882,7 +1882,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -2257,7 +2257,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
@@ -2560,7 +2560,7 @@
               },
               "w":{
                 "a":0,
-                "k":1,
+                "k":1.3,
                 "ix":5
               },
               "lc":2,
diff --git a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
index a25a475..a30a03a 100644
--- a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
+++ b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
@@ -1 +1 @@
-{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]}
\ No newline at end of file
+{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 721e1f3..10b0f79 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -110,7 +110,7 @@
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        internet,wifi,cell,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
+        internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
     </string>
 
     <!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a12fd2b..28233f8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -538,6 +538,9 @@
     <!-- Gravity for the notification panel -->
     <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
 
+    <!-- Padding for the lock icon on the keyguard. In pixels - should not scale with display size. -->
+    <dimen name="lock_icon_padding">48px</dimen>
+
     <!-- Height of the carrier/wifi name label -->
     <dimen name="carrier_label_height">24dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a8812bf..b9002c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -438,6 +438,8 @@
     <string name="fingerprint_dialog_use_fingerprint">Use your fingerprint to continue</string>
     <!-- Message shown to ask the user to use screenlock to continue.[CHAR LIMIT=NONE] -->
     <string name="fingerprint_dialog_cant_recognize_fp_use_screenlock">Can\u2019t recognize fingerprint. Use screen lock instead.</string>
+    <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
+    <string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
 
     <!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
     <string name="face_dialog_looking_for_face">Looking for you\u2026</string>
@@ -3012,6 +3014,8 @@
     <string name="pref_title_network_details" msgid="7329759534269363308">"Network details"</string>
     <!-- Provider Model: Panel subtitle for tapping a network to connect to internet. [CHAR LIMIT=60] -->
     <string name="tap_a_network_to_connect">Tap a network to connect</string>
+    <!-- Provider Model: Panel subtitle for unlocking screen to view networks. [CHAR LIMIT=60] -->
+    <string name="unlock_to_view_networks">Unlock to view networks</string>
     <!-- Provider Model: Wi-Fi settings. text displayed when Wi-Fi is on and network list is empty [CHAR LIMIT=50]-->
     <string name="wifi_empty_list_wifi_on">Searching for networks\u2026</string>
     <!-- Provider Model: Failure notification for connect -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ad196ef..6908409 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -347,13 +347,16 @@
     private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
     private static final int HAL_ERROR_RETRY_MAX = 20;
 
-    private final Runnable mCancelNotReceived = new Runnable() {
-        @Override
-        public void run() {
-            Log.w(TAG, "Cancel not received, transitioning to STOPPED");
-            mFingerprintRunningState = mFaceRunningState = BIOMETRIC_STATE_STOPPED;
-            updateBiometricListeningState();
-        }
+    private final Runnable mFpCancelNotReceived = () -> {
+        Log.e(TAG, "Fp cancellation not received, transitioning to STOPPED");
+        mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+        updateFingerprintListeningState();
+    };
+
+    private final Runnable mFaceCancelNotReceived = () -> {
+        Log.e(TAG, "Face cancellation not received, transitioning to STOPPED");
+        mFaceRunningState = BIOMETRIC_STATE_STOPPED;
+        updateFaceListeningState();
     };
 
     private final Handler mHandler;
@@ -791,19 +794,19 @@
 
     private void handleFingerprintError(int msgId, String errString) {
         Assert.isMainThread();
-        if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks(
-                mCancelNotReceived)) {
-            mHandler.removeCallbacks(mCancelNotReceived);
+        if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+            mHandler.removeCallbacks(mFpCancelNotReceived);
         }
 
+        // Error is always the end of authentication lifecycle.
+        mFingerprintCancelSignal = null;
+
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
                 && mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
             updateFingerprintListeningState();
         } else {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
-            mFingerprintCancelSignal = null;
-            mFaceCancelSignal = null;
         }
 
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
@@ -905,6 +908,7 @@
 
     private void handleFaceAuthFailed() {
         Assert.isMainThread();
+        mFaceCancelSignal = null;
         setFaceRunningState(BIOMETRIC_STATE_STOPPED);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -983,10 +987,13 @@
     private void handleFaceError(int msgId, String errString) {
         Assert.isMainThread();
         if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
-        if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) {
-            mHandler.removeCallbacks(mCancelNotReceived);
+        if (mHandler.hasCallbacks(mFaceCancelNotReceived)) {
+            mHandler.removeCallbacks(mFaceCancelNotReceived);
         }
 
+        // Error is always the end of authentication lifecycle
+        mFaceCancelSignal = null;
+
         if (msgId == FaceManager.FACE_ERROR_CANCELED
                 && mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
             setFaceRunningState(BIOMETRIC_STATE_STOPPED);
@@ -2368,6 +2375,14 @@
     }
 
     private void startListeningForFingerprint() {
+        final int userId = getCurrentUser();
+        final boolean unlockPossible = isUnlockWithFingerprintPossible(userId);
+        if (mFingerprintCancelSignal != null) {
+            Log.e(TAG, "Cancellation signal is not null, high chance of bug in fp auth lifecycle"
+                    + " management. FP state: " + mFingerprintRunningState
+                    + ", unlockPossible: " + unlockPossible);
+        }
+
         if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) {
             setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
             return;
@@ -2377,11 +2392,8 @@
             return;
         }
         if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
-        int userId = getCurrentUser();
-        if (isUnlockWithFingerprintPossible(userId)) {
-            if (mFingerprintCancelSignal != null) {
-                mFingerprintCancelSignal.cancel();
-            }
+
+        if (unlockPossible) {
             mFingerprintCancelSignal = new CancellationSignal();
 
             if (isEncryptedOrLockdown(userId)) {
@@ -2397,6 +2409,14 @@
     }
 
     private void startListeningForFace() {
+        final int userId = getCurrentUser();
+        final boolean unlockPossible = isUnlockWithFacePossible(userId);
+        if (mFaceCancelSignal != null) {
+            Log.e(TAG, "Cancellation signal is not null, high chance of bug in face auth lifecycle"
+                    + " management. Face state: " + mFaceRunningState
+                    + ", unlockPossible: " + unlockPossible);
+        }
+
         if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
             setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
             return;
@@ -2405,11 +2425,8 @@
             return;
         }
         if (DEBUG) Log.v(TAG, "startListeningForFace(): " + mFaceRunningState);
-        int userId = getCurrentUser();
-        if (isUnlockWithFacePossible(userId)) {
-            if (mFaceCancelSignal != null) {
-                mFaceCancelSignal.cancel();
-            }
+
+        if (unlockPossible) {
             mFaceCancelSignal = new CancellationSignal();
 
             // This would need to be updated for multi-sensor devices
@@ -2461,9 +2478,8 @@
             if (mFingerprintCancelSignal != null) {
                 mFingerprintCancelSignal.cancel();
                 mFingerprintCancelSignal = null;
-                if (!mHandler.hasCallbacks(mCancelNotReceived)) {
-                    mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
-                }
+                mHandler.removeCallbacks(mFpCancelNotReceived);
+                mHandler.postDelayed(mFpCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
             }
             setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING);
         }
@@ -2478,9 +2494,8 @@
             if (mFaceCancelSignal != null) {
                 mFaceCancelSignal.cancel();
                 mFaceCancelSignal = null;
-                if (!mHandler.hasCallbacks(mCancelNotReceived)) {
-                    mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
-                }
+                mHandler.removeCallbacks(mFaceCancelNotReceived);
+                mHandler.postDelayed(mFaceCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
             }
             setFaceRunningState(BIOMETRIC_STATE_CANCELLING);
         }
@@ -2842,6 +2857,11 @@
             mSecureCameraLaunched = false;
         }
 
+        if (mKeyguardBypassController != null) {
+            // LS visibility has changed, so reset deviceEntryIntent
+            mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+        }
+
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index d122610..d46426a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -23,7 +23,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
@@ -68,8 +67,6 @@
     private float mBurnInProgress;
     private float mInterpolatedDarkAmount;
 
-    private ValueAnimator mHintAnimator;
-
     public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -94,9 +91,6 @@
                 new KeyPath("**"), LottieProperty.COLOR_FILTER,
                 frameInfo -> new PorterDuffColorFilter(mTextColorPrimary, PorterDuff.Mode.SRC_ATOP)
         );
-
-        mHintAnimator = ObjectAnimator.ofFloat(mLockScreenFp, "progress", 1f, 0f, 1f);
-        mHintAnimator.setDuration(4000);
     }
 
     @Override
@@ -183,19 +177,11 @@
     }
 
     void onDozeAmountChanged(float linear, float eased) {
-        mHintAnimator.cancel();
         mInterpolatedDarkAmount = eased;
         updateAlpha();
         updateBurnInOffsets();
     }
 
-    void animateHint() {
-        if (!isShadeLocked() && !mUdfpsRequested && mAlpha == 255
-                && mLockScreenFp.isVisibleToUser()) {
-            mHintAnimator.start();
-        }
-    }
-
     /**
      * Animates in the bg protection circle behind the fp icon to highlight the icon.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 102dc41..79a4a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -20,14 +20,10 @@
 
 import android.annotation.NonNull;
 import android.content.res.Configuration;
-import android.hardware.biometrics.BiometricSourceType;
 import android.util.MathUtils;
 import android.view.MotionEvent;
 
-import androidx.annotation.Nullable;
-
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -47,14 +43,8 @@
 
 /**
  * Class that coordinates non-HBM animations during keyguard authentication.
- *
- * Highlights the udfps icon when:
- * - Face authentication has failed
- * - Face authentication has been run for > 2 seconds
  */
 public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
-    private static final long AFTER_FACE_AUTH_HINT_DELAY = 2000;
-
     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @NonNull private final DelayableExecutor mExecutor;
@@ -63,12 +53,10 @@
     @NonNull private final ConfigurationController mConfigurationController;
     @NonNull private final UdfpsController mUdfpsController;
 
-    @Nullable private Runnable mCancelDelayedHintRunnable;
     private boolean mShowingUdfpsBouncer;
     private boolean mUdfpsRequested;
     private boolean mQsExpanded;
     private boolean mFaceDetectRunning;
-    private boolean mHintShown;
     private int mStatusBarState;
     private float mTransitionToFullShadeProgress;
     private float mLastDozeAmount;
@@ -111,10 +99,6 @@
     @Override
     protected void onViewAttached() {
         super.onViewAttached();
-        mHintShown = false;
-        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
-        updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
-
         final float dozeAmount = mStatusBarStateController.getDozeAmount();
         mLastDozeAmount = dozeAmount;
         mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
@@ -137,7 +121,6 @@
     @Override
     protected void onViewDetached() {
         super.onViewDetached();
-        mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
         mFaceDetectRunning = false;
 
         mStatusBarStateController.removeCallback(mStateListener);
@@ -147,11 +130,6 @@
         if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
             mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
         }
-
-        if (mCancelDelayedHintRunnable != null) {
-            mCancelDelayedHintRunnable.run();
-            mCancelDelayedHintRunnable = null;
-        }
     }
 
     @Override
@@ -250,36 +228,6 @@
         }
     }
 
-    private void cancelDelayedHint() {
-        if (mCancelDelayedHintRunnable != null) {
-            mCancelDelayedHintRunnable.run();
-            mCancelDelayedHintRunnable = null;
-        }
-    }
-
-    private void updateFaceDetectRunning(boolean running) {
-        if (mFaceDetectRunning == running) {
-            return;
-        }
-
-        // show udfps hint a few seconds after face auth started running
-        if (!mFaceDetectRunning && running && !mHintShown && mCancelDelayedHintRunnable == null) {
-            // Face detect started running, show udfps hint after a delay
-            mCancelDelayedHintRunnable = mExecutor.executeDelayed(() -> showHint(false),
-                    AFTER_FACE_AUTH_HINT_DELAY);
-        }
-
-        mFaceDetectRunning = running;
-    }
-
-    private void showHint(boolean forceShow) {
-        cancelDelayedHint();
-        if (!mHintShown || forceShow) {
-            mHintShown = true;
-            mView.animateHint();
-        }
-    }
-
     /**
      * Set the progress we're currently transitioning to the full shade. 0.0f means we're not
      * transitioning yet, while 1.0f means we've fully dragged down.
@@ -319,39 +267,6 @@
         }
     };
 
-    private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
-            new KeyguardUpdateMonitorCallback() {
-                public void onBiometricRunningStateChanged(boolean running,
-                        BiometricSourceType biometricSourceType) {
-                    if (biometricSourceType == BiometricSourceType.FACE) {
-                        updateFaceDetectRunning(running);
-                    }
-                }
-
-                public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
-                    if (biometricSourceType == BiometricSourceType.FACE) {
-                        // show udfps hint when face auth fails
-                        showHint(true);
-                    }
-                }
-
-                public void onBiometricError(int msgId, String errString,
-                        BiometricSourceType biometricSourceType) {
-                    if (biometricSourceType == BiometricSourceType.FACE) {
-                        // show udfps hint when face auth fails
-                        showHint(true);
-                    }
-                }
-
-                public void onBiometricAuthenticated(int userId,
-                        BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
-                    if (biometricSourceType == BiometricSourceType.FACE) {
-                        // cancel delayed hint if face auth succeeded
-                        cancelDelayedHint();
-                    }
-                }
-            };
-
     private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
             new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 543004e..1ca2217 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -116,7 +116,7 @@
     private final TaskbarDelegate mTaskbarDelegate;
     private final NotificationShadeDepthController mNotificationShadeDepthController;
     private int mNavMode;
-    private boolean mIsTablet;
+    @VisibleForTesting boolean mIsTablet;
     private final UserTracker mUserTracker;
 
     /** A displayId - nav bar maps. */
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 2bf4bf4..aaa3bf0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -106,7 +106,7 @@
     static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
 
     private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
-            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", true);
+            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
 
     private ISystemGestureExclusionListener mGestureExclusionListener =
             new ISystemGestureExclusionListener.Stub() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index ce1066e..1bd3664 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -268,7 +268,7 @@
     }
 
     @Override
-    public void setExpansion(float expansion) {
+    public void setExpansion(float expansion, float proposedTranslation) {
         mLastExpansion = expansion;
         updateSelected();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index e38bd4b..0e0681b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -35,11 +35,6 @@
     void setExpanded(boolean expanded);
 
     /**
-     * Returns the full height of the footer.
-     */
-    int getHeight();
-
-    /**
      * Sets the percentage amount that the quick settings has been expanded.
      *
      * @param expansion A value from 1 to 0 that indicates how much the quick settings have been
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt
new file mode 100644
index 0000000..dbf62a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt
@@ -0,0 +1,167 @@
+package com.android.systemui.qs
+
+import android.content.Intent
+import android.os.UserManager
+import android.provider.Settings
+import android.view.View
+import android.widget.Toast
+import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.nano.MetricsProto
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.phone.SettingsButton
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.ViewController
+import javax.inject.Inject
+import javax.inject.Named
+
+class QSFooterActionsController @Inject constructor(
+    view: QSFooterActionsView,
+    private val qsPanelController: QSPanelController,
+    private val activityStarter: ActivityStarter,
+    private val userManager: UserManager,
+    private val userInfoController: UserInfoController,
+    private val multiUserSwitchController: MultiUserSwitchController,
+    private val deviceProvisionedController: DeviceProvisionedController,
+    private val falsingManager: FalsingManager,
+    private val metricsLogger: MetricsLogger,
+    private val tunerService: TunerService,
+    private val globalActionsDialog: GlobalActionsDialogLite,
+    private val uiEventLogger: UiEventLogger,
+    @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean
+) : ViewController<QSFooterActionsView>(view) {
+
+    private var listening: Boolean = false
+    var expanded = false
+        set(value) {
+            field = value
+            mView.setExpanded(value, isTunerEnabled(),
+                    multiUserSwitchController.isMultiUserEnabled)
+        }
+
+    private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button)
+    private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container)
+    private val editButton: View = view.findViewById(android.R.id.edit)
+    private val powerMenuLite: View = view.findViewById(R.id.pm_lite)
+
+    private val onUserInfoChangedListener = OnUserInfoChangedListener { _, picture, _ ->
+        val isGuestUser: Boolean = userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser())
+        mView.onUserInfoChanged(picture, isGuestUser)
+    }
+
+    private val onClickListener = View.OnClickListener { v ->
+        // Don't do anything until views are unhidden. Don't do anything if the tap looks
+        // suspicious.
+        if (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+            return@OnClickListener
+        }
+        if (v === settingsButton) {
+            if (!deviceProvisionedController.isCurrentUserSetup) {
+                // If user isn't setup just unlock the device and dump them back at SUW.
+                activityStarter.postQSRunnableDismissingKeyguard {}
+                return@OnClickListener
+            }
+            metricsLogger.action(
+                    if (expanded) MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+                    else MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH)
+            if (settingsButton.isTunerClick) {
+                activityStarter.postQSRunnableDismissingKeyguard {
+                    if (isTunerEnabled()) {
+                        tunerService.showResetRequest {
+                            // Relaunch settings so that the tuner disappears.
+                            startSettingsActivity()
+                        }
+                    } else {
+                        Toast.makeText(context, R.string.tuner_toast, Toast.LENGTH_LONG).show()
+                        tunerService.isTunerEnabled = true
+                    }
+                    startSettingsActivity()
+                }
+            } else {
+                startSettingsActivity()
+            }
+        } else if (v === powerMenuLite) {
+            uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+            globalActionsDialog.showOrHideDialog(false, true)
+        }
+    }
+
+    override fun onInit() {
+        multiUserSwitchController.init()
+    }
+
+    private fun startSettingsActivity() {
+        val animationController = settingsButtonContainer?.let {
+            ActivityLaunchAnimator.Controller.fromView(
+                    it,
+                    InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON)
+            }
+        activityStarter.startActivity(Intent(Settings.ACTION_SETTINGS),
+                true /* dismissShade */, animationController)
+    }
+
+    @VisibleForTesting
+    public override fun onViewAttached() {
+        if (showPMLiteButton) {
+            powerMenuLite.visibility = View.VISIBLE
+            powerMenuLite.setOnClickListener(onClickListener)
+        } else {
+            powerMenuLite.visibility = View.GONE
+        }
+        settingsButton.setOnClickListener(onClickListener)
+        editButton.setOnClickListener(View.OnClickListener { view: View? ->
+            if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                return@OnClickListener
+            }
+            activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) }
+        })
+
+        mView.updateEverything(isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
+    }
+
+    override fun onViewDetached() {
+        setListening(false)
+    }
+
+    fun setListening(listening: Boolean) {
+        if (this.listening == listening) {
+            return
+        }
+        this.listening = listening
+        if (this.listening) {
+            userInfoController.addCallback(onUserInfoChangedListener)
+        } else {
+            userInfoController.removeCallback(onUserInfoChangedListener)
+        }
+    }
+
+    fun disable(state2: Int) {
+        mView.disable(state2, isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
+    }
+
+    fun setExpansion(headerExpansionFraction: Float) {
+        mView.setExpansion(headerExpansionFraction)
+    }
+
+    fun updateAnimator(width: Int, numTiles: Int) {
+        mView.updateAnimator(width, numTiles)
+    }
+
+    fun setKeyguardShowing() {
+        mView.setKeyguardShowing()
+    }
+
+    private fun isTunerEnabled() = tunerService.isTunerEnabled
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt
new file mode 100644
index 0000000..66a29a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.PorterDuff
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.RippleDrawable
+import android.os.UserManager
+import android.util.AttributeSet
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import com.android.settingslib.Utils
+import com.android.settingslib.drawable.UserIconDrawable
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.MultiUserSwitch
+import com.android.systemui.statusbar.phone.SettingsButton
+
+/**
+ * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS,
+ * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings,
+ * edit tiles, power off and conditionally: user switch and tuner
+ */
+class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+    private lateinit var settingsContainer: View
+    private lateinit var settingsButton: SettingsButton
+    private lateinit var multiUserSwitch: MultiUserSwitch
+    private lateinit var multiUserAvatar: ImageView
+    private lateinit var tunerIcon: View
+    private lateinit var editTilesButton: View
+
+    private var settingsCogAnimator: TouchAnimator? = null
+
+    private var qsDisabled = false
+    private var isExpanded = false
+    private var expansionAmount = 0f
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        editTilesButton = requireViewById(android.R.id.edit)
+        settingsButton = findViewById(R.id.settings_button)
+        settingsContainer = findViewById(R.id.settings_button_container)
+        multiUserSwitch = findViewById(R.id.multi_user_switch)
+        multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar)
+        tunerIcon = requireViewById(R.id.tuner_icon)
+
+        // RenderThread is doing more harm than good when touching the header (to expand quick
+        // settings), so disable it for this view
+        if (settingsButton.background is RippleDrawable) {
+            (settingsButton.background as RippleDrawable).setForceSoftware(true)
+        }
+        updateResources()
+        importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
+    }
+
+    fun updateAnimator(width: Int, numTiles: Int) {
+        val size = (mContext.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) -
+                mContext.resources.getDimensionPixelSize(R.dimen.qs_tile_padding))
+        val remaining = (width - numTiles * size) / (numTiles - 1)
+        val defSpace = mContext.resources.getDimensionPixelOffset(R.dimen.default_gear_space)
+        val translation = if (isLayoutRtl) (remaining - defSpace) else -(remaining - defSpace)
+        settingsCogAnimator = TouchAnimator.Builder()
+                .addFloat(settingsButton, "translationX", translation.toFloat(), 0f)
+                .addFloat(settingsButton, "rotation", -120f, 0f)
+                .build()
+        setExpansion(expansionAmount)
+    }
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        super.onConfigurationChanged(newConfig)
+        updateResources()
+    }
+
+    override fun onRtlPropertiesChanged(layoutDirection: Int) {
+        super.onRtlPropertiesChanged(layoutDirection)
+        updateResources()
+    }
+
+    private fun updateResources() {
+        val tunerIconTranslation = mContext.resources
+                .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation).toFloat()
+        tunerIcon.translationX = if (isLayoutRtl) (-tunerIconTranslation) else tunerIconTranslation
+    }
+
+    fun setKeyguardShowing() {
+        setExpansion(expansionAmount)
+    }
+
+    fun setExpanded(expanded: Boolean, isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+        if (isExpanded == expanded) return
+        isExpanded = expanded
+        updateEverything(isTunerEnabled, multiUserEnabled)
+    }
+
+    fun setExpansion(headerExpansionFraction: Float) {
+        expansionAmount = headerExpansionFraction
+        if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction)
+    }
+
+    fun disable(state2: Int, isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+        val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
+        if (disabled == qsDisabled) return
+        qsDisabled = disabled
+        updateEverything(isTunerEnabled, multiUserEnabled)
+    }
+
+    fun updateEverything(isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+        post {
+            updateVisibilities(isTunerEnabled, multiUserEnabled)
+            updateClickabilities()
+            isClickable = false
+        }
+    }
+
+    private fun updateClickabilities() {
+        multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE
+        editTilesButton.isClickable = editTilesButton.visibility == VISIBLE
+        settingsButton.isClickable = settingsButton.visibility == VISIBLE
+    }
+
+    private fun updateVisibilities(isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+        settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
+        tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE
+        multiUserSwitch.visibility = if (showUserSwitcher(multiUserEnabled)) VISIBLE else GONE
+        val isDemo = UserManager.isDeviceInDemoMode(context)
+        settingsButton.visibility = if (isDemo || !isExpanded) INVISIBLE else VISIBLE
+    }
+
+    private fun showUserSwitcher(multiUserEnabled: Boolean): Boolean {
+        return isExpanded && multiUserEnabled
+    }
+
+    fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {
+        var pictureToSet = picture
+        if (picture != null && isGuestUser && picture !is UserIconDrawable) {
+            pictureToSet = picture.constantState.newDrawable(resources).mutate()
+            pictureToSet.setColorFilter(
+                    Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
+                    PorterDuff.Mode.SRC_IN)
+        }
+        multiUserAvatar.setImageDrawable(pictureToSet)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index 57438d1..7db13bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -21,60 +21,40 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.settingslib.Utils;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
-import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.R;
-import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.phone.MultiUserSwitch;
-import com.android.systemui.statusbar.phone.SettingsButton;
 
-/** */
+/**
+ * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and
+ * {@link QSFooterActionsView}
+ */
 public class QSFooterView extends FrameLayout {
-    private SettingsButton mSettingsButton;
-    protected View mSettingsContainer;
     private PageIndicator mPageIndicator;
     private TextView mBuildText;
-    private boolean mShouldShowBuildText;
-
-    private boolean mQsDisabled;
-
-    private boolean mExpanded;
-
-    private boolean mListening;
-
-    protected MultiUserSwitch mMultiUserSwitch;
-    private ImageView mMultiUserAvatar;
+    private View mActionsContainer;
 
     protected TouchAnimator mFooterAnimator;
+
+    private boolean mQsDisabled;
+    private boolean mExpanded;
     private float mExpansionAmount;
 
-    protected View mEdit;
-    private TouchAnimator mSettingsCogAnimator;
-
-    private View mActionsContainer;
-    private View mTunerIcon;
-    private int mTunerIconTranslation;
+    private boolean mShouldShowBuildText;
 
     private OnClickListener mExpandClickListener;
 
@@ -94,27 +74,11 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mEdit = requireViewById(android.R.id.edit);
-
         mPageIndicator = findViewById(R.id.footer_page_indicator);
-
-        mSettingsButton = findViewById(R.id.settings_button);
-        mSettingsContainer = findViewById(R.id.settings_button_container);
-
-        mMultiUserSwitch = findViewById(R.id.multi_user_switch);
-        mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
-
         mActionsContainer = requireViewById(R.id.qs_footer_actions_container);
         mBuildText = findViewById(R.id.build);
-        mTunerIcon = requireViewById(R.id.tuner_icon);
 
-        // RenderThread is doing more harm than good when touching the header (to expand quick
-        // settings), so disable it for this view
-        if (mSettingsButton.getBackground() instanceof RippleDrawable) {
-            ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
-        }
         updateResources();
-
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         setBuildText();
     }
@@ -137,18 +101,7 @@
         }
     }
 
-    void updateAnimator(int width, int numTiles) {
-        int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
-                - mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
-        int remaining = (width - numTiles * size) / (numTiles - 1);
-        int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
-
-        mSettingsCogAnimator = new Builder()
-                .addFloat(mSettingsButton, "translationX",
-                        isLayoutRtl() ? (remaining - defSpace) : -(remaining - defSpace), 0)
-                .addFloat(mSettingsButton, "rotation", -120, 0)
-                .build();
-
+    void updateExpansion() {
         setExpansion(mExpansionAmount);
     }
 
@@ -158,20 +111,11 @@
         updateResources();
     }
 
-    @Override
-    public void onRtlPropertiesChanged(int layoutDirection) {
-        super.onRtlPropertiesChanged(layoutDirection);
-        updateResources();
-    }
-
     private void updateResources() {
         updateFooterAnimator();
         MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
         lp.bottomMargin = getResources().getDimensionPixelSize(R.dimen.qs_footers_margin_bottom);
         setLayoutParams(lp);
-        mTunerIconTranslation = mContext.getResources()
-                .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation);
-        mTunerIcon.setTranslationX(isLayoutRtl() ? -mTunerIconTranslation : mTunerIconTranslation);
     }
 
     private void updateFooterAnimator() {
@@ -197,17 +141,15 @@
         mExpandClickListener = onClickListener;
     }
 
-    void setExpanded(boolean expanded, boolean isTunerEnabled, boolean multiUserEnabled) {
+    void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
-        updateEverything(isTunerEnabled, multiUserEnabled);
+        updateEverything();
     }
 
     /** */
     public void setExpansion(float headerExpansionFraction) {
         mExpansionAmount = headerExpansionFraction;
-        if (mSettingsCogAnimator != null) mSettingsCogAnimator.setPosition(headerExpansionFraction);
-
         if (mFooterAnimator != null) {
             mFooterAnimator.setPosition(headerExpansionFraction);
         }
@@ -228,14 +170,6 @@
         super.onDetachedFromWindow();
     }
 
-    /** */
-    public void setListening(boolean listening) {
-        if (listening == mListening) {
-            return;
-        }
-        mListening = listening;
-    }
-
     @Override
     public boolean performAccessibilityAction(int action, Bundle arguments) {
         if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
@@ -253,50 +187,26 @@
         info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
     }
 
-    void disable(int state2, boolean isTunerEnabled, boolean multiUserEnabled) {
+    void disable(int state2) {
         final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
         if (disabled == mQsDisabled) return;
         mQsDisabled = disabled;
-        updateEverything(isTunerEnabled, multiUserEnabled);
+        updateEverything();
     }
 
-    void updateEverything(boolean isTunerEnabled, boolean multiUserEnabled) {
+    void updateEverything() {
         post(() -> {
-            updateVisibilities(isTunerEnabled, multiUserEnabled);
+            updateVisibilities();
             updateClickabilities();
             setClickable(false);
         });
     }
 
     private void updateClickabilities() {
-        mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE);
-        mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE);
-        mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE);
         mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE);
     }
 
-    private void updateVisibilities(boolean isTunerEnabled, boolean multiUserEnabled) {
-        mSettingsContainer.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
-        mTunerIcon.setVisibility(isTunerEnabled ? View.VISIBLE : View.INVISIBLE);
-        final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
-        mMultiUserSwitch.setVisibility(
-                showUserSwitcher(multiUserEnabled) ? View.VISIBLE : View.GONE);
-        mSettingsButton.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
-
+    private void updateVisibilities() {
         mBuildText.setVisibility(mExpanded && mShouldShowBuildText ? View.VISIBLE : View.INVISIBLE);
     }
-
-    private boolean showUserSwitcher(boolean multiUserEnabled) {
-        return mExpanded && multiUserEnabled;
-    }
-
-    void onUserInfoChanged(Drawable picture, boolean isGuestUser) {
-        if (picture != null && isGuestUser && !(picture instanceof UserIconDrawable)) {
-            picture = picture.getConstantState().newDrawable(getResources()).mutate();
-            picture.setColorFilter(
-                    Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
-                    Mode.SRC_IN);
-        }
-        mMultiUserAvatar.setImageDrawable(picture);
-    }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index 929aeda..c8ae590 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -16,39 +16,19 @@
 
 package com.android.systemui.qs;
 
-import static com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED;
-
 import android.content.ClipData;
 import android.content.ClipboardManager;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.os.UserManager;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
-import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 
 /**
  * Controller for {@link QSFooterView}.
@@ -56,137 +36,45 @@
 @QSScope
 public class QSFooterViewController extends ViewController<QSFooterView> implements QSFooter {
 
-    private final UserManager mUserManager;
-    private final UserInfoController mUserInfoController;
-    private final ActivityStarter mActivityStarter;
-    private final DeviceProvisionedController mDeviceProvisionedController;
     private final UserTracker mUserTracker;
     private final QSPanelController mQsPanelController;
     private final QuickQSPanelController mQuickQSPanelController;
-    private final TunerService mTunerService;
-    private final MetricsLogger mMetricsLogger;
-    private final FalsingManager mFalsingManager;
-    private final MultiUserSwitchController mMultiUserSwitchController;
-    private final SettingsButton mSettingsButton;
-    private final View mSettingsButtonContainer;
+    private final QSFooterActionsController mQsFooterActionsController;
     private final TextView mBuildText;
-    private final View mEdit;
     private final PageIndicator mPageIndicator;
-    private final View mPowerMenuLite;
-    private final boolean mShowPMLiteButton;
-    private final GlobalActionsDialogLite mGlobalActionsDialog;
-    private final UiEventLogger mUiEventLogger;
-
-    private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
-            new UserInfoController.OnUserInfoChangedListener() {
-        @Override
-        public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
-            boolean isGuestUser = mUserManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser());
-            mView.onUserInfoChanged(picture, isGuestUser);
-        }
-    };
-
-    private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            // Don't do anything until views are unhidden. Don't do anything if the tap looks
-            // suspicious.
-            if (!mExpanded || mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
-                return;
-            }
-
-            if (v == mSettingsButton) {
-                if (!mDeviceProvisionedController.isCurrentUserSetup()) {
-                    // If user isn't setup just unlock the device and dump them back at SUW.
-                    mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
-                    });
-                    return;
-                }
-                mMetricsLogger.action(
-                        mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
-                                : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
-                if (mSettingsButton.isTunerClick()) {
-                    mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
-                        if (isTunerEnabled()) {
-                            mTunerService.showResetRequest(
-                                    () -> {
-                                        // Relaunch settings so that the tuner disappears.
-                                        startSettingsActivity();
-                                    });
-                        } else {
-                            Toast.makeText(getContext(), R.string.tuner_toast,
-                                    Toast.LENGTH_LONG).show();
-                            mTunerService.setTunerEnabled(true);
-                        }
-                        startSettingsActivity();
-
-                    });
-                } else {
-                    startSettingsActivity();
-                }
-            } else if (v == mPowerMenuLite) {
-                mUiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
-                mGlobalActionsDialog.showOrHideDialog(false, true);
-            }
-        }
-    };
-
-    private boolean mListening;
-    private boolean mExpanded;
 
     @Inject
-    QSFooterViewController(QSFooterView view, UserManager userManager,
-            UserInfoController userInfoController, ActivityStarter activityStarter,
-            DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
+    QSFooterViewController(QSFooterView view,
+            UserTracker userTracker,
             QSPanelController qsPanelController,
-            MultiUserSwitchController multiUserSwitchController,
             QuickQSPanelController quickQSPanelController,
-            TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager,
-            @Named(PM_LITE_ENABLED) boolean showPMLiteButton,
-            GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger) {
+            QSFooterActionsController qsFooterActionsController) {
         super(view);
-        mUserManager = userManager;
-        mUserInfoController = userInfoController;
-        mActivityStarter = activityStarter;
-        mDeviceProvisionedController = deviceProvisionedController;
         mUserTracker = userTracker;
         mQsPanelController = qsPanelController;
         mQuickQSPanelController = quickQSPanelController;
-        mTunerService = tunerService;
-        mMetricsLogger = metricsLogger;
-        mFalsingManager = falsingManager;
-        mMultiUserSwitchController = multiUserSwitchController;
+        mQsFooterActionsController = qsFooterActionsController;
 
-        mSettingsButton = mView.findViewById(R.id.settings_button);
-        mSettingsButtonContainer = mView.findViewById(R.id.settings_button_container);
         mBuildText = mView.findViewById(R.id.build);
-        mEdit = mView.findViewById(android.R.id.edit);
         mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
-        mPowerMenuLite = mView.findViewById(R.id.pm_lite);
-        mShowPMLiteButton = showPMLiteButton;
-        mGlobalActionsDialog = globalActionsDialog;
-        mUiEventLogger = uiEventLogger;
     }
 
     @Override
     protected void onInit() {
         super.onInit();
-        mMultiUserSwitchController.init();
+        mQsFooterActionsController.init();
     }
 
     @Override
     protected void onViewAttached() {
-        if (mShowPMLiteButton) {
-            mPowerMenuLite.setVisibility(View.VISIBLE);
-            mPowerMenuLite.setOnClickListener(mSettingsOnClickListener);
-        } else {
-            mPowerMenuLite.setVisibility(View.GONE);
-        }
         mView.addOnLayoutChangeListener(
-                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
-                        mView.updateAnimator(
-                                right - left, mQuickQSPanelController.getNumQuickTiles()));
-        mSettingsButton.setOnClickListener(mSettingsOnClickListener);
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    mView.updateExpansion();
+                    mQsFooterActionsController.updateAnimator(right - left,
+                            mQuickQSPanelController.getNumQuickTiles());
+                }
+        );
+
         mBuildText.setOnLongClickListener(view -> {
             CharSequence buildText = mBuildText.getText();
             if (!TextUtils.isEmpty(buildText)) {
@@ -200,17 +88,8 @@
             }
             return false;
         });
-
-        mEdit.setOnClickListener(view -> {
-            if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
-                return;
-            }
-            mActivityStarter.postQSRunnableDismissingKeyguard(() ->
-                    mQsPanelController.showEdit(view));
-        });
-
         mQsPanelController.setFooterPageIndicator(mPageIndicator);
-        mView.updateEverything(isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
+        mView.updateEverything();
     }
 
     @Override
@@ -225,38 +104,25 @@
 
     @Override
     public void setExpanded(boolean expanded) {
-        mExpanded = expanded;
-        mView.setExpanded(
-                expanded, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
-    }
-
-    @Override
-    public int getHeight() {
-        return mView.getHeight();
+        mQsFooterActionsController.setExpanded(expanded);
+        mView.setExpanded(expanded);
     }
 
     @Override
     public void setExpansion(float expansion) {
         mView.setExpansion(expansion);
+        mQsFooterActionsController.setExpansion(expansion);
     }
 
     @Override
     public void setListening(boolean listening) {
-        if (mListening == listening) {
-            return;
-        }
-
-        mListening = listening;
-        if (mListening) {
-            mUserInfoController.addCallback(mOnUserInfoChangedListener);
-        } else {
-            mUserInfoController.removeCallback(mOnUserInfoChangedListener);
-        }
+        mQsFooterActionsController.setListening(listening);
     }
 
     @Override
     public void setKeyguardShowing(boolean keyguardShowing) {
         mView.setKeyguardShowing();
+        mQsFooterActionsController.setKeyguardShowing();
     }
 
     /** */
@@ -267,19 +133,7 @@
 
     @Override
     public void disable(int state1, int state2, boolean animate) {
-        mView.disable(state2, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
-    }
-
-    private void startSettingsActivity() {
-        ActivityLaunchAnimator.Controller animationController =
-                mSettingsButtonContainer != null ? ActivityLaunchAnimator.Controller.fromView(
-                        mSettingsButtonContainer,
-                        InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON) : null;
-        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */, animationController);
-    }
-
-    private boolean isTunerEnabled() {
-        return mTunerService.isTunerEnabled();
+        mView.disable(state2);
+        mQsFooterActionsController.disable(state2);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 4e09bc6..4242e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -510,11 +510,13 @@
                             : headerTranslation);
         }
         int currentHeight = getView().getHeight();
-        mLastHeaderTranslation = headerTranslation;
-        if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded
-                && mLastViewHeight == currentHeight) {
+        if (expansion == mLastQSExpansion
+                && mLastKeyguardAndExpanded == onKeyguardAndExpanded
+                && mLastViewHeight == currentHeight
+                && mLastHeaderTranslation == headerTranslation) {
             return;
         }
+        mLastHeaderTranslation = headerTranslation;
         mLastQSExpansion = expansion;
         mLastKeyguardAndExpanded = onKeyguardAndExpanded;
         mLastViewHeight = currentHeight;
@@ -534,8 +536,8 @@
         }
         mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
         mQSPanelController.setRevealExpansion(expansion);
-        mQSPanelController.getTileLayout().setExpansion(expansion);
-        mQuickQSPanelController.getTileLayout().setExpansion(expansion);
+        mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
+        mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
         mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
         if (fullyCollapsed) {
             mQSPanelScrollView.setScrollY(0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 63124ab..28aa884 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -736,7 +736,7 @@
         void setListening(boolean listening, UiEventLogger uiEventLogger);
 
         /**
-         * Set the minimum number of rows to show
+         * Sets the minimum number of rows to show
          *
          * @param minRows the minimum.
          */
@@ -745,7 +745,7 @@
         }
 
         /**
-         * Set the max number of columns to show
+         * Sets the max number of columns to show
          *
          * @param maxColumns the maximum
          *
@@ -755,7 +755,10 @@
             return false;
         }
 
-        default void setExpansion(float expansion) {}
+        /**
+         * Sets the expansion value and proposedTranslation to panel.
+         */
+        default void setExpansion(float expansion, float proposedTranslation) {}
 
         int getNumVisibleTiles();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 240cf93..541ee2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -39,7 +39,6 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.qs.QSTile;
@@ -512,33 +511,6 @@
                 }
             }
         }
-        // TODO(b/174753536): Move it into the config file.
-        // Only do the below hacking when at least one of the below tiles exist
-        //   --InternetTile
-        //   --WiFiTile
-        //   --CellularTIle
-        if (tiles.contains("internet") || tiles.contains("wifi") || tiles.contains("cell")) {
-            if (FeatureFlags.isProviderModelSettingEnabled(context)) {
-                if (!tiles.contains("internet")) {
-                    if (tiles.contains("wifi")) {
-                        // Replace the WiFi with Internet, and remove the Cell
-                        tiles.set(tiles.indexOf("wifi"), "internet");
-                        tiles.remove("cell");
-                    } else if (tiles.contains("cell")) {
-                        // Replace the Cell with Internet
-                        tiles.set(tiles.indexOf("cell"), "internet");
-                    }
-                } else {
-                    tiles.remove("wifi");
-                    tiles.remove("cell");
-                }
-            } else {
-                if (tiles.contains("internet")) {
-                    tiles.set(tiles.indexOf("internet"), "wifi");
-                    tiles.add("cell");
-                }
-            }
-        }
         return tiles;
     }
 
@@ -558,14 +530,6 @@
                 && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
             tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
         }
-        // TODO(b/174753536): Change the config file directly.
-        // Filter out unused tiles from the default QS config.
-        if (FeatureFlags.isProviderModelSettingEnabled(context)) {
-            tiles.remove("cell");
-            tiles.remove("wifi");
-        } else {
-            tiles.remove("internet");
-        }
         return tiles;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index f1c1e12..613e7f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -171,6 +171,8 @@
 
     static class QQSSideLabelTileLayout extends SideLabelTileLayout {
 
+        private boolean mLastSelected;
+
         QQSSideLabelTileLayout(Context context) {
             super(context, null);
             setClipChildren(false);
@@ -216,5 +218,29 @@
                 }
             }
         }
+
+        @Override
+        public void setExpansion(float expansion, float proposedTranslation) {
+            if (expansion > 0f && expansion < 1f) {
+                return;
+            }
+            // The cases we must set select for marquee when QQS/QS collapsed, and QS full expanded.
+            // Expansion == 0f is when QQS is fully showing (as opposed to 1f, which is QS). At this
+            // point we want them to be selected so the tiles will marquee (but not at other points
+            // of expansion.
+            boolean selected = (expansion == 1f || proposedTranslation < 0f);
+            if (mLastSelected == selected) {
+                return;
+            }
+            // We set it as not important while we change this, so setting each tile as selected
+            // will not cause them to announce themselves until the user has actually selected the
+            // item.
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+            for (int i = 0; i < getChildCount(); i++) {
+                getChildAt(i).setSelected(selected);
+            }
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            mLastSelected = selected;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 1770807..3c2f35b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -34,7 +34,6 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.QSTileHost;
@@ -63,7 +62,6 @@
     private final Executor mBgExecutor;
     private final Context mContext;
     private final UserTracker mUserTracker;
-    private final FeatureFlags mFeatureFlags;
     private TileStateListener mListener;
 
     private boolean mFinished;
@@ -73,14 +71,12 @@
             Context context,
             UserTracker userTracker,
             @Main Executor mainExecutor,
-            @Background Executor bgExecutor,
-            FeatureFlags featureFlags
+            @Background Executor bgExecutor
     ) {
         mContext = context;
         mMainExecutor = mainExecutor;
         mBgExecutor = bgExecutor;
         mUserTracker = userTracker;
-        mFeatureFlags = featureFlags;
     }
 
     public void setListener(TileStateListener listener) {
@@ -121,19 +117,11 @@
         }
 
         final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
-        // TODO(b/174753536): Move it into the config file.
-        if (mFeatureFlags.isProviderModelSettingEnabled()) {
-            possibleTiles.remove("cell");
-            possibleTiles.remove("wifi");
-        } else {
-            possibleTiles.remove("internet");
-        }
 
         for (String spec : possibleTiles) {
             // Only add current and stock tiles that can be created from QSFactoryImpl.
             // Do not include CustomTile. Those will be created by `addPackageTiles`.
             if (spec.startsWith(CustomTile.PREFIX)) continue;
-            // TODO(b/174753536): Move it into the config file.
             final QSTile tile = host.createTile(spec);
             if (tile == null) {
                 continue;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 2046550..2de2d04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -28,6 +28,7 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSContainerImpl;
 import com.android.systemui.qs.QSFooter;
+import com.android.systemui.qs.QSFooterActionsView;
 import com.android.systemui.qs.QSFooterView;
 import com.android.systemui.qs.QSFooterViewController;
 import com.android.systemui.qs.QSFragment;
@@ -122,6 +123,12 @@
 
     /** */
     @Provides
+    static QSFooterActionsView providesQSFooterActionsView(@RootView View view) {
+        return view.findViewById(R.id.qs_footer_actions_container);
+    }
+
+    /** */
+    @Provides
     @QSScope
     static QSFooter providesQSFooter(QSFooterViewController qsFooterViewController) {
         qsFooterViewController.init();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 70685a6..222539d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -195,9 +195,6 @@
             // sibling methods to have special behavior for labelContainer.
             labelContainer.forceUnspecifiedMeasure = true
             secondaryLabel.alpha = 0f
-            // Do not marque in QQS
-            label.ellipsize = TextUtils.TruncateAt.END
-            secondaryLabel.ellipsize = TextUtils.TruncateAt.END
         }
         setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE))
         setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE))
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index a63d1f8..e338750 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -287,14 +287,22 @@
         }
         showProgressBar();
         setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular());
-        setConnectedWifiLayout();
-        boolean isWifiEnabled = mWifiManager.isWifiEnabled();
-        mWiFiToggle.setChecked(isWifiEnabled);
-        int visible = isWifiEnabled ? View.VISIBLE : View.GONE;
-        mWifiRecyclerView.setVisibility(visible);
-        mAdapter.notifyDataSetChanged();
-        mSeeAllLayout.setVisibility(visible);
-        mSpace.setVisibility(isWifiEnabled ? View.GONE : View.VISIBLE);
+
+        final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
+        final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+        updateWifiToggle(isWifiEnabled, isDeviceLocked);
+        updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+
+        List<WifiEntry> wifiEntryList = mInternetDialogController.getWifiEntryList();
+        final int wifiListVisibility =
+                (isDeviceLocked || wifiEntryList == null || wifiEntryList.size() <= 0)
+                        ? View.GONE : View.VISIBLE;
+        mWifiRecyclerView.setVisibility(wifiListVisibility);
+        if (wifiListVisibility == View.VISIBLE) {
+            mAdapter.notifyDataSetChanged();
+        }
+        mSeeAllLayout.setVisibility(wifiListVisibility);
+        mSpace.setVisibility(wifiListVisibility == View.VISIBLE ? View.GONE : View.VISIBLE);
     }
 
     private void setOnClickListener() {
@@ -358,8 +366,14 @@
         }
     }
 
-    private void setConnectedWifiLayout() {
-        if (!mWifiManager.isWifiEnabled() || mConnectedWifiEntry == null) {
+    private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
+        mWiFiToggle.setChecked(isWifiEnabled);
+        mTurnWifiOnLayout.setBackground(
+                (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
+    }
+
+    private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) {
+        if (!isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) {
             mConnectedWifListLayout.setBackground(null);
             mConnectedWifListLayout.setVisibility(View.GONE);
             return;
@@ -418,7 +432,8 @@
     }
 
     protected void showProgressBar() {
-        if (mWifiManager == null || !mWifiManager.isWifiEnabled()) {
+        if (mWifiManager == null || !mWifiManager.isWifiEnabled()
+                || mInternetDialogController.isDeviceLocked()) {
             setProgressBarVisible(false);
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 890dcfd..80a93d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -67,6 +67,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
 import com.android.systemui.util.settings.GlobalSettings;
@@ -97,6 +98,8 @@
     private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off;
     private static final int SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT =
             R.string.tap_a_network_to_connect;
+    private static final int SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS =
+            R.string.unlock_to_view_networks;
     private static final int SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS =
             R.string.wifi_empty_list_wifi_on;
     private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE =
@@ -137,6 +140,9 @@
     @VisibleForTesting
     protected WifiUtils.InternetIconInjector mWifiIconInjector;
 
+    @VisibleForTesting
+    KeyguardStateController mKeyguardStateController;
+
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
@@ -161,7 +167,7 @@
             @Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
             @Main Handler handler, @Main Executor mainExecutor,
             BroadcastDispatcher broadcastDispatcher, KeyguardUpdateMonitor keyguardUpdateMonitor,
-            GlobalSettings globalSettings) {
+            GlobalSettings globalSettings, KeyguardStateController keyguardStateController) {
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialogController");
         }
@@ -175,6 +181,7 @@
         mSubscriptionManager = subscriptionManager;
         mBroadcastDispatcher = broadcastDispatcher;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mKeyguardStateController = keyguardStateController;
         mConnectionStateFilter = new IntentFilter();
         mConnectionStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         mConnectionStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
@@ -272,6 +279,15 @@
             return mContext.getText(SUBTITLE_TEXT_WIFI_IS_OFF);
         }
 
+        if (isDeviceLocked()) {
+            // When the device is locked.
+            //   Sub-Title: Unlock to view networks
+            if (DEBUG) {
+                Log.d(TAG, "The device is locked.");
+            }
+            return mContext.getText(SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS);
+        }
+
         final List<ScanResult> wifiList = mWifiManager.getScanResults();
         if (wifiList != null && wifiList.size() != 0) {
             return mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT);
@@ -683,6 +699,10 @@
                 && serviceState.getState() == serviceState.STATE_IN_SERVICE;
     }
 
+    public boolean isDeviceLocked() {
+        return !mKeyguardStateController.isUnlocked();
+    }
+
     boolean activeNetworkIsCellular() {
         if (mConnectivityManager == null) {
             if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index eb72296..ad7c522 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -427,6 +427,19 @@
         }
     };
 
+    private final BroadcastReceiver mDebugAnyPackageChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String[] stringArrayExtra = intent.getStringArrayExtra(
+                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+            Log.e("b/188806432", intent.toString()
+                    + (stringArrayExtra != null
+                            ? ", EXTRA_CHANGED_COMPONENT_NAME_LIST: " + String.join(", ",
+                            stringArrayExtra)
+                            : ""));
+        }
+    };
+
     private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -566,6 +579,13 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         mContext.registerReceiver(mLauncherStateChangedReceiver, filter);
 
+        // b/188806432
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addDataScheme("package");
+        filter.addDataSchemeSpecificPart("", PatternMatcher.PATTERN_PREFIX);
+        mContext.registerReceiver(mDebugAnyPackageChangedReceiver, filter);
+
         // Listen for status bar state changes
         statusBarWinController.registerCallback(mStatusBarWindowCallback);
         mScreenshotHelper = new ScreenshotHelper(context);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 3890c1a..503b5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -825,7 +825,11 @@
         if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
             // if udfps available, there will always be a tappable affordance to unlock
             // For example, the lock icon
-            showTransientIndication(R.string.keyguard_unlock_press);
+            if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) {
+                showTransientIndication(R.string.keyguard_unlock_press);
+            } else {
+                showTransientIndication(R.string.keyguard_face_failed_use_fp);
+            }
         } else {
             showTransientIndication(R.string.keyguard_try_fingerprint);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index f317628..dbf115b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -2255,6 +2255,11 @@
 
         @Override
         public void onClick(View view) {
+            // If the ringer drawer isn't open, don't let anything in it be clicked.
+            if (!mIsRingerDrawerOpen) {
+                return;
+            }
+
             setRingerMode(mClickedRingerMode);
 
             mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 7e733a9..7e3553a 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -55,6 +55,7 @@
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
 import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
 import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
@@ -213,6 +214,13 @@
     }
 
     //
+    // Freeform (optional feature)
+    //
+
+    @BindsOptionalOf
+    abstract Optional<FreeformTaskListener> optionalFreeformTaskListener();
+
+    //
     // Hide display cutout
     //
 
@@ -328,9 +336,11 @@
     @WMSingleton
     @Provides
     static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
-            Context context, @ShellMainThread ShellExecutor mainExecutor,
+            DisplayController displayController, Context context,
+            @ShellMainThread ShellExecutor mainExecutor,
             @ShellAnimationThread ShellExecutor animExecutor) {
-        return new Transitions(organizer, pool, context, mainExecutor, animExecutor);
+        return new Transitions(organizer, pool, displayController, context, mainExecutor,
+                animExecutor);
     }
 
     //
@@ -451,6 +461,7 @@
             Optional<AppPairsController> appPairsOptional,
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             FullscreenTaskListener fullscreenTaskListener,
+            Optional<Optional<FreeformTaskListener>> freeformTaskListener,
             Transitions transitions,
             StartingWindowController startingWindow,
             @ShellMainThread ShellExecutor mainExecutor) {
@@ -463,6 +474,7 @@
                 appPairsOptional,
                 pipTouchHandlerOptional,
                 fullscreenTaskListener,
+                freeformTaskListener,
                 transitions,
                 startingWindow,
                 mainExecutor);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index be7813e..6397ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -36,6 +36,7 @@
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
 import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.freeform.FreeformTaskListener;
 import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.pip.Pip;
@@ -89,6 +90,18 @@
     }
 
     //
+    // Freeform
+    //
+
+    @WMSingleton
+    @Provides
+    static Optional<FreeformTaskListener> provideFreeformTaskListener(
+            Context context,
+            SyncTransactionQueue syncQueue) {
+        return Optional.ofNullable(FreeformTaskListener.create(context, syncQueue));
+    }
+
+    //
     // Split/multiwindow
     //
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
index 79b0dd0..8e1b13c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -69,7 +69,7 @@
         whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
                 .thenReturn(true)
         whenever(mediaHost.hostView).thenReturn(hostView)
-
+        hostView.layoutParams = FrameLayout.LayoutParams(100, 100)
         keyguardMediaController = KeyguardMediaController(
             mediaHost,
             bypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 8fd2a32..3ea57be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -142,6 +142,8 @@
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultTrue() {
+        // Tablets may be using taskbar and the logic is different
+        mNavigationBarController.mIsTablet = false;
         doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
 
         mNavigationBarController.createNavigationBars(true, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt
new file mode 100644
index 0000000..9378b2b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt
@@ -0,0 +1,91 @@
+package com.android.systemui.qs
+
+import com.android.systemui.R
+import android.os.UserManager
+import android.view.LayoutInflater
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.testing.FakeMetricsLogger
+import com.android.systemui.Dependency
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.utils.leaks.FakeTunerService
+import com.android.systemui.utils.leaks.LeakCheckedTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+class QSFooterActionsControllerTest : LeakCheckedTest() {
+    @Mock
+    private lateinit var userManager: UserManager
+    @Mock
+    private lateinit var activityStarter: ActivityStarter
+    @Mock
+    private lateinit var deviceProvisionedController: DeviceProvisionedController
+    @Mock
+    private lateinit var userInfoController: UserInfoController
+    @Mock
+    private lateinit var qsPanelController: QSPanelController
+    @Mock
+    private lateinit var multiUserSwitchController: MultiUserSwitchController
+    @Mock
+    private lateinit var globalActionsDialog: GlobalActionsDialogLite
+    @Mock
+    private lateinit var uiEventLogger: UiEventLogger
+    @Mock
+    private lateinit var controller: QSFooterActionsController
+
+    private val metricsLogger: MetricsLogger = FakeMetricsLogger()
+    private lateinit var view: QSFooterActionsView
+    private val falsingManager: FalsingManagerFake = FalsingManagerFake()
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
+        val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
+
+        view = LayoutInflater.from(context)
+                .inflate(R.layout.qs_footer_actions, null) as QSFooterActionsView
+
+        controller = QSFooterActionsController(view, qsPanelController, activityStarter,
+                userManager, userInfoController, multiUserSwitchController,
+                deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
+                globalActionsDialog, uiEventLogger, showPMLiteButton = true)
+        controller.init()
+        controller.onViewAttached()
+    }
+
+    @Test
+    fun testLogPowerMenuClick() {
+        controller.expanded = true
+        falsingManager.setFalseTap(false)
+
+        view.findViewById<View>(R.id.pm_lite).performClick()
+        // Verify clicks are logged
+        verify(uiEventLogger, Mockito.times(1))
+                .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+    }
+
+    @Test
+    fun testSettings_UserNotSetup() {
+        whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+        view.findViewById<View>(R.id.settings_button).performClick()
+        // Verify Settings wasn't launched.
+        verify<ActivityStarter>(activityStarter, Mockito.never()).startActivity(any(), anyBoolean())
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 6f7bf3b..8c6c358 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -18,16 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.ClipData;
 import android.content.ClipboardManager;
-import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
@@ -35,21 +30,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.FakeMetricsLogger;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.utils.leaks.FakeTunerService;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
 import org.junit.Before;
@@ -67,14 +49,6 @@
     @Mock
     private QSFooterView mView;
     @Mock
-    private UserManager mUserManager;
-    @Mock
-    private ActivityStarter mActivityStarter;
-    @Mock
-    private DeviceProvisionedController mDeviceProvisionedController;
-    @Mock
-    private UserInfoController mUserInfoController;
-    @Mock
     private UserTracker mUserTracker;
     @Mock
     private QSPanelController mQSPanelController;
@@ -82,36 +56,19 @@
     private ClipboardManager mClipboardManager;
     @Mock
     private QuickQSPanelController mQuickQSPanelController;
-    private FakeTunerService mFakeTunerService;
-    private MetricsLogger mMetricsLogger = new FakeMetricsLogger();
-    private FalsingManagerFake mFalsingManager;
-
-    @Mock
-    private SettingsButton mSettingsButton;
     @Mock
     private TextView mBuildText;
     @Mock
-    private View mEdit;
-    @Mock
-    private MultiUserSwitchController mMultiUserSwitchController;
-    @Mock
-    private View mPowerMenuLiteView;
-    @Mock
-    private GlobalActionsDialogLite mGlobalActionsDialog;
-    @Mock
-    private UiEventLogger mUiEventLogger;
+    private QSFooterActionsController mQSFooterActionsController;
 
     private QSFooterViewController mController;
 
     @Before
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mFalsingManager = new FalsingManagerFake();
 
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
 
-        mFakeTunerService = (FakeTunerService) Dependency.get(TunerService.class);
-
         mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
 
         when(mView.getContext()).thenReturn(mContext);
@@ -119,16 +76,10 @@
         when(mUserTracker.getUserContext()).thenReturn(mContext);
 
         when(mView.isAttachedToWindow()).thenReturn(true);
-        when(mView.findViewById(R.id.settings_button)).thenReturn(mSettingsButton);
         when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
-        when(mView.findViewById(android.R.id.edit)).thenReturn(mEdit);
-        when(mView.findViewById(R.id.pm_lite)).thenReturn(mPowerMenuLiteView);
 
-        mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
-                mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
-                mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
-                mMetricsLogger, mFalsingManager, false, mGlobalActionsDialog,
-                mUiEventLogger);
+        mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController,
+                mQuickQSPanelController, mQSFooterActionsController);
 
         mController.init();
     }
@@ -148,40 +99,4 @@
         verify(mClipboardManager).setPrimaryClip(captor.capture());
         assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(text);
     }
-
-    @Test
-    public void testSettings_UserNotSetup() {
-        ArgumentCaptor<View.OnClickListener> onClickCaptor =
-                ArgumentCaptor.forClass(View.OnClickListener.class);
-        verify(mSettingsButton).setOnClickListener(onClickCaptor.capture());
-
-        when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
-
-        onClickCaptor.getValue().onClick(mSettingsButton);
-        // Verify Settings wasn't launched.
-        verify(mActivityStarter, never()).startActivity(any(), anyBoolean());
-    }
-
-    @Test
-    public void testLogPowerMenuClick() {
-        // Enable power menu button
-        mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
-                mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
-                mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
-                mMetricsLogger, new FalsingManagerFake(), true, mGlobalActionsDialog,
-                mUiEventLogger);
-        mController.init();
-        mController.setExpanded(true);
-        mFalsingManager.setFalseTap(false);
-
-        ArgumentCaptor<View.OnClickListener> onClickCaptor =
-                ArgumentCaptor.forClass(View.OnClickListener.class);
-        verify(mPowerMenuLiteView).setOnClickListener(onClickCaptor.capture());
-
-        onClickCaptor.getValue().onClick(mPowerMenuLiteView);
-
-        // Verify clicks are logged
-        verify(mUiEventLogger, times(1))
-                .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 3b78632..9e97f80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -44,7 +44,6 @@
 import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.util.CollectionUtils;
@@ -53,7 +52,6 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.qs.QSTile;
@@ -71,15 +69,12 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.settings.SecureSettings;
 
-import org.junit.After;
 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 org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -133,16 +128,9 @@
     private Handler mHandler;
     private TestableLooper mLooper;
     private QSTileHost mQSTileHost;
-    MockitoSession mMockingSession = null;
 
     @Before
     public void setUp() {
-        // TODO(b/174753536): Remove the mMockingSession when
-        // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
-        mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
-                .mockStatic(FeatureFlags.class).startMocking();
-        ExtendedMockito.doReturn(false)
-                .when(() -> FeatureFlags.isProviderModelSettingEnabled(mContext));
         MockitoAnnotations.initMocks(this);
         mLooper = TestableLooper.get(this);
         mHandler = new Handler(mLooper.getLooper());
@@ -156,13 +144,6 @@
                 .thenReturn("");
     }
 
-    @After
-    public void tearDown() throws Exception {
-        if (mMockingSession != null) {
-            mMockingSession.finishMocking();
-        }
-    }
-
     private void setUpTileFactory() {
         when(mMockState.toString()).thenReturn(MOCK_STATE_STRING);
         // Only create this kind of tiles
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index a6d044a..4efcc5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -45,17 +45,14 @@
 import android.testing.TestableLooper;
 import android.text.TextUtils;
 import android.util.ArraySet;
-import android.util.FeatureFlagUtils;
 import android.view.View;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.logging.InstanceId;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
@@ -64,7 +61,6 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -74,8 +70,6 @@
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -114,7 +108,6 @@
     private PackageManager mPackageManager;
     @Mock
     private UserTracker mUserTracker;
-    @Mock private FeatureFlags mFeatureFlags;
     @Captor
     private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
 
@@ -122,18 +115,10 @@
     private TileQueryHelper mTileQueryHelper;
     private FakeExecutor mMainExecutor;
     private FakeExecutor mBgExecutor;
-    MockitoSession mMockingSession = null;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        // TODO(b/174753536): Remove the mMockingSession when
-        // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
-        mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
-                .mockStatic(FeatureFlagUtils.class).startMocking();
-        ExtendedMockito.doReturn(false).when(() -> FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.SETTINGS_PROVIDER_MODEL));
-
         mContext.setMockPackageManager(mPackageManager);
 
         mState = new QSTile.State();
@@ -153,17 +138,10 @@
         mMainExecutor = new FakeExecutor(clock);
         mBgExecutor = new FakeExecutor(clock);
         mTileQueryHelper = new TileQueryHelper(
-                mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
+                mContext, mUserTracker, mMainExecutor, mBgExecutor);
         mTileQueryHelper.setListener(mListener);
     }
 
-    @After
-    public void tearDown() throws Exception {
-        if (mMockingSession != null) {
-            mMockingSession.finishMocking();
-        }
-    }
-
     @Test
     public void testIsFinished_falseBeforeQuerying() {
         assertFalse(mTileQueryHelper.isFinished());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index f876a43..2b3624e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -33,13 +33,13 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -79,7 +79,7 @@
     @Mock
     private GlobalSettings mGlobalSettings;
     @Mock
-    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private KeyguardStateController mKeyguardStateController;
     @Mock
     private NetworkController.AccessPointController mAccessPointController;
     @Mock
@@ -99,15 +99,16 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
         when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo);
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
         when(mConnectedEntry.isDefaultNetwork()).thenReturn(true);
 
         mInternetDialogController = new MockInternetDialogController(mContext,
                 mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController,
                 mSubscriptionManager, mTelephonyManager, mWifiManager,
                 mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
-                mKeyguardUpdateMonitor, mGlobalSettings);
+                mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
                 mInternetDialogController.mOnSubscriptionsChangedListener);
         mInternetDialogController.onStart(
@@ -174,6 +175,16 @@
     }
 
     @Test
+    public void getSubtitleText_deviceLockedWithWifiOn_returnUnlockToViewNetworks() {
+        mInternetDialogController.setAirplaneModeEnabled(false);
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
+                getResourcesString("unlock_to_view_networks")));
+    }
+
+    @Test
     public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
@@ -311,6 +322,20 @@
         verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
     }
 
+    @Test
+    public void isDeviceLocked_keyguardIsUnlocked_returnFalse() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+
+        assertThat(mInternetDialogController.isDeviceLocked()).isFalse();
+    }
+
+    @Test
+    public void isDeviceLocked_keyguardIsLocked_returnTrue() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+        assertThat(mInternetDialogController.isDeviceLocked()).isTrue();
+    }
+
     private String getResourcesString(String name) {
         return mContext.getResources().getString(getResourcesId(name));
     }
@@ -331,10 +356,12 @@
                 @Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
                 @Main Handler handler, @Main Executor mainExecutor,
                 BroadcastDispatcher broadcastDispatcher,
-                KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings) {
+                KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
+                KeyguardStateController keyguardStateController) {
             super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
                     telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
-                    broadcastDispatcher, keyguardUpdateMonitor, globalSettings);
+                    broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
+                    keyguardStateController);
             mGlobalSettings = globalSettings;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 856e3a1..de2c7e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -59,24 +59,31 @@
     private static final String WIFI_TITLE = "Connected Wi-Fi Title";
     private static final String WIFI_SUMMARY = "Connected Wi-Fi Summary";
 
-    private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
-
-    private InternetDialogFactory mInternetDialogFactory = mock(InternetDialogFactory.class);
-    private InternetAdapter mInternetAdapter = mock(InternetAdapter.class);
-    private InternetDialogController mInternetDialogController = mock(
-            InternetDialogController.class);
-    private InternetDialogController.InternetDialogCallback mCallback =
-            mock(InternetDialogController.InternetDialogCallback.class);
-    private MockInternetDialog mInternetDialog;
-    private WifiReceiver mWifiReceiver = null;
-    private WifiManager mMockWifiManager = mock(WifiManager.class);
-    private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
     @Mock
-    private WifiEntry mWifiEntry = mock(WifiEntry.class);
+    private InternetDialogFactory mInternetDialogFactory;
     @Mock
-    private WifiInfo mWifiInfo;
+    private InternetDialogController mInternetDialogController;
+    @Mock
+    private UiEventLogger mUiEventLogger;
     @Mock
     private Handler mHandler;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private InternetAdapter mInternetAdapter;
+    @Mock
+    private WifiManager mMockWifiManager;
+    @Mock
+    private WifiEntry mWifiEntry;
+    @Mock
+    private WifiInfo mWifiInfo;
+
+    private MockInternetDialog mInternetDialog;
+    private WifiReceiver mWifiReceiver;
+    private LinearLayout mWifiToggle;
+    private LinearLayout mConnectedWifi;
+    private RecyclerView mWifiList;
+    private LinearLayout mSeeAll;
 
     @Before
     public void setUp() {
@@ -99,6 +106,10 @@
         when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
         when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
         when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
+        mWifiToggle = mInternetDialog.mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+        mConnectedWifi = mInternetDialog.mDialogView.requireViewById(R.id.wifi_connected_layout);
+        mWifiList = mInternetDialog.mDialogView.requireViewById(R.id.wifi_list_layout);
+        mSeeAll = mInternetDialog.mDialogView.requireViewById(R.id.see_all_layout);
     }
 
     @After
@@ -137,7 +148,7 @@
     }
 
     @Test
-    public void updateDialog_withWifiOnAndHasConnectedWifi_connectedWifiLayoutVisible() {
+    public void updateDialog_wifiOnAndHasConnectedWifi_showConnectedWifi() {
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
         when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
         when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
@@ -147,36 +158,85 @@
 
         mInternetDialog.updateDialog();
 
-        final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
-                R.id.wifi_connected_layout);
-        assertThat(linearLayout.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
-    public void updateDialog_withWifiOnAndNoConnectedWifi_connectedWifiLayoutGone() {
+    public void updateDialog_wifiOnAndNoConnectedWifi_hideConnectedWifi() {
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
-        mInternetDialog.updateDialog();
-        final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
-                R.id.wifi_connected_layout);
 
-        assertThat(linearLayout.getVisibility()).isEqualTo(View.GONE);
+        mInternetDialog.updateDialog();
+
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
-    public void updateDialog_withWifiOff_WifiRecycleViewGone() {
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(false);
-        mInternetDialog.updateDialog();
-        final RecyclerView view = mInternetDialog.mDialogView.requireViewById(
-                R.id.wifi_list_layout);
+    public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
+        when(mInternetDialogController.getWifiEntryList()).thenReturn(null);
 
-        assertThat(view.getVisibility()).isEqualTo(View.GONE);
+        mInternetDialog.updateDialog();
+
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
-    public void onClickSeeMoreButton_clickSeeMore_verifyLaunchNetworkSetting() {
-        final LinearLayout seeAllLayout = mInternetDialog.mDialogView.requireViewById(
-                R.id.see_all_layout);
-        seeAllLayout.performClick();
+    public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+        List<WifiEntry> wifiEntries = new ArrayList<WifiEntry>();
+        wifiEntries.add(mWifiEntry);
+        when(mInternetDialogController.getWifiEntryList()).thenReturn(wifiEntries);
+
+        mInternetDialog.updateDialog();
+
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void updateDialog_deviceLockedAndHasConnectedWifi_showHighlightWifiToggle() {
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+        when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+        when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+        when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+        when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
+        mInternetDialog.mConnectedWifiEntry = mWifiEntry;
+
+        mInternetDialog.updateDialog();
+
+        assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mWifiToggle.getBackground()).isNotNull();
+    }
+
+    @Test
+    public void updateDialog_deviceLockedAndHasConnectedWifi_hideConnectedWifi() {
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+        when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+        when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+        when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+        when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
+        mInternetDialog.mConnectedWifiEntry = mWifiEntry;
+
+        mInternetDialog.updateDialog();
+
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() {
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+        List<WifiEntry> wifiEntries = new ArrayList<WifiEntry>();
+        wifiEntries.add(mWifiEntry);
+        when(mInternetDialogController.getWifiEntryList()).thenReturn(wifiEntries);
+
+        mInternetDialog.updateDialog();
+
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
+        mSeeAll.performClick();
 
         verify(mInternetDialogController).launchNetworkSetting();
     }
@@ -193,6 +253,17 @@
     }
 
     @Test
+    public void showProgressBar_deviceLocked_hideProgressBar() {
+        Mockito.reset(mHandler);
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+        mInternetDialog.showProgressBar();
+
+        assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
+        verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong());
+    }
+
+    @Test
     public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
         Mockito.reset(mHandler);
         when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index cd332a6..4946ad4 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -125,7 +125,7 @@
             // connect with remote AppPredictionService instead for dark launch
             usesPeopleService = false;
         }
-        final boolean serviceExists = resolveService(sessionId, false,
+        final boolean serviceExists = resolveService(sessionId, true,
                 usesPeopleService, s -> s.onCreatePredictionSession(context, sessionId));
         if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
             final AppPredictionSessionInfo sessionInfo = new AppPredictionSessionInfo(
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index a56b1db..5aec6aa 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -3285,57 +3285,6 @@
         }
     }
 
-    private void applyResourceOverlaysToWidgetsLocked(Set<String> packageNames, int userId,
-            boolean updateFrameworkRes) {
-        for (int i = 0, N = mProviders.size(); i < N; i++) {
-            Provider provider = mProviders.get(i);
-            if (provider.getUserId() != userId) {
-                continue;
-            }
-
-            final String packageName = provider.id.componentName.getPackageName();
-            if (!updateFrameworkRes && !packageNames.contains(packageName)) {
-                continue;
-            }
-
-            ApplicationInfo newAppInfo = null;
-            try {
-                newAppInfo = mPackageManager.getApplicationInfo(packageName,
-                        PackageManager.GET_SHARED_LIBRARY_FILES, userId);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to retrieve app info for " + packageName
-                        + " userId=" + userId, e);
-            }
-            if (newAppInfo == null) {
-                continue;
-            }
-            ApplicationInfo oldAppInfo = provider.info.providerInfo.applicationInfo;
-            if (!newAppInfo.sourceDir.equals(oldAppInfo.sourceDir)) {
-                // Overlay paths are generated against a particular version of an application.
-                // The overlays paths of a newly upgraded application are incompatible with the
-                // old version of the application.
-                continue;
-            }
-
-            // Isolate the changes relating to RROs. The app info must be copied to prevent
-            // affecting other parts of system server that may have cached this app info.
-            oldAppInfo = new ApplicationInfo(oldAppInfo);
-            oldAppInfo.overlayPaths = newAppInfo.overlayPaths.clone();
-            oldAppInfo.resourceDirs = newAppInfo.resourceDirs.clone();
-            provider.info.providerInfo.applicationInfo = oldAppInfo;
-
-            for (int j = 0, M = provider.widgets.size(); j < M; j++) {
-                Widget widget = provider.widgets.get(j);
-                if (widget.views != null) {
-                    widget.views.updateAppInfo(oldAppInfo);
-                }
-                if (widget.maskedViews != null) {
-                    widget.maskedViews.updateAppInfo(oldAppInfo);
-                }
-            }
-        }
-    }
-
     /**
      * Updates all providers with the specified package names, and records any providers that were
      * pruned.
@@ -4926,14 +4875,5 @@
         public void unlockUser(int userId) {
             handleUserUnlocked(userId);
         }
-
-        @Override
-        public void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
-                boolean updateFrameworkRes) {
-            synchronized (mLock) {
-                applyResourceOverlaysToWidgetsLocked(new HashSet<>(packageNames), userId,
-                        updateFrameworkRes);
-            }
-        }
     }
 }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 282b868..689890f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -92,6 +92,7 @@
     name: "services.core.unboosted",
     defaults: ["platform_service_defaults"],
     srcs: [
+        ":android.hardware.biometrics.face-V1-java-source",
         ":statslog-art-java-gen",
         ":services.core-sources",
         ":services.core.protologsrc",
@@ -116,6 +117,7 @@
 
     libs: [
         "services.net",
+        "android.hardware.common-V2-java",
         "android.hardware.light-V2.0-java",
         "android.hardware.gnss-V1-java",
         "android.hardware.power-V1-java",
@@ -145,7 +147,6 @@
         "android.hardware.light-V1-java",
         "android.hardware.tv.cec-V1.1-java",
         "android.hardware.weaver-V1.0-java",
-        "android.hardware.biometrics.face-V1-java",
         "android.hardware.biometrics.face-V1.0-java",
         "android.hardware.biometrics.fingerprint-V2.3-java",
         "android.hardware.biometrics.fingerprint-V1-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 0621d0f..e390ae28 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -353,6 +353,12 @@
 
 
     /**
+     * Retrieve all receivers that can handle a broadcast of the given intent.
+     */
+    public abstract List<ResolveInfo> queryIntentReceivers(Intent intent,
+            String resolvedType, int flags, int filterCallingUid, int userId);
+
+    /**
      * Retrieve all services that can be performed for the given intent.
      * @see PackageManager#queryIntentServices(Intent, int)
      */
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 047aae7..aae1cc0 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -147,6 +147,47 @@
         return true;
     }
 
+    /**
+     * Returns whether an intent matches the IntentFilter with a pre-resolved type.
+     */
+    public static boolean intentMatchesFilter(
+            IntentFilter filter, Intent intent, String resolvedType) {
+        final boolean debug = localLOGV
+                || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+
+        final Printer logPrinter = debug
+                ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM) : null;
+
+        if (debug) {
+            Slog.v(TAG, "Intent: " + intent);
+            Slog.v(TAG, "Matching against filter: " + filter);
+            filter.dump(logPrinter, "  ");
+        }
+
+        final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
+                intent.getData(), intent.getCategories(), TAG);
+
+        if (match >= 0) {
+            if (debug) {
+                Slog.v(TAG, "Filter matched!  match=0x" + Integer.toHexString(match));
+            }
+            return true;
+        } else {
+            if (debug) {
+                final String reason;
+                switch (match) {
+                    case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
+                    case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
+                    case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
+                    case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
+                    default: reason = "unknown reason"; break;
+                }
+                Slog.v(TAG, "Filter did not match: " + reason);
+            }
+            return false;
+        }
+    }
+
     private ArrayList<F> collectFilters(F[] array, IntentFilter matching) {
         ArrayList<F> res = null;
         if (array != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 35ed477..0d8cbaf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -193,7 +193,6 @@
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetManagerInternal;
 import android.content.AttributionSource;
 import android.content.AutofillOptions;
 import android.content.BroadcastReceiver;
@@ -12628,76 +12627,72 @@
         int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
 
         List<ResolveInfo> receivers = null;
-        try {
-            HashSet<ComponentName> singleUserReceivers = null;
-            boolean scannedFirstReceivers = false;
-            for (int user : users) {
-                // Skip users that have Shell restrictions
-                if (callingUid == SHELL_UID
-                        && mUserController.hasUserRestriction(
-                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
-                    continue;
-                }
-                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
-                        .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
-                if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
-                    // If this is not the system user, we need to check for
-                    // any receivers that should be filtered out.
-                    for (int i=0; i<newReceivers.size(); i++) {
-                        ResolveInfo ri = newReceivers.get(i);
-                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
-                            newReceivers.remove(i);
-                            i--;
-                        }
+        HashSet<ComponentName> singleUserReceivers = null;
+        boolean scannedFirstReceivers = false;
+        for (int user : users) {
+            // Skip users that have Shell restrictions
+            if (callingUid == SHELL_UID
+                    && mUserController.hasUserRestriction(
+                    UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
+                continue;
+            }
+            List<ResolveInfo> newReceivers = mPackageManagerInt
+                    .queryIntentReceivers(intent, resolvedType, pmFlags, callingUid, user);
+            if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
+                // If this is not the system user, we need to check for
+                // any receivers that should be filtered out.
+                for (int i = 0; i < newReceivers.size(); i++) {
+                    ResolveInfo ri = newReceivers.get(i);
+                    if ((ri.activityInfo.flags & ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
+                        newReceivers.remove(i);
+                        i--;
                     }
                 }
-                if (newReceivers != null && newReceivers.size() == 0) {
-                    newReceivers = null;
-                }
-                if (receivers == null) {
-                    receivers = newReceivers;
-                } else if (newReceivers != null) {
-                    // We need to concatenate the additional receivers
-                    // found with what we have do far.  This would be easy,
-                    // but we also need to de-dup any receivers that are
-                    // singleUser.
-                    if (!scannedFirstReceivers) {
-                        // Collect any single user receivers we had already retrieved.
-                        scannedFirstReceivers = true;
-                        for (int i=0; i<receivers.size(); i++) {
-                            ResolveInfo ri = receivers.get(i);
-                            if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
-                                ComponentName cn = new ComponentName(
-                                        ri.activityInfo.packageName, ri.activityInfo.name);
-                                if (singleUserReceivers == null) {
-                                    singleUserReceivers = new HashSet<ComponentName>();
-                                }
-                                singleUserReceivers.add(cn);
-                            }
-                        }
-                    }
-                    // Add the new results to the existing results, tracking
-                    // and de-dupping single user receivers.
-                    for (int i=0; i<newReceivers.size(); i++) {
-                        ResolveInfo ri = newReceivers.get(i);
+            }
+            if (newReceivers != null && newReceivers.size() == 0) {
+                newReceivers = null;
+            }
+            if (receivers == null) {
+                receivers = newReceivers;
+            } else if (newReceivers != null) {
+                // We need to concatenate the additional receivers
+                // found with what we have do far.  This would be easy,
+                // but we also need to de-dup any receivers that are
+                // singleUser.
+                if (!scannedFirstReceivers) {
+                    // Collect any single user receivers we had already retrieved.
+                    scannedFirstReceivers = true;
+                    for (int i = 0; i < receivers.size(); i++) {
+                        ResolveInfo ri = receivers.get(i);
                         if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                             ComponentName cn = new ComponentName(
                                     ri.activityInfo.packageName, ri.activityInfo.name);
                             if (singleUserReceivers == null) {
                                 singleUserReceivers = new HashSet<ComponentName>();
                             }
-                            if (!singleUserReceivers.contains(cn)) {
-                                singleUserReceivers.add(cn);
-                                receivers.add(ri);
-                            }
-                        } else {
-                            receivers.add(ri);
+                            singleUserReceivers.add(cn);
                         }
                     }
                 }
+                // Add the new results to the existing results, tracking
+                // and de-dupping single user receivers.
+                for (int i = 0; i < newReceivers.size(); i++) {
+                    ResolveInfo ri = newReceivers.get(i);
+                    if ((ri.activityInfo.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                        ComponentName cn = new ComponentName(
+                                ri.activityInfo.packageName, ri.activityInfo.name);
+                        if (singleUserReceivers == null) {
+                            singleUserReceivers = new HashSet<ComponentName>();
+                        }
+                        if (!singleUserReceivers.contains(cn)) {
+                            singleUserReceivers.add(cn);
+                            receivers.add(ri);
+                        }
+                    } else {
+                        receivers.add(ri);
+                    }
+                }
             }
-        } catch (RemoteException ex) {
-            // pm is in same process, this will never happen.
         }
         if (receivers != null && broadcastAllowList != null) {
             for (int i = receivers.size() - 1; i >= 0; i--) {
@@ -13331,8 +13326,7 @@
         List receivers = null;
         List<BroadcastFilter> registeredReceivers = null;
         // Need to resolve the intent to interested receivers...
-        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
-                 == 0) {
+        if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
             receivers = collectReceiverComponents(
                     intent, resolvedType, callingUid, users, broadcastAllowList);
         }
@@ -16658,13 +16652,6 @@
         if (updateFrameworkRes) {
             ParsingPackageUtils.readConfigUseRoundIcon(null);
         }
-
-        AppWidgetManagerInternal widgets = LocalServices.getService(AppWidgetManagerInternal.class);
-        if (widgets != null) {
-            widgets.applyResourceOverlaysToWidgets(new HashSet<>(packagesToUpdate), userId,
-                    updateFrameworkRes);
-        }
-
         mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);
 
         if (updateFrameworkRes) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index fcd198e..2f69abf 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -738,6 +738,11 @@
     private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
     private long mLoweredFromNormalToVibrateTime;
 
+    // Uid of the active hotword detection service to check if caller is the one or not.
+    @GuardedBy("mHotwordDetectionServiceUidLock")
+    private int mHotwordDetectionServiceUid = android.os.Process.INVALID_UID;
+    private final Object mHotwordDetectionServiceUidLock = new Object();
+
     // Array of Uids of valid accessibility services to check if caller is one of them
     private final Object mAccessibilityServiceUidsLock = new Object();
     @GuardedBy("mAccessibilityServiceUidsLock")
@@ -1339,6 +1344,9 @@
             updateAssistantUId(true);
             AudioSystem.setRttEnabled(mRttEnabled);
         }
+        synchronized (mHotwordDetectionServiceUidLock) {
+            AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+        }
         synchronized (mAccessibilityServiceUidsLock) {
             AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
         }
@@ -9082,6 +9090,16 @@
         }
 
         @Override
+        public void setHotwordDetectionServiceUid(int uid) {
+            synchronized (mHotwordDetectionServiceUidLock) {
+                if (mHotwordDetectionServiceUid != uid) {
+                    mHotwordDetectionServiceUid = uid;
+                    AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+                }
+            }
+        }
+
+        @Override
         public void setAccessibilityServiceUids(IntArray uids) {
             synchronized (mAccessibilityServiceUidsLock) {
                 if (uids.size() == 0) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index 973fbd2..6d56780 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -367,6 +367,14 @@
     }
 
     /**
+     * Same as {@link AudioSystem#setHotwordDetectionServiceUid(int)}
+     * Communicate UID of current HotwordDetectionService to audio policy service.
+     */
+    public int setHotwordDetectionServiceUid(int uid) {
+        return AudioSystem.setHotwordDetectionServiceUid(uid);
+    }
+
+    /**
      * Same as {@link AudioSystem#setCurrentImeUid(int)}
      * Communicate UID of current InputMethodService to audio policy service.
      */
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index afd1889..a0944c0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -63,8 +63,6 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
-import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
 import android.hardware.display.DisplayViewport;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -636,6 +634,9 @@
         synchronized (mSyncRoot) {
             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
             if (display != null) {
+                // Do not let constrain be overwritten by override from WindowManager.
+                info.shouldConstrainMetricsForLauncher =
+                        display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher;
                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
                     handleLogicalDisplayChangedLocked(display);
                     scheduleTraversalLocked(false);
@@ -1723,6 +1724,21 @@
         }
     }
 
+    void setShouldConstrainMetricsForLauncher(boolean constrain) {
+        // Apply constrain for every display.
+        synchronized (mSyncRoot) {
+            int[] displayIds = mLogicalDisplayMapper.getDisplayIdsLocked(Process.myUid());
+            for (int i : displayIds) {
+                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(i);
+                if (display == null) {
+                    return;
+                }
+                display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher = constrain;
+                setDisplayInfoOverrideFromWindowManagerInternal(i, display.getDisplayInfoLocked());
+            }
+        }
+    }
+
     private void clearViewportsLocked() {
         mViewports.clear();
     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 48edb73..94e64f0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -58,6 +58,8 @@
                 return setDisplayModeDirectorLoggingEnabled(false);
             case "dwb-set-cct":
                 return setAmbientColorTemperatureOverride();
+            case "constrain-launcher-metrics":
+                return setConstrainLauncherMetrics();
             default:
                 return handleDefaultCommands(cmd);
         }
@@ -88,6 +90,9 @@
         pw.println("    Disable display mode director logging.");
         pw.println("  dwb-set-cct CCT");
         pw.println("    Sets the ambient color temperature override to CCT (use -1 to disable).");
+        pw.println("  constrain-launcher-metrics [true|false]");
+        pw.println("    Sets if Display#getRealSize and getRealMetrics should be constrained for ");
+        pw.println("    Launcher.");
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
@@ -150,4 +155,15 @@
         mService.setAmbientColorTemperatureOverride(cct);
         return 0;
     }
+
+    private int setConstrainLauncherMetrics() {
+        String constrainText = getNextArg();
+        if (constrainText == null) {
+            getErrPrintWriter().println("Error: no value specified");
+            return 1;
+        }
+        boolean constrain = Boolean.parseBoolean(constrainText);
+        mService.setShouldConstrainMetricsForLauncher(constrain);
+        return 0;
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index b0ad118..803ba40 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -153,7 +153,7 @@
                 updateVoteLocked(displayId, priority, vote);
             }
         };
-        mSensorObserver = new SensorObserver(context, ballotBox);
+        mSensorObserver = new SensorObserver(context, ballotBox, injector);
         mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
         mDeviceConfig = injector.getDeviceConfig();
@@ -2129,27 +2129,34 @@
         }
     }
 
-    private static class SensorObserver implements ProximityActiveListener {
-        private static final String PROXIMITY_SENSOR_NAME = null;
-        private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY;
+    private final class SensorObserver implements ProximityActiveListener,
+            DisplayManager.DisplayListener {
+        private final String mProximitySensorName = null;
+        private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
 
         private final BallotBox mBallotBox;
         private final Context mContext;
+        private final Injector mInjector;
 
         private DisplayManager mDisplayManager;
         private DisplayManagerInternal mDisplayManagerInternal;
         private boolean mIsProxActive = false;
+        private final SparseBooleanArray mDozeStateByDisplay;
 
-        SensorObserver(Context context, BallotBox ballotBox) {
+        SensorObserver(Context context, BallotBox ballotBox, Injector injector) {
             mContext = context;
             mBallotBox = ballotBox;
+            mInjector = injector;
+            mDozeStateByDisplay = new SparseBooleanArray();
         }
 
         @Override
         public void onProximityActive(boolean isActive) {
-            if (mIsProxActive != isActive) {
-                mIsProxActive = isActive;
-                recalculateVotes();
+            synchronized (mLock) {
+                if (mIsProxActive != isActive) {
+                    mIsProxActive = isActive;
+                    recalculateVotesLocked();
+                }
             }
         }
 
@@ -2160,17 +2167,27 @@
             final SensorManagerInternal sensorManager =
                     LocalServices.getService(SensorManagerInternal.class);
             sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
+
+            synchronized (mLock) {
+                for (Display d : mDisplayManager.getDisplays()) {
+                    mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
+                }
+            }
+            mInjector.registerDisplayListener(this, BackgroundThread.getHandler(),
+                    DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+                            | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+                            | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
         }
 
-        private void recalculateVotes() {
+        private void recalculateVotesLocked() {
             final Display[] displays = mDisplayManager.getDisplays();
             for (Display d : displays) {
                 int displayId = d.getDisplayId();
                 Vote vote = null;
-                if (mIsProxActive) {
+                if (mIsProxActive && !mDozeStateByDisplay.get(displayId)) {
                     final RefreshRateRange rate =
                             mDisplayManagerInternal.getRefreshRateForDisplayAndSensor(
-                                    displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE);
+                                    displayId, mProximitySensorName, mProximitySensorType);
                     if (rate != null) {
                         vote = Vote.forRefreshRates(rate.min, rate.max);
                     }
@@ -2182,6 +2199,41 @@
         void dumpLocked(PrintWriter pw) {
             pw.println("  SensorObserver");
             pw.println("    mIsProxActive=" + mIsProxActive);
+            pw.println("    mDozeStateByDisplay:");
+            for (int i = 0; i < mDozeStateByDisplay.size(); i++) {
+                final int id = mDozeStateByDisplay.keyAt(i);
+                final boolean dozed = mDozeStateByDisplay.valueAt(i);
+                pw.println("      " + id + " -> " + dozed);
+            }
+        }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId));
+            synchronized (mLock) {
+                mDozeStateByDisplay.put(displayId, isDozeState);
+                recalculateVotesLocked();
+            }
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            boolean wasDozeState = mDozeStateByDisplay.get(displayId);
+            synchronized (mLock) {
+                mDozeStateByDisplay.put(displayId,
+                        mInjector.isDozeState(mDisplayManager.getDisplay(displayId)));
+                if (wasDozeState != mDozeStateByDisplay.get(displayId)) {
+                    recalculateVotesLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            synchronized (mLock) {
+                mDozeStateByDisplay.delete(displayId);
+                recalculateVotesLocked();
+            }
         }
     }
 
@@ -2413,6 +2465,8 @@
                 Handler handler, long flags);
 
         BrightnessInfo getBrightnessInfo(int displayId);
+
+        boolean isDozeState(Display d);
     }
 
     @VisibleForTesting
@@ -2465,6 +2519,11 @@
             return null;
         }
 
+        @Override
+        public boolean isDozeState(Display d) {
+            return Display.isDozeState(d.getState());
+        }
+
         private DisplayManager getDisplayManager() {
             if (mDisplayManager == null) {
                 mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 5186744..86c9ca9 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -233,6 +233,8 @@
                 info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
                 info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
                 info.roundedCorners = mOverrideDisplayInfo.roundedCorners;
+                info.shouldConstrainMetricsForLauncher =
+                        mOverrideDisplayInfo.shouldConstrainMetricsForLauncher;
             }
             mInfo.set(info);
         }
diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java
new file mode 100644
index 0000000..4d36078
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Feature action that queries the Short Audio Descriptor (SAD) of another device. This action is
+ * initiated from the Android system working as TV device to get the SAD of the connected audio
+ * system device.
+ * <p>
+ * Package-private
+ */
+final class RequestSadAction extends HdmiCecFeatureAction {
+    private static final String TAG = "RequestSadAction";
+
+    // 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 List<Integer> ALL_CEC_CODECS = new ArrayList<Integer>(Arrays.asList(
+            Constants.AUDIO_CODEC_LPCM,
+            Constants.AUDIO_CODEC_DD,
+            Constants.AUDIO_CODEC_MPEG1,
+            Constants.AUDIO_CODEC_MP3,
+            Constants.AUDIO_CODEC_MPEG2,
+            Constants.AUDIO_CODEC_AAC,
+            Constants.AUDIO_CODEC_DTS,
+            Constants.AUDIO_CODEC_ATRAC,
+            Constants.AUDIO_CODEC_ONEBITAUDIO,
+            Constants.AUDIO_CODEC_DDP,
+            Constants.AUDIO_CODEC_DTSHD,
+            Constants.AUDIO_CODEC_TRUEHD,
+            Constants.AUDIO_CODEC_DST,
+            Constants.AUDIO_CODEC_WMAPRO,
+            Constants.AUDIO_CODEC_MAX));
+    private static final int MAX_SAD_PER_REQUEST = 4;
+    private static final int RETRY_COUNTER_MAX = 1;
+    private final int mTargetAddress;
+    private final RequestSadCallback mCallback;
+    // List of all valid SADs reported by the target device. Not parsed nor deduplicated.
+    private final List<byte[]> mSupportedSads = new ArrayList<>();
+    private int mQueriedSadCount = 0; // Number of SADs queries that has already been completed
+    private int mTimeoutRetry = 0; // Number of times we have already retried on time-out
+
+    /**
+     * Constructor.
+     *
+     * @param source        an instance of {@link HdmiCecLocalDevice}.
+     * @param targetAddress the logical address the SAD is directed at.
+     */
+    RequestSadAction(HdmiCecLocalDevice source, int targetAddress, RequestSadCallback callback) {
+        super(source);
+        mTargetAddress = targetAddress;
+        mCallback = Objects.requireNonNull(callback);
+    }
+
+
+    @Override
+    boolean start() {
+        querySad();
+        return true;
+    }
+
+    private void querySad() {
+        if (mQueriedSadCount >= ALL_CEC_CODECS.size()) {
+            wrapUpAndFinish();
+            return;
+        }
+        int[] codecsToQuery = ALL_CEC_CODECS.subList(mQueriedSadCount,
+                Math.min(ALL_CEC_CODECS.size(), mQueriedSadCount + MAX_SAD_PER_REQUEST))
+                    .stream().mapToInt(i -> i).toArray();
+        sendCommand(HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(getSourceAddress(),
+                mTargetAddress, codecsToQuery));
+        mState = STATE_WAITING_FOR_REPORT_SAD;
+        addTimer(mState, HdmiConfig.TIMEOUT_MS);
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WAITING_FOR_REPORT_SAD
+                || mTargetAddress != cmd.getSource()) {
+            return false;
+        }
+        if (cmd.getOpcode() == Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR) {
+            if (cmd.getParams() == null || cmd.getParams().length == 0
+                    || cmd.getParams().length % 3 != 0) {
+                // Invalid message. Wait for time-out and query again.
+                return true;
+            }
+            for (int i = 0; i < cmd.getParams().length - 2; i += 3) {
+                if (isValidCodec(cmd.getParams()[i])) {
+                    byte[] sad = new byte[]{cmd.getParams()[i], cmd.getParams()[i + 1],
+                            cmd.getParams()[i + 2]};
+                    updateResult(sad);
+                }
+                // Don't include invalid codecs in the result. Don't query again.
+                Slog.w(TAG, "Received invalid codec " + cmd.getParams()[i] + ".");
+            }
+            mQueriedSadCount += MAX_SAD_PER_REQUEST;
+            mTimeoutRetry = 0;
+            querySad();
+            return true;
+        }
+        if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
+                && (cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR
+                && (cmd.getParams()[1] & 0xFF) == Constants.ABORT_INVALID_OPERAND) {
+            // Queried SADs are not supported
+            mQueriedSadCount += MAX_SAD_PER_REQUEST;
+            mTimeoutRetry = 0;
+            querySad();
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isValidCodec(byte codec) {
+        return Constants.AUDIO_CODEC_NONE < (codec & 0xFF)
+                && (codec & 0xFF) <= Constants.AUDIO_CODEC_MAX;
+    }
+
+    private void updateResult(byte[] sad) {
+        mSupportedSads.add(sad);
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+        if (state == STATE_WAITING_FOR_REPORT_SAD) {
+            if (++mTimeoutRetry <= RETRY_COUNTER_MAX) {
+                querySad();
+                return;
+            }
+            mQueriedSadCount += MAX_SAD_PER_REQUEST;
+            mTimeoutRetry = 0;
+            querySad();
+        }
+    }
+
+    private void wrapUpAndFinish() {
+        mCallback.onRequestSadDone(mSupportedSads);
+        finish();
+    }
+
+    /**
+     * Interface used to report result of SAD request.
+     */
+    interface RequestSadCallback {
+        /**
+         * Called when SAD request is done.
+         *
+         * @param sads a list of all supported SADs. It can be an empty list.
+         */
+        void onRequestSadDone(List<byte[]> supportedSads);
+    }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c553176..c905fe0 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -180,7 +180,7 @@
     private static final boolean UNTRUSTED_TOUCHES_TOAST = false;
 
     public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
-            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", true);
+            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
 
     // Pointer to native input manager service object.
     private final long mPtr;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 87982cd..bff7e52 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1237,15 +1237,19 @@
         }
 
         @Override
-        public MediaSession.Token getMediaKeyEventSession() {
+        public MediaSession.Token getMediaKeyEventSession(ComponentName notificationListener) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
-            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+            final int userId = userHandle.getIdentifier();
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!hasMediaControlPermission(pid, uid)) {
-                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
-                            + " get the media key event session");
+                if (!hasMediaControlPermission(pid, uid)
+                        && !isEnabledNotificationListener(
+                                notificationListener, userHandle, userId)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+                            + " notification listener is required to"
+                            + " get media key event session.");
                 }
                 MediaSessionRecordImpl record;
                 synchronized (mLock) {
@@ -1268,15 +1272,19 @@
         }
 
         @Override
-        public String getMediaKeyEventSessionPackageName() {
+        public String getMediaKeyEventSessionPackageName(ComponentName notificationListener) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
-            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+            final int userId = userHandle.getIdentifier();
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!hasMediaControlPermission(pid, uid)) {
-                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
-                            + " get the media key event session package");
+                if (!hasMediaControlPermission(pid, uid)
+                        && !isEnabledNotificationListener(
+                        notificationListener, userHandle, userId)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+                            + " notification listener is required to"
+                            + " get media key event session package name");
                 }
                 MediaSessionRecordImpl record;
                 synchronized (mLock) {
@@ -1588,19 +1596,25 @@
 
         @Override
         public void addOnMediaKeyEventSessionChangedListener(
-                final IOnMediaKeyEventSessionChangedListener listener) {
+                final IOnMediaKeyEventSessionChangedListener listener,
+                final ComponentName notificationListener) {
             if (listener == null) {
-                Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+                Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: listener is null, ignoring");
                 return;
             }
+
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
-            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+            final int userId = userHandle.getIdentifier();
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!hasMediaControlPermission(pid, uid)) {
-                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
-                            + "  add MediaKeyEventSessionChangedListener");
+                if (!hasMediaControlPermission(pid, uid)
+                        && !isEnabledNotificationListener(
+                                notificationListener, userHandle, userId)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+                            + " notification listener is required to"
+                            + " add MediaKeyEventSessionChangedListener.");
                 }
                 synchronized (mLock) {
                     FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1622,18 +1636,16 @@
         public void removeOnMediaKeyEventSessionChangedListener(
                 final IOnMediaKeyEventSessionChangedListener listener) {
             if (listener == null) {
-                Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+                Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: listener is null,"
+                        + " ignoring");
                 return;
             }
+
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!hasMediaControlPermission(pid, uid)) {
-                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
-                            + "  remove MediaKeyEventSessionChangedListener");
-                }
                 synchronized (mLock) {
                     FullUserRecord user = getFullUserRecordLocked(userId);
                     if (user == null || user.mFullUserId != userId) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 6ae4dd0..7889ff2 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -250,6 +250,14 @@
             throws PackageManagerException;
 
     /**
+     * Returns {@code ApeInfo} about apex sessions that have been marked ready via
+     * {@link #markStagedSessionReady(int)}
+     *
+     * Returns empty array if there is no staged apex session or if there is any error.
+     */
+    abstract ApexInfo[] getStagedApexInfos(ApexSessionParams params);
+
+    /**
      * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
      * applied at next reboot.
      *
@@ -758,6 +766,19 @@
         }
 
         @Override
+        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+            try {
+                return waitForApexService().getStagedApexInfos(params);
+            } catch (RemoteException re) {
+                Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
+                throw new RuntimeException(re);
+            } catch (Exception e) {
+                Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
+                return new ApexInfo[0];
+            }
+        }
+
+        @Override
         void markStagedSessionReady(int sessionId) throws PackageManagerException {
             try {
                 waitForApexService().markStagedSessionReady(sessionId);
@@ -1250,6 +1271,11 @@
         }
 
         @Override
+        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
         void markStagedSessionReady(int sessionId) {
             throw new UnsupportedOperationException();
         }
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index e87dbed..45ce3980 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -1207,7 +1207,10 @@
                     // Check for shared user id changes
                     String invalidPackageName = null;
                     if (!Objects.equals(oldPackage.getSharedUserId(),
-                            parsedPackage.getSharedUserId())) {
+                            parsedPackage.getSharedUserId())
+                            // Don't mark as invalid if the app is trying to
+                            // leave a sharedUserId
+                            && parsedPackage.getSharedUserId() != null) {
                         invalidPackageName = parsedPackage.getPackageName();
                     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c9e4829..d2c15ab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -289,6 +289,7 @@
 import android.util.PackageUtils;
 import android.util.Pair;
 import android.util.PrintStreamPrinter;
+import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -327,6 +328,7 @@
 import com.android.server.DeviceIdleInternal;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
+import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.PackageWatchdog;
@@ -701,6 +703,20 @@
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
     private static final long ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES = 142191088;
 
+    /**
+     * Components of apps targeting Android T and above will stop receiving intents from
+     * external callers that do not match its declared intent filters.
+     *
+     * When an app registers an exported component in its manifest and adds an <intent-filter>,
+     * the component can be started by any intent - even those that do not match the intent filter.
+     * This has proven to be something that many developers find counterintuitive.
+     * Without checking the intent when the component is started, in some circumstances this can
+     * allow 3P apps to trigger internal-only functionality.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+    private static final long ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS = 161252188;
+
     public static final String PLATFORM_PACKAGE_NAME = "android";
 
     static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -2160,9 +2176,11 @@
                     false /* requireFullPermission */, false /* checkShell */,
                     "query intent activities");
             final String pkgName = intent.getPackage();
+            Intent originalIntent = null;
             ComponentName comp = intent.getComponent();
             if (comp == null) {
                 if (intent.getSelector() != null) {
+                    originalIntent = intent;
                     intent = intent.getSelector();
                     comp = intent.getComponent();
                 }
@@ -2172,8 +2190,9 @@
                     comp != null || pkgName != null /*onlyExposedExplicitly*/,
                     isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                             flags));
+            List<ResolveInfo> list = Collections.emptyList();
+            boolean skipPostResolution = false;
             if (comp != null) {
-                final List<ResolveInfo> list = new ArrayList<>(1);
                 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
                 if (ai != null) {
                     // When specifying an explicit component, we prevent the activity from being
@@ -2216,35 +2235,45 @@
                     if (!blockInstantResolution && !blockNormalResolution) {
                         final ResolveInfo ri = new ResolveInfo();
                         ri.activityInfo = ai;
+                        list = new ArrayList<>(1);
                         list.add(ri);
+                        applyEnforceIntentFilterMatching(
+                                mInjector.getCompatibility(), mComponentResolver,
+                                list, false, intent, resolvedType, filterCallingUid);
                     }
                 }
-
-                return applyPostResolutionFilter(
-                        list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
-                        resolveForStart,
-                        userId, intent);
+            } else {
+                QueryIntentActivitiesResult lockedResult =
+                        queryIntentActivitiesInternalBody(
+                                intent, resolvedType, flags, filterCallingUid, userId,
+                                resolveForStart, allowDynamicSplits, pkgName, instantAppPkgName);
+                if (lockedResult.answer != null) {
+                    skipPostResolution = true;
+                    list = lockedResult.answer;
+                } else {
+                    if (lockedResult.addInstant) {
+                        String callingPkgName = getInstantAppPackageName(filterCallingUid);
+                        boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+                        lockedResult.result = maybeAddInstantAppInstaller(
+                                lockedResult.result, intent, resolvedType, flags,
+                                userId, resolveForStart, isRequesterInstantApp);
+                    }
+                    if (lockedResult.sortResult) {
+                        lockedResult.result.sort(RESOLVE_PRIORITY_SORTER);
+                    }
+                    list = lockedResult.result;
+                }
             }
 
-            QueryIntentActivitiesResult lockedResult =
-                    queryIntentActivitiesInternalBody(
-                        intent, resolvedType, flags, filterCallingUid, userId, resolveForStart,
-                        allowDynamicSplits, pkgName, instantAppPkgName);
-            if (lockedResult.answer != null) {
-                return lockedResult.answer;
+            if (originalIntent != null) {
+                // We also have to ensure all components match the original intent
+                applyEnforceIntentFilterMatching(
+                        mInjector.getCompatibility(), mComponentResolver,
+                        list, false, originalIntent, resolvedType, filterCallingUid);
             }
 
-            if (lockedResult.addInstant) {
-                String callingPkgName = getInstantAppPackageName(filterCallingUid);
-                boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
-                lockedResult.result = maybeAddInstantAppInstaller(lockedResult.result, intent,
-                        resolvedType, flags, userId, resolveForStart, isRequesterInstantApp);
-            }
-            if (lockedResult.sortResult) {
-                Collections.sort(lockedResult.result, RESOLVE_PRIORITY_SORTER);
-            }
-            return applyPostResolutionFilter(
-                    lockedResult.result, instantAppPkgName, allowDynamicSplits, filterCallingUid,
+            return skipPostResolution ? list : applyPostResolutionFilter(
+                    list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
                     resolveForStart, userId, intent);
         }
 
@@ -2267,15 +2296,17 @@
             final String instantAppPkgName = getInstantAppPackageName(callingUid);
             flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
                     false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
+            Intent originalIntent = null;
             ComponentName comp = intent.getComponent();
             if (comp == null) {
                 if (intent.getSelector() != null) {
+                    originalIntent = intent;
                     intent = intent.getSelector();
                     comp = intent.getComponent();
                 }
             }
+            List<ResolveInfo> list = Collections.emptyList();
             if (comp != null) {
-                final List<ResolveInfo> list = new ArrayList<>(1);
                 final ServiceInfo si = getServiceInfo(comp, flags, userId);
                 if (si != null) {
                     // When specifying an explicit component, we prevent the service from being
@@ -2308,14 +2339,26 @@
                     if (!blockInstantResolution && !blockNormalResolution) {
                         final ResolveInfo ri = new ResolveInfo();
                         ri.serviceInfo = si;
+                        list = new ArrayList<>(1);
                         list.add(ri);
+                        applyEnforceIntentFilterMatching(
+                                mInjector.getCompatibility(), mComponentResolver,
+                                list, false, intent, resolvedType, callingUid);
                     }
                 }
-                return list;
+            } else {
+                list = queryIntentServicesInternalBody(intent, resolvedType, flags,
+                        userId, callingUid, instantAppPkgName);
             }
 
-            return queryIntentServicesInternalBody(intent, resolvedType, flags,
-                    userId, callingUid, instantAppPkgName);
+            if (originalIntent != null) {
+                // We also have to ensure all components match the original intent
+                applyEnforceIntentFilterMatching(
+                        mInjector.getCompatibility(), mComponentResolver,
+                        list, false, originalIntent, resolvedType, callingUid);
+            }
+
+            return list;
         }
 
         protected @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
@@ -5544,10 +5587,8 @@
             }
         }
     }
-    private static final ThreadLocal<ThreadComputer> sThreadComputer = new ThreadLocal<>() {
-            @Override protected ThreadComputer initialValue() {
-                return new ThreadComputer();
-            }};
+    private static final ThreadLocal<ThreadComputer> sThreadComputer =
+            ThreadLocal.withInitial(ThreadComputer::new);
 
     /**
      * This lock is used to make reads from {@link #sSnapshotInvalid} and
@@ -8136,7 +8177,7 @@
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+                UserHandle.USER_SYSTEM, Binder.getCallingUid());
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
         } else if (matches.size() == 0) {
@@ -8232,7 +8273,7 @@
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+                UserHandle.USER_SYSTEM, Binder.getCallingUid());
         ResolveInfo best = null;
         final int N = matches.size();
         for (int i = 0; i < N; i++) {
@@ -8260,7 +8301,7 @@
         Intent intent = new Intent(Intent.ACTION_DOMAINS_NEED_VERIFICATION);
         List<ResolveInfo> matches = queryIntentReceiversInternal(intent, null,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+                UserHandle.USER_SYSTEM, Binder.getCallingUid());
         ResolveInfo best = null;
         final int N = matches.size();
         for (int i = 0; i < N; i++) {
@@ -10939,30 +10980,32 @@
     @Override
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
             String resolvedType, int flags, int userId) {
-        return new ParceledListSlice<>(
-                queryIntentReceiversInternal(intent, resolvedType, flags, userId,
-                        false /*allowDynamicSplits*/));
+        return new ParceledListSlice<>(queryIntentReceiversInternal(intent, resolvedType,
+                flags, userId, Binder.getCallingUid()));
     }
 
+    // In this method, we have to know the actual calling UID, but in some cases Binder's
+    // call identity is removed, so the UID has to be passed in explicitly.
     private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
-            String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
+            String resolvedType, int flags, int userId, int filterCallingUid) {
         if (!mUserManager.exists(userId)) return Collections.emptyList();
-        final int callingUid = Binder.getCallingUid();
-        enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+        enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
                 false /*checkShell*/, "query intent receivers");
-        final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
+        final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+        flags = updateFlagsForResolve(flags, userId, filterCallingUid, false /*includeInstantApps*/,
                 isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                         flags));
+        Intent originalIntent = null;
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
+                originalIntent = intent;
                 intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
+        List<ResolveInfo> list = Collections.emptyList();
         if (comp != null) {
-            final List<ResolveInfo> list = new ArrayList<>(1);
             final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
             if (ai != null) {
                 // When specifying an explicit component, we prevent the activity from being
@@ -10998,40 +11041,44 @@
                 if (!blockResolution) {
                     ResolveInfo ri = new ResolveInfo();
                     ri.activityInfo = ai;
+                    list = new ArrayList<>(1);
                     list.add(ri);
+                    applyEnforceIntentFilterMatching(
+                            mInjector.getCompatibility(), mComponentResolver,
+                            list, true, intent, resolvedType, filterCallingUid);
                 }
             }
-            return applyPostResolutionFilter(
-                    list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
-                    intent);
+        } else {
+            // reader
+            synchronized (mLock) {
+                String pkgName = intent.getPackage();
+                if (pkgName == null) {
+                    final List<ResolveInfo> result =
+                            mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
+                    if (result != null) {
+                        list = result;
+                    }
+                }
+                final AndroidPackage pkg = mPackages.get(pkgName);
+                if (pkg != null) {
+                    final List<ResolveInfo> result = mComponentResolver.queryReceivers(
+                            intent, resolvedType, flags, pkg.getReceivers(), userId);
+                    if (result != null) {
+                        list = result;
+                    }
+                }
+            }
         }
 
-        // reader
-        synchronized (mLock) {
-            String pkgName = intent.getPackage();
-            if (pkgName == null) {
-                final List<ResolveInfo> result =
-                        mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
-                if (result == null) {
-                    return Collections.emptyList();
-                }
-                return applyPostResolutionFilter(
-                        result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
-                        intent);
-            }
-            final AndroidPackage pkg = mPackages.get(pkgName);
-            if (pkg != null) {
-                final List<ResolveInfo> result = mComponentResolver.queryReceivers(
-                        intent, resolvedType, flags, pkg.getReceivers(), userId);
-                if (result == null) {
-                    return Collections.emptyList();
-                }
-                return applyPostResolutionFilter(
-                        result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
-                        intent);
-            }
-            return Collections.emptyList();
+        if (originalIntent != null) {
+            // We also have to ensure all components match the original intent
+            applyEnforceIntentFilterMatching(
+                    mInjector.getCompatibility(), mComponentResolver,
+                    list, true, originalIntent, resolvedType, filterCallingUid);
         }
+
+        return applyPostResolutionFilter(
+                list, instantAppPkgName, false, filterCallingUid, false, userId, intent);
     }
 
     @Override
@@ -11073,6 +11120,68 @@
                 includeInstantApps);
     }
 
+    // Static to give access to ComputeEngine
+    private static void applyEnforceIntentFilterMatching(
+            PlatformCompat compat, ComponentResolver resolver,
+            List<ResolveInfo> resolveInfos, boolean isReceiver,
+            Intent intent, String resolvedType, int filterCallingUid) {
+        // Do not enforce filter matching when the caller is system or root.
+        // see ActivityManager#checkComponentPermission(String, int, int, boolean)
+        if (filterCallingUid == Process.ROOT_UID || filterCallingUid == Process.SYSTEM_UID) {
+            return;
+        }
+
+        final Printer logPrinter = DEBUG_INTENT_MATCHING
+                ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
+                : null;
+
+        for (int i = resolveInfos.size() - 1; i >= 0; --i) {
+            final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
+
+            // Do not enforce filter matching when the caller is the same app
+            if (info.applicationInfo.uid == filterCallingUid) {
+                continue;
+            }
+
+            // Only enforce filter matching if target app's target SDK >= T
+            if (!compat.isChangeEnabledInternal(
+                    ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
+                continue;
+            }
+
+            final ParsedMainComponent comp;
+            if (info instanceof ActivityInfo) {
+                if (isReceiver) {
+                    comp = resolver.getReceiver(info.getComponentName());
+                } else {
+                    comp = resolver.getActivity(info.getComponentName());
+                }
+            } else if (info instanceof ServiceInfo) {
+                comp = resolver.getService(info.getComponentName());
+            } else {
+                // This shall never happen
+                throw new IllegalArgumentException("Unsupported component type");
+            }
+
+            if (comp.getIntents().isEmpty()) {
+                continue;
+            }
+
+            final boolean match = comp.getIntents().stream().anyMatch(
+                    f -> IntentResolver.intentMatchesFilter(f, intent, resolvedType));
+            if (!match) {
+                Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
+                Slog.w(TAG, "Access blocked: " + comp.getComponentName());
+                if (DEBUG_INTENT_MATCHING) {
+                    Slog.v(TAG, "Component intent filters:");
+                    comp.getIntents().forEach(f -> f.dump(logPrinter, "  "));
+                    Slog.v(TAG, "-----------------------------");
+                }
+                resolveInfos.remove(i);
+            }
+        }
+    }
+
     @Override
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
             String resolvedType, int flags, int userId) {
@@ -13528,10 +13637,6 @@
         }
     }
 
-
-
-
-
     /**
      * Returns the actual scan flags depending upon the state of the other settings.
      * <p>Updated system applications will not have the following flags set
@@ -13699,10 +13804,10 @@
      */
     boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
             throws PackageManagerException {
-        if (!result.mExistingSettingCopied) {
+        if (!result.mExistingSettingCopied || result.mNeedsNewAppId) {
             // THROWS: when we can't allocate a user id. add call to check if there's
             // enough space to ensure we won't throw; otherwise, don't modify state
-            return mSettings.registerAppIdLPw(result.mPkgSetting);
+            return mSettings.registerAppIdLPw(result.mPkgSetting, result.mNeedsNewAppId);
         }
         return false;
     }
@@ -14072,15 +14177,25 @@
             }
         }
 
+        boolean leavingSharedUser = false;
+
         if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) {
-            PackageManagerService.reportSettingsProblem(Log.WARN,
-                    "Package " + parsedPackage.getPackageName() + " shared user changed from "
-                            + (pkgSetting.sharedUser != null
-                            ? pkgSetting.sharedUser.name : "<nothing>")
-                            + " to "
-                            + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
-                            + "; replacing with new");
-            pkgSetting = null;
+            if (pkgSetting.sharedUser != null && sharedUserSetting == null) {
+                leavingSharedUser = true;
+                // Log that something is leaving shareduid and keep going
+                Slog.i(TAG,
+                        "Package " + parsedPackage.getPackageName() + " shared user changed from "
+                        + pkgSetting.sharedUser.name + " to " + "<nothing>.");
+            } else {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Package " + parsedPackage.getPackageName() + " shared user changed from "
+                                + (pkgSetting.sharedUser != null
+                                ? pkgSetting.sharedUser.name : "<nothing>")
+                                + " to "
+                                + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
+                                + "; replacing with new");
+                pkgSetting = null;
+            }
         }
 
         String[] usesStaticLibraries = null;
@@ -14356,7 +14471,8 @@
         }
 
         return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
-                !createNewPackage /* existingSettingCopied */, staticSharedLibraryInfo,
+                !createNewPackage /* existingSettingCopied */,
+                leavingSharedUser /* needsNewAppId */, staticSharedLibraryInfo,
                 dynamicSharedLibraryInfos);
     }
 
@@ -21735,6 +21851,10 @@
                 continue;
             }
 
+            // TODO@ashfall check ScanResult.mNeedsNewAppId, and if true instead
+            // of creating app data, migrate / change ownership of existing
+            // data.
+
             if (ps.getInstalled(user.id)) {
                 // TODO: when user data is locked, mark that we're still dirty
                 prepareAppData(batch, pkg, user.id, flags).thenRun(() -> {
@@ -22399,7 +22519,7 @@
     }
 
     boolean readPermissionStateForUser(@UserIdInt int userId) {
-        synchronized (mPackages) {
+        synchronized (mLock) {
             mPermissionManager.writeLegacyPermissionStateTEMP();
             mSettings.readPermissionStateForUserSyncLPr(userId);
             mPermissionManager.readLegacyPermissionStateTEMP();
@@ -22471,7 +22591,7 @@
         if (packageName == null || alias == null) {
             return null;
         }
-        synchronized(mLock) {
+        synchronized (mLock) {
             final AndroidPackage pkg = mPackages.get(packageName);
             if (pkg == null
                     || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -22518,7 +22638,7 @@
         if (packageName == null || ks == null) {
             return false;
         }
-        synchronized(mLock) {
+        synchronized (mLock) {
             final AndroidPackage pkg = mPackages.get(packageName);
             if (pkg == null
                     || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -23401,6 +23521,13 @@
         }
 
         @Override
+        public List<ResolveInfo> queryIntentReceivers(Intent intent,
+                String resolvedType, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this.queryIntentReceiversInternal(intent, resolvedType,
+                    flags, userId, filterCallingUid);
+        }
+
+        @Override
         public List<ResolveInfo> queryIntentServices(
                 Intent intent, int flags, int callingUid, int userId) {
             final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java
index 6915a50..34f86ba 100644
--- a/services/core/java/com/android/server/pm/ScanResult.java
+++ b/services/core/java/com/android/server/pm/ScanResult.java
@@ -36,6 +36,11 @@
      */
     public final boolean mExistingSettingCopied;
     /**
+     * Whether or not the original PackageSetting needs to be updated with
+     * a new uid. Useful when leaving a sharedUserID.
+     */
+    public final boolean mNeedsNewAppId;
+    /**
      * The final package settings. This may be the same object passed in
      * the {@link ScanRequest}, but, with modified values.
      */
@@ -52,6 +57,7 @@
             ScanRequest request, boolean success,
             @Nullable PackageSetting pkgSetting,
             @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
+            boolean needsNewAppId,
             SharedLibraryInfo staticSharedLibraryInfo,
             List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
         mRequest = request;
@@ -59,6 +65,7 @@
         mPkgSetting = pkgSetting;
         mChangedAbiCodePath = changedAbiCodePath;
         mExistingSettingCopied = existingSettingCopied;
+        mNeedsNewAppId = needsNewAppId;
         mStaticSharedLibraryInfo = staticSharedLibraryInfo;
         mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3995cc6..902263a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1126,9 +1126,9 @@
      *         already registered.
      * @throws PackageManagerException If a user ID could not be allocated.
      */
-    boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+    boolean registerAppIdLPw(PackageSetting p, boolean forceNew) throws PackageManagerException {
         final boolean createdNew;
-        if (p.appId == 0) {
+        if (p.appId == 0 || forceNew) {
             // Assign new user ID
             p.appId = acquireAndRegisterNewAppIdLPw(p);
             createdNew = true;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 3eb4bde..2fcc4b2 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -55,6 +55,7 @@
  */
 public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
 
+    @NonNull
     public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
             @NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
         return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
@@ -70,6 +71,7 @@
      * this case only cares about
      * volumeUuid, just fake it rather than having separate method paths.
      */
+    @NonNull
     public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
         return ((ParsedPackage) PackageImpl.forTesting(packageName)
                 .setVolumeUuid(volumeUuid)
@@ -77,11 +79,13 @@
                 .hideAsFinal();
     }
 
+    @NonNull
     @VisibleForTesting
     public static ParsingPackage forTesting(String packageName) {
         return forTesting(packageName, "");
     }
 
+    @NonNull
     @VisibleForTesting
     public static ParsingPackage forTesting(String packageName, String baseCodePath) {
         return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
@@ -568,6 +572,7 @@
         assignDerivedFields();
     }
 
+    @NonNull
     public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
         @Override
         public PackageImpl createFromParcel(Parcel source) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index e85fa23..0f4f58b 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -228,17 +228,20 @@
 
             Vibration.Status status = null;
             while (!mStepQueue.isEmpty()) {
-                long waitTime = mStepQueue.calculateWaitTime();
-                if (waitTime <= 0) {
-                    mStepQueue.consumeNext();
-                } else {
-                    synchronized (mLock) {
+                long waitTime;
+                synchronized (mLock) {
+                    waitTime = mStepQueue.calculateWaitTime();
+                    if (waitTime > 0) {
                         try {
                             mLock.wait(waitTime);
                         } catch (InterruptedException e) {
                         }
                     }
                 }
+                // If we waited, the queue may have changed, so let the loop run again.
+                if (waitTime <= 0) {
+                    mStepQueue.consumeNext();
+                }
                 Vibration.Status currentStatus = mStop ? Vibration.Status.CANCELLED
                         : mStepQueue.calculateVibrationStatus(sequentialEffectSize);
                 if (status == null && currentStatus != Vibration.Status.RUNNING) {
@@ -387,15 +390,13 @@
         }
 
         /** Returns the time in millis to wait before calling {@link #consumeNext()}. */
+        @GuardedBy("mLock")
         public long calculateWaitTime() {
-            Step nextStep;
-            synchronized (mLock) {
-                if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
-                    // Steps anticipated by vibrator complete callback should be played right away.
-                    return 0;
-                }
-                nextStep = mNextSteps.peek();
+            if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
+                // Steps anticipated by vibrator complete callback should be played right away.
+                return 0;
             }
+            Step nextStep = mNextSteps.peek();
             return nextStep == null ? 0 : nextStep.calculateWaitTime();
         }
 
@@ -603,7 +604,10 @@
             return false;
         }
 
-        /** Returns the time in millis to wait before playing this step. */
+        /**
+         * Returns the time in millis to wait before playing this step. This is performed
+         * while holding the queue lock, so should not rely on potentially slow operations.
+         */
         public long calculateWaitTime() {
             if (startTime == Long.MAX_VALUE) {
                 // This step don't have a predefined start time, it's just marked to be executed
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 331b8de..675c7eb 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1197,10 +1197,10 @@
 
                 final Task task = r.getTask();
                 isLastRunningActivity = task.topRunningActivity() == r;
-                final Intent baseIntent = task.getBaseIntent();
-                final boolean activityIsBaseActivity = baseIntent != null
-                        && r.mActivityComponent.equals(baseIntent.getComponent());
-                baseActivityIntent = activityIsBaseActivity ? r.intent : null;
+
+                final boolean isBaseActivity = r.mActivityComponent.equals(task.realActivity);
+                baseActivityIntent = isBaseActivity ? r.intent : null;
+
                 launchedFromHome = r.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
             }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e6e18fd..37003ad 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3687,7 +3687,7 @@
 
     @Override
     void removeImmediately() {
-        if (!finishing) {
+        if (!isState(DESTROYING, DESTROYED)) {
             // If Task#removeImmediately is called directly with alive activities, ensure that the
             // activities are destroyed and detached from process.
             destroyImmediately("removeImmediately");
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 25827cf..19cf14f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1908,15 +1908,15 @@
 
         if (r.moveFocusableActivityToTop("setFocusedTask")) {
             mRootWindowContainer.resumeFocusedTasksTopActivities();
-        } else if (touchedActivity != null && touchedActivity != r
-                && touchedActivity.getTask() == r.getTask()
-                && touchedActivity.getTaskFragment() != r.getTaskFragment()) {
-            // Set the focused app directly since the focused window is not on the
-            // top-most TaskFragment of the top-most Task
-            final DisplayContent displayContent = touchedActivity.getDisplayContent();
-            displayContent.setFocusedApp(touchedActivity);
-            mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
-                    true /* updateInputWindows */);
+        } else if (touchedActivity != null && touchedActivity.isFocusable()) {
+            final TaskFragment parent = touchedActivity.getTaskFragment();
+            if (parent != null && parent.isEmbedded()) {
+                // Set the focused app directly if the focused window is currently embedded
+                final DisplayContent displayContent = touchedActivity.getDisplayContent();
+                displayContent.setFocusedApp(touchedActivity);
+                mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+                        true /* updateInputWindows */);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b2e7b8f..31f943b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -771,10 +771,19 @@
                 return true;
             }
 
-            if (focusedApp.getTask() == activity.getTask()
-                    && focusedApp.getTaskFragment() != activity.getTaskFragment()) {
-                // Do not use the activity window of another TaskFragment in the same leaf Task
-                return false;
+            // If the candidate activity is currently being embedded in the focused task, the
+            // activity cannot be focused unless it is on the same TaskFragment as the focusedApp's.
+            TaskFragment parent = activity.getTaskFragment();
+            if (parent != null && parent.isEmbedded()) {
+                Task hostTask = focusedApp.getTask();
+                if (hostTask.isEmbedded()) {
+                    // Use the hosting task if the current task is embedded.
+                    hostTask = hostTask.getParent().asTaskFragment().getTask();
+                }
+                if (activity.isDescendantOf(hostTask)
+                        && activity.getTaskFragment() != focusedApp.getTaskFragment()) {
+                    return false;
+                }
             }
         }
 
@@ -4577,7 +4586,9 @@
                 return true;
             }
 
-            if (task.isOrganized()) {
+            // TODO(b/165794880): Freeform task organizer doesn't support drag-resize yet. Remove
+            // the special case when it does.
+            if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
                 return true;
             }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index eb5ab83..3bb72b2 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -306,7 +306,10 @@
         boolean useSurfaceCrop = false;
         final Task task = w.getTask();
         if (task != null) {
-            if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+            // TODO(b/165794636): Remove the special case for freeform window once drag resizing is
+            // handled by WM shell.
+            if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
+                        && !task.inFreeformWindowingMode()) {
                 // If the window is in a TaskManaged by a TaskOrganizer then most cropping will
                 // be applied using the SurfaceControl hierarchy from the Organizer. This means
                 // we need to make sure that these changes in crop are reflected in the input
@@ -538,7 +541,8 @@
             if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
                 if (recentsAnimationController.updateInputConsumerForApp(
                         mRecentsAnimationInputConsumer.mWindowHandle)) {
-                    mRecentsAnimationInputConsumer.show(mInputTransaction, w.mActivityRecord);
+                    mRecentsAnimationInputConsumer.show(mInputTransaction,
+                            recentsAnimationController.getHighestLayerTask());
                     mAddRecentsAnimationInputConsumerHandle = false;
                 }
             }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 895a82b..53af563 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -30,10 +30,6 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
 
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.StatusBarManager;
@@ -222,7 +218,7 @@
     InsetsState getInsetsForWindow(WindowState target) {
         final InsetsState originalState = mStateController.getInsetsForWindow(target);
         final InsetsState state = adjustVisibilityForTransientTypes(originalState);
-        return adjustVisibilityForIme(target, state, state == originalState);
+        return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
     }
 
     /**
@@ -252,38 +248,16 @@
         return state;
     }
 
-    private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
+    // Navigation bar insets is always visible to IME.
+    private static InsetsState adjustVisibilityForIme(InsetsState originalState,
             boolean copyState) {
-        if (w.mIsImWindow) {
-            // Navigation bar insets is always visible to IME.
-            final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
-            if (originalNavSource != null && !originalNavSource.isVisible()) {
-                final InsetsState state = copyState ? new InsetsState(originalState)
-                        : originalState;
-                final InsetsSource navSource = new InsetsSource(originalNavSource);
-                navSource.setVisible(true);
-                state.addSource(navSource);
-                return state;
-            }
-        } else if (w.mActivityRecord != null && !w.mActivityRecord.mLastImeShown) {
-            // During switching tasks with gestural navigation, if the IME is attached to
-            // one app window on that time, even the next app window is behind the IME window,
-            // conceptually the window should not receive the IME insets if the next window is
-            // not eligible IME requester and ready to show IME on top of it.
-            final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
-            final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
-
-            if (originalImeSource != null && shouldImeAttachedToApp
-                    && (w.isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS)
-                            || !w.getRequestedVisibility(ITYPE_IME))) {
-                final InsetsState state = copyState ? new InsetsState(originalState)
-                        : originalState;
-
-                final InsetsSource imeSource = new InsetsSource(originalImeSource);
-                imeSource.setVisible(false);
-                state.addSource(imeSource);
-                return state;
-            }
+        final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+        if (originalNavSource != null && !originalNavSource.isVisible()) {
+            final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+            final InsetsSource navSource = new InsetsSource(originalNavSource);
+            navSource.setVisible(true);
+            state.addSource(navSource);
+            return state;
         }
         return originalState;
     }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 750de3b..d67d5fa 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -386,7 +386,9 @@
                 // can be committed before KEYGUARD_OCCLUDE transition is handled.
                 // Set mRequestForceTransition flag to make sure that the app transition animation
                 // is applied for such case.
-                if (topActivity != null) {
+                // TODO(b/194243906): Fix this before enabling the remote keyguard animation.
+                if (WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
+                        && topActivity != null) {
                     topActivity.mRequestForceTransition = true;
                 }
                 updateKeyguardSleepToken(DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4f93c7a..c457df9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -1102,6 +1102,23 @@
         return mTargetActivityRecord.findMainWindow();
     }
 
+    /**
+     * Returns the task with the highest layer, or null if none is found.
+     */
+    public Task getHighestLayerTask() {
+        int highestLayer = Integer.MIN_VALUE;
+        Task highestLayerTask = null;
+        for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+            TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+            int layer = adapter.mTask.getPrefixOrderIndex();
+            if (layer > highestLayer) {
+                highestLayer = layer;
+                highestLayerTask = adapter.mTask;
+            }
+        }
+        return highestLayerTask;
+    }
+
     boolean isAnimatingTask(Task task) {
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             if (task == mPendingAnimations.get(i).mTask) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 69ad59a..fec7ede 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3252,7 +3252,7 @@
             boolean consumed = false;
             if (traverseTopToBottom) {
                 for (int i = task.mChildren.size() - 1; i >= 0; --i) {
-                    final WindowContainer child = mChildren.get(i);
+                    final WindowContainer child = task.mChildren.get(i);
                     if (child.asTaskFragment() != null) {
                         child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                     } else if (child.asActivityRecord() != null && !consumed) {
@@ -3262,7 +3262,7 @@
                 }
             } else {
                 for (int i = 0; i < task.mChildren.size(); i++) {
-                    final WindowContainer child = mChildren.get(i);
+                    final WindowContainer child = task.mChildren.get(i);
                     if (child.asTaskFragment() != null) {
                         child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                     } else if (child.asActivityRecord() != null && !consumed) {
@@ -4174,8 +4174,7 @@
     }
 
     private boolean canBeOrganized() {
-        if (mForceNotOrganized || !mAtmService.mTaskOrganizerController
-                .isSupportedWindowingMode(getWindowingMode())) {
+        if (mForceNotOrganized) {
             return false;
         }
         // All root tasks can be organized
@@ -4332,7 +4331,7 @@
 
         final int windowingMode = getWindowingMode();
         final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
-        final ITaskOrganizer organizer = controller.getTaskOrganizer(windowingMode);
+        final ITaskOrganizer organizer = controller.getTaskOrganizer();
         if (!forceUpdate && mTaskOrganizer == organizer) {
             return false;
         }
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 8a7688f..5d679cf 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1398,6 +1398,8 @@
 
             } else {
                 prev.schedulePauseTimeout();
+                // Unset readiness since we now need to wait until this pause is complete.
+                mAtmService.getTransitionController().setReady(this, false /* ready */);
                 return true;
             }
 
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 99f31ad..b17a939 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -16,9 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
@@ -67,14 +64,6 @@
 class TaskOrganizerController extends ITaskOrganizerController.Stub {
     private static final String TAG = "TaskOrganizerController";
 
-    // The set of modes that are currently supports
-    // TODO: Remove once the task organizer can support all modes
-    @VisibleForTesting
-    static final int[] UNSUPPORTED_WINDOWING_MODES = {
-            WINDOWING_MODE_UNDEFINED,
-            WINDOWING_MODE_FREEFORM
-    };
-
     private class DeathRecipient implements IBinder.DeathRecipient {
         ITaskOrganizer mTaskOrganizer;
 
@@ -373,11 +362,6 @@
 
                 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
                 mService.mRootWindowContainer.forAllTasks((task) -> {
-                    if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES,
-                            task.getWindowingMode())) {
-                        return;
-                    }
-
                     boolean returnTask = !task.mCreatedByOrganizer;
                     task.updateTaskOrganizerState(true /* forceUpdate */,
                             returnTask /* skipTaskAppeared */);
@@ -433,14 +417,8 @@
     /**
      * @return the task organizer key for a given windowing mode.
      */
-    ITaskOrganizer getTaskOrganizer(int windowingMode) {
-        return isSupportedWindowingMode(windowingMode)
-                ? mTaskOrganizers.peekLast()
-                : null;
-    }
-
-    boolean isSupportedWindowingMode(int winMode) {
-        return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode);
+    ITaskOrganizer getTaskOrganizer() {
+        return mTaskOrganizers.peekLast();
     }
 
     // Capture the animation surface control for activity's main window
@@ -993,9 +971,6 @@
             for (int k = 0; k < tasks.size(); k++) {
                 final Task task = tasks.get(k);
                 final int mode = task.getWindowingMode();
-                if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, mode)) {
-                    continue;
-                }
                 pw.println(innerPrefix + "    ("
                         + WindowConfiguration.windowingModeToString(mode) + ") " + task);
             }
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 6bfa611..da16de7 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -20,6 +20,8 @@
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
@@ -36,6 +38,7 @@
 import static android.view.WindowManager.TransitionFlags;
 import static android.view.WindowManager.TransitionType;
 import static android.view.WindowManager.transitTypeToString;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
 import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -657,7 +660,7 @@
         ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>();
         for (int i = mParticipants.size() - 1; i >= 0; --i) {
             ActivityRecord r = mParticipants.valueAt(i).asActivityRecord();
-            if (r == null) continue;
+            if (r == null || !r.mVisibleRequested) continue;
             // At this point, r is "ready", but if it's not "ALL ready" then it is probably only
             // ready due to starting-window.
             reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData
@@ -1066,6 +1069,7 @@
                 final ActivityManager.RunningTaskInfo tinfo = new ActivityManager.RunningTaskInfo();
                 task.fillTaskInfo(tinfo);
                 change.setTaskInfo(tinfo);
+                change.setRotationAnimation(getTaskRotationAnimation(task));
             }
             out.addChange(change);
         }
@@ -1073,6 +1077,23 @@
         return out;
     }
 
+    private static int getTaskRotationAnimation(@NonNull Task task) {
+        final ActivityRecord top = task.getTopVisibleActivity();
+        if (top == null) return ROTATION_ANIMATION_UNSPECIFIED;
+        final WindowState mainWin = top.findMainWindow(false);
+        if (mainWin == null) return ROTATION_ANIMATION_UNSPECIFIED;
+        int anim = mainWin.getRotationAnimationHint();
+        if (anim >= 0) return anim;
+        anim = mainWin.getAttrs().rotationAnimation;
+        if (anim != ROTATION_ANIMATION_SEAMLESS) return anim;
+        if (mainWin != task.mDisplayContent.getDisplayPolicy().getTopFullscreenOpaqueWindow()
+                || !top.matchParentBounds()) {
+            // At the moment, we only support seamless rotation if there is only one window showing.
+            return ROTATION_ANIMATION_UNSPECIFIED;
+        }
+        return mainWin.getAttrs().rotationAnimation;
+    }
+
     boolean getLegacyIsReady() {
         return mState == STATE_STARTED && mSyncId >= 0 && mSyncEngine.isReady(mSyncId);
     }
@@ -1166,6 +1187,9 @@
             final DisplayContent dc = wc.asDisplayContent();
             if (dc != null) {
                 flags |= FLAG_IS_DISPLAY;
+                if (dc.hasAlertWindowSurfaces()) {
+                    flags |= FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+                }
             }
             if (isWallpaper(wc)) {
                 flags |= FLAG_IS_WALLPAPER;
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index ab4f1f6..8c93377 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -157,12 +157,12 @@
         "android.hardware.input.classifier@1.0",
         "android.hardware.ir@1.0",
         "android.hardware.light@2.0",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
         "android.hardware.power-V2-cpp",
         "android.hardware.power.stats@1.0",
-        "android.hardware.power.stats-V1-ndk_platform",
+        "android.hardware.power.stats-V1-ndk",
         "android.hardware.thermal@1.0",
         "android.hardware.tv.input@1.0",
         "android.hardware.vibrator-V2-cpp",
@@ -175,7 +175,7 @@
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
         "android.frameworks.stats@1.0",
-        "android.frameworks.stats-V1-ndk_platform",
+        "android.frameworks.stats-V1-ndk",
         "android.system.suspend.control-V1-cpp",
         "android.system.suspend.control.internal-cpp",
         "android.system.suspend@1.0",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index be8b21c..f641d21 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -648,7 +648,6 @@
 
     private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
     private final DeviceStateCacheImpl mStateCache = new DeviceStateCacheImpl();
-    private EnterpriseSpecificIdCalculator mEsidCalculator;
 
     /**
      * Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@@ -1474,10 +1473,6 @@
             return new LockPatternUtils(mContext);
         }
 
-        EnterpriseSpecificIdCalculator newEnterpriseSpecificIdCalculator() {
-            return new EnterpriseSpecificIdCalculator(mContext);
-        }
-
         boolean storageManagerIsFileBasedEncryptionEnabled() {
             return StorageManager.isFileEncryptedNativeOnly();
         }
@@ -3126,10 +3121,6 @@
                 factoryResetIfDelayedEarlier();
 
                 ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
-
-                // This is constructed here as EnterpriseSpecificIdCalculator depends on telephony
-                // and wifi service and these services are only fully available at this stage.
-                mEsidCalculator = mInjector.newEnterpriseSpecificIdCalculator();
                 break;
         }
     }
@@ -16927,8 +16918,6 @@
     @Override
     public void setOrganizationIdForUser(
             @NonNull String callerPackage, @NonNull String organizationId, int userId) {
-        Preconditions.checkState(mEsidCalculator != null,
-                "setOrganizationIdForUser can't be called before boot phase completion");
         if (!mHasFeature) {
             return;
         }
@@ -16962,7 +16951,10 @@
                             + "be changed");
             final String dpcPackage = owner.info.getPackageName();
             mInjector.binderWithCleanCallingIdentity(() -> {
-                final String esid = mEsidCalculator.calculateEnterpriseId(dpcPackage,
+                EnterpriseSpecificIdCalculator esidCalculator =
+                        new EnterpriseSpecificIdCalculator(mContext);
+
+                final String esid = esidCalculator.calculateEnterpriseId(dpcPackage,
                         organizationId);
                 owner.mOrganizationId = organizationId;
                 owner.mEnrollmentSpecificId = esid;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
index 29091ce..df7f308 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
@@ -51,19 +51,13 @@
 
     EnterpriseSpecificIdCalculator(Context context) {
         TelephonyManager telephonyService = context.getSystemService(TelephonyManager.class);
-        if (telephonyService != null) {
-            mImei = telephonyService.getImei(0);
-            mMeid = telephonyService.getMeid(0);
-        } else {
-            mImei = "";
-            mMeid = "";
-        }
+        Preconditions.checkState(telephonyService != null, "Unable to access telephony service");
+        mImei = telephonyService.getImei(0);
+        mMeid = telephonyService.getMeid(0);
         mSerialNumber = Build.getSerial();
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
-        String[] macAddresses = null;
-        if (wifiManager != null) {
-            macAddresses = wifiManager.getFactoryMacAddresses();
-        }
+        Preconditions.checkState(wifiManager != null, "Unable to access WiFi service");
+        final String[] macAddresses = wifiManager.getFactoryMacAddresses();
         if (macAddresses == null || macAddresses.length == 0) {
             mMacAddress = "";
         } else {
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 988c02b..1bcc3d1 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -32,6 +32,7 @@
         "androidx.test.runner",
         "junit",
         "kotlin-test",
+        "kotlin-reflect",
         "services.core",
         "servicestests-utils",
         "truth-prebuilt",
diff --git a/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
new file mode 100644
index 0000000..cacfcf0
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "PackageManagerServiceUnitTests"
+    }
+  ]
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
new file mode 100644
index 0000000..a7644ec
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.ConfigurationInfo
+import android.content.pm.FeatureGroupInfo
+import android.content.pm.FeatureInfo
+import android.content.pm.PackageManager
+import android.content.pm.SigningDetails
+import android.content.pm.parsing.ParsingPackage
+import android.content.pm.parsing.component.ParsedActivity
+import android.content.pm.parsing.component.ParsedAttribution
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedInstrumentation
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import android.content.pm.parsing.component.ParsedProcess
+import android.content.pm.parsing.component.ParsedProvider
+import android.content.pm.parsing.component.ParsedService
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.net.Uri
+import android.os.Bundle
+import android.os.Parcelable
+import android.util.ArraySet
+import android.util.SparseArray
+import android.util.SparseIntArray
+import com.android.internal.R
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import java.security.KeyPairGenerator
+import java.security.PublicKey
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
+
+    override val defaultImpl = PackageImpl.forTesting("com.example.test")
+    override val creator = PackageImpl.CREATOR
+
+    override val excludedMethods = listOf(
+        // Internal methods
+        "toAppInfoToString",
+        "toAppInfoWithoutState",
+        "toAppInfoWithoutStateWithoutFlags",
+        "assignDerivedFields",
+        "buildFakeForDeletion",
+        "capPermissionPriorities",
+        "forParsing",
+        "forTesting",
+        "getBaseAppDataCredentialProtectedDirForSystemUser",
+        "getBaseAppDataDeviceProtectedDirForSystemUser",
+        "getBoolean",
+        "setBoolean",
+        "hideAsFinal",
+        "hideAsParsed",
+        "markNotActivitiesAsNotExportedIfSingleUser",
+        "sortActivities",
+        "sortReceivers",
+        "sortServices",
+        "setAllComponentsDirectBootAware",
+        // Tested through setting minor/major manually
+        "setLongVersionCode",
+        "getLongVersionCode",
+        // Tested through constructor
+        "getManifestPackageName",
+        "setManifestPackageName",
+        // Utility methods
+        "getStorageUuid",
+        // Removal not tested, irrelevant for parcelling concerns
+        "removeUsesOptionalLibrary",
+        "clearAdoptPermissions",
+        "clearOriginalPackages",
+        "clearProtectedBroadcasts",
+        "removePermission",
+        "removeUsesLibrary",
+        "removeUsesOptionalNativeLibrary",
+        // Tested manually
+        "getMimeGroups",
+        "getRequestedPermissions",
+        // Tested through asSplit
+        "asSplit",
+        "getSplitNames",
+        "getSplitCodePaths",
+        "getSplitRevisionCodes",
+        "getSplitFlags",
+        "getSplitClassLoaderNames",
+        "getSplitDependencies",
+        "setSplitCodePaths",
+        "setSplitClassLoaderName",
+        "setSplitHasCode",
+    )
+
+    override val baseParams = listOf(
+        AndroidPackage::getAppComponentFactory,
+        AndroidPackage::getAutoRevokePermissions,
+        AndroidPackage::getBackupAgentName,
+        AndroidPackage::getBanner,
+        AndroidPackage::getBaseApkPath,
+        AndroidPackage::getBaseRevisionCode,
+        AndroidPackage::getCategory,
+        AndroidPackage::getClassLoaderName,
+        AndroidPackage::getClassName,
+        AndroidPackage::getCompatibleWidthLimitDp,
+        AndroidPackage::getCompileSdkVersion,
+        AndroidPackage::getCompileSdkVersionCodeName,
+        AndroidPackage::getDataExtractionRules,
+        AndroidPackage::getDescriptionRes,
+        AndroidPackage::getFullBackupContent,
+        AndroidPackage::getGwpAsanMode,
+        AndroidPackage::getIconRes,
+        AndroidPackage::getInstallLocation,
+        AndroidPackage::getLabelRes,
+        AndroidPackage::getLargestWidthLimitDp,
+        AndroidPackage::getLogo,
+        AndroidPackage::getManageSpaceActivityName,
+        AndroidPackage::getMemtagMode,
+        AndroidPackage::getMinSdkVersion,
+        AndroidPackage::getNativeHeapZeroInitialized,
+        AndroidPackage::getNativeLibraryDir,
+        AndroidPackage::getNativeLibraryRootDir,
+        AndroidPackage::getNetworkSecurityConfigRes,
+        AndroidPackage::getNonLocalizedLabel,
+        AndroidPackage::getOverlayCategory,
+        AndroidPackage::getOverlayPriority,
+        AndroidPackage::getOverlayTarget,
+        AndroidPackage::getOverlayTargetName,
+        AndroidPackage::getPackageName,
+        AndroidPackage::getPath,
+        AndroidPackage::getPermission,
+        AndroidPackage::getPrimaryCpuAbi,
+        AndroidPackage::getProcessName,
+        AndroidPackage::getRealPackage,
+        AndroidPackage::getRequiredAccountType,
+        AndroidPackage::getRequiresSmallestWidthDp,
+        AndroidPackage::getResizeableActivity,
+        AndroidPackage::getRestrictedAccountType,
+        AndroidPackage::getRoundIconRes,
+        AndroidPackage::getSeInfo,
+        AndroidPackage::getSeInfoUser,
+        AndroidPackage::getSecondaryCpuAbi,
+        AndroidPackage::getSecondaryNativeLibraryDir,
+        AndroidPackage::getSharedUserId,
+        AndroidPackage::getSharedUserLabel,
+        AndroidPackage::getStaticSharedLibName,
+        AndroidPackage::getStaticSharedLibVersion,
+        AndroidPackage::getTargetSandboxVersion,
+        AndroidPackage::getTargetSdkVersion,
+        AndroidPackage::getTaskAffinity,
+        AndroidPackage::getTheme,
+        AndroidPackage::getUiOptions,
+        AndroidPackage::getUid,
+        AndroidPackage::getVersionName,
+        AndroidPackage::getZygotePreloadName,
+        AndroidPackage::isAllowAudioPlaybackCapture,
+        AndroidPackage::isAllowBackup,
+        AndroidPackage::isAllowClearUserData,
+        AndroidPackage::isAllowClearUserDataOnFailedRestore,
+        AndroidPackage::isAllowNativeHeapPointerTagging,
+        AndroidPackage::isAllowTaskReparenting,
+        AndroidPackage::isBackupInForeground,
+        AndroidPackage::isBaseHardwareAccelerated,
+        AndroidPackage::isCantSaveState,
+        AndroidPackage::isCoreApp,
+        AndroidPackage::isCrossProfile,
+        AndroidPackage::isDebuggable,
+        AndroidPackage::isDefaultToDeviceProtectedStorage,
+        AndroidPackage::isDirectBootAware,
+        AndroidPackage::isEnabled,
+        AndroidPackage::isExternalStorage,
+        AndroidPackage::isExtractNativeLibs,
+        AndroidPackage::isFactoryTest,
+        AndroidPackage::isForceQueryable,
+        AndroidPackage::isFullBackupOnly,
+        AndroidPackage::isGame,
+        AndroidPackage::isHasCode,
+        AndroidPackage::isHasDomainUrls,
+        AndroidPackage::isHasFragileUserData,
+        AndroidPackage::isIsolatedSplitLoading,
+        AndroidPackage::isKillAfterRestore,
+        AndroidPackage::isLargeHeap,
+        AndroidPackage::isMultiArch,
+        AndroidPackage::isNativeLibraryRootRequiresIsa,
+        AndroidPackage::isOdm,
+        AndroidPackage::isOem,
+        AndroidPackage::isOverlay,
+        AndroidPackage::isOverlayIsStatic,
+        AndroidPackage::isPartiallyDirectBootAware,
+        AndroidPackage::isPersistent,
+        AndroidPackage::isPrivileged,
+        AndroidPackage::isProduct,
+        AndroidPackage::isProfileableByShell,
+        AndroidPackage::isRequestLegacyExternalStorage,
+        AndroidPackage::isRequiredForAllUsers,
+        AndroidPackage::isResizeableActivityViaSdkVersion,
+        AndroidPackage::isRestoreAnyVersion,
+        AndroidPackage::isSignedWithPlatformKey,
+        AndroidPackage::isStaticSharedLibrary,
+        AndroidPackage::isStub,
+        AndroidPackage::isSupportsRtl,
+        AndroidPackage::isSystem,
+        AndroidPackage::isSystemExt,
+        AndroidPackage::isTestOnly,
+        AndroidPackage::isUse32BitAbi,
+        AndroidPackage::isUseEmbeddedDex,
+        AndroidPackage::isUsesCleartextTraffic,
+        AndroidPackage::isUsesNonSdkApi,
+        AndroidPackage::isVendor,
+        AndroidPackage::isVisibleToInstantApps,
+        AndroidPackage::isVmSafeMode,
+        AndroidPackage::getMaxAspectRatio,
+        AndroidPackage::getMinAspectRatio,
+        AndroidPackage::hasPreserveLegacyExternalStorage,
+        AndroidPackage::hasRequestForegroundServiceExemption,
+        AndroidPackage::hasRequestRawExternalStorageAccess,
+    )
+
+    override fun extraParams() = listOf(
+        getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
+        getter(AndroidPackage::isProfileable, true),
+        getter(AndroidPackage::getVersionCode, 3),
+        getter(AndroidPackage::getVersionCodeMajor, 9),
+        getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
+        getter(AndroidPackage::isAnyDensity, false, 0),
+        getter(AndroidPackage::isResizeable, false, 0),
+        getter(AndroidPackage::isSupportsSmallScreens, false, 0),
+        getter(AndroidPackage::isSupportsNormalScreens, false, 0),
+        getter(AndroidPackage::isSupportsLargeScreens, false, 0),
+        getter(AndroidPackage::isSupportsExtraLargeScreens, false, 0),
+        adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
+        adder(AndroidPackage::getOriginalPackages, "com.test.original"),
+        adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
+        adder(AndroidPackage::getLibraryNames, "testLibraryName"),
+        adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
+        adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
+        adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
+        adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
+        adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
+        adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
+        adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
+        adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
+        getSetByValue(
+            AndroidPackage::getUsesStaticLibrariesVersions,
+            PackageImpl::addUsesStaticLibraryVersion,
+            (testCounter++).toLong(),
+            transformGet = { it?.singleOrNull() }
+        ),
+        getSetByValue(
+            AndroidPackage::areAttributionsUserVisible,
+            ParsingPackage::setAttributionsAreUserVisible,
+            true
+        ),
+        getSetByValue2(
+            AndroidPackage::getOverlayables,
+            PackageImpl::addOverlayable,
+            "testOverlayableName" to "testActorName",
+            transformGet = { "testOverlayableName" to it["testOverlayableName"] }
+        ),
+        getSetByValue(
+            AndroidPackage::getMetaData,
+            PackageImpl::setMetaData,
+            "testBundleKey" to "testBundleValue",
+            transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+            transformSet = { Bundle().apply { putString(it.first, it.second) } }
+        ),
+        getSetByValue(
+            AndroidPackage::getAttributions,
+            PackageImpl::addAttribution,
+            Triple("testTag", 13, listOf("testInherit")),
+            transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
+            transformSet = { it?.let { ParsedAttribution(it.first, it.second, it.third) } }
+        ),
+        getSetByValue2(
+            AndroidPackage::getKeySetMapping,
+            PackageImpl::addKeySet,
+            "testKeySetName" to testKey(),
+            transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
+        ),
+        getSetByValue(
+            AndroidPackage::getPermissionGroups,
+            PackageImpl::addPermissionGroup,
+            "test.permission.GROUP",
+            transformGet = { it.singleOrNull()?.name },
+            transformSet = { ParsedPermissionGroup().apply { setName(it) } }
+        ),
+        getSetByValue2(
+            AndroidPackage::getPreferredActivityFilters,
+            PackageImpl::addPreferredActivityFilter,
+            "TestClassName" to ParsedIntentInfo().apply {
+                addDataScheme("http")
+                addDataAuthority("test.pm.server.android.com", null)
+            },
+            transformGet = { it.singleOrNull()?.let { it.first to it.second } },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    { it.first },
+                    { it.second.schemesIterator().asSequence().singleOrNull() },
+                    { it.second.authoritiesIterator().asSequence().singleOrNull()?.host },
+                )
+            }
+        ),
+        getSetByValue(
+            AndroidPackage::getQueriesIntents,
+            PackageImpl::addQueriesIntent,
+            Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
+            transformGet = { it.singleOrNull() },
+            compare = { first, second -> first?.filterEquals(second) },
+        ),
+        getSetByValue(
+            AndroidPackage::getRestrictUpdateHash,
+            PackageImpl::setRestrictUpdateHash,
+            byteArrayOf(0, 1, 2, 3, 4),
+            compare = ByteArray::contentEquals
+        ),
+        getSetByValue(
+            AndroidPackage::getSigningDetails,
+            PackageImpl::setSigningDetails,
+            testKey(),
+            transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
+            transformSet = {
+                SigningDetails(
+                    null,
+                    SigningDetails.SignatureSchemeVersion.UNKNOWN,
+                    ArraySet<PublicKey>().apply { add(it) },
+                    null
+                )
+            }
+        ),
+        getSetByValue(
+            AndroidPackage::getUsesStaticLibrariesCertDigests,
+            PackageImpl::addUsesStaticLibraryCertDigests,
+            arrayOf("testCertDigest"),
+            transformGet = { it?.singleOrNull() },
+            compare = Array<String?>?::contentEquals
+        ),
+        getSetByValue(
+            AndroidPackage::getActivities,
+            PackageImpl::addActivity,
+            "TestActivityName",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+        ),
+        getSetByValue(
+            AndroidPackage::getReceivers,
+            PackageImpl::addReceiver,
+            "TestReceiverName",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+        ),
+        getSetByValue(
+            AndroidPackage::getServices,
+            PackageImpl::addService,
+            "TestServiceName",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedService().apply { name = it }.withMimeGroups() }
+        ),
+        getSetByValue(
+            AndroidPackage::getProviders,
+            PackageImpl::addProvider,
+            "TestProviderName",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedProvider().apply { name = it }.withMimeGroups() }
+        ),
+        getSetByValue(
+            AndroidPackage::getInstrumentations,
+            PackageImpl::addInstrumentation,
+            "TestInstrumentationName",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedInstrumentation().apply { name = it } }
+        ),
+        getSetByValue(
+            AndroidPackage::getConfigPreferences,
+            PackageImpl::addConfigPreference,
+            testCounter++,
+            transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
+            transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
+        ),
+        getSetByValue(
+            AndroidPackage::getFeatureGroups,
+            PackageImpl::addFeatureGroup,
+            "test.feature.GROUP",
+            transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
+            transformSet = {
+                FeatureGroupInfo().apply {
+                    features = arrayOf(FeatureInfo().apply { name = it })
+                }
+            }
+        ),
+        getSetByValue(
+            AndroidPackage::getPermissions,
+            PackageImpl::addPermission,
+            "test.PERMISSION",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { ParsedPermission().apply { name = it } }
+        ),
+        getSetByValue(
+            AndroidPackage::getUsesPermissions,
+            PackageImpl::addUsesPermission,
+            "test.USES_PERMISSION",
+            transformGet = {
+                // Need to strip implicit permission, which calls addUsesPermission when added
+                it.filterNot { it.name == "test.implicit.PERMISSION" }
+                    .singleOrNull()?.name.orEmpty()
+            },
+            transformSet = { ParsedUsesPermission(it, 0) }
+        ),
+        getSetByValue(
+            AndroidPackage::getReqFeatures,
+            PackageImpl::addReqFeature,
+            "test.feature.INFO",
+            transformGet = { it.singleOrNull()?.name.orEmpty() },
+            transformSet = { FeatureInfo().apply { name = it } }
+        ),
+        getSetByValue(
+            AndroidPackage::getMinExtensionVersions,
+            PackageImpl::setMinExtensionVersions,
+            SparseIntArray().apply { put(testCounter++, testCounter++) },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    { it.size() },
+                    { it.keyAt(0) },
+                    { it.valueAt(0) },
+                )
+            }
+        ),
+        getSetByValue(
+            AndroidPackage::getProcesses,
+            PackageImpl::setProcesses,
+            mapOf("testProcess" to ParsedProcess().apply { name = "testProcessName" }),
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    { it["testProcess"]?.name },
+                )
+            }
+        ),
+        getSetByValue(
+            AndroidPackage::getProperties,
+            PackageImpl::addProperty,
+            PackageManager.Property(
+                "testPropertyName",
+                "testPropertyValue",
+                "testPropertyClassName",
+                "testPropertyPackageName"
+            ),
+            transformGet = { it["testPropertyName"] },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    PackageManager.Property::getName,
+                    PackageManager.Property::getClassName,
+                    PackageManager.Property::getPackageName,
+                    PackageManager.Property::getString,
+                )
+            }
+        ),
+    )
+
+    override fun initialObject() = PackageImpl.forParsing(
+        "com.example.test",
+        "/test/test/base.apk",
+        "/test/test",
+        mockThrowOnUnmocked {
+            whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
+            whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
+
+            // Return invalid values here so that the getter/setter is tested properly
+            whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
+            whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
+            whenever(
+                getNonConfigurationString(
+                    R.styleable.AndroidManifest_versionName,
+                    0
+                )
+            ) { "" }
+            whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
+            whenever(
+                getNonConfigurationString(
+                    R.styleable.AndroidManifest_compileSdkVersionCodename,
+                    0
+                )
+            ) { "" }
+        },
+        true
+    )
+        .asSplit(
+            arrayOf("testSplitNameZero", "testSplitNameOne"),
+            arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
+            intArrayOf(10, 11),
+            SparseArray<IntArray>().apply {
+                put(0, intArrayOf(-1))
+                put(1, intArrayOf(0))
+            }
+        )
+        .setSplitHasCode(0, true)
+        .setSplitHasCode(1, false)
+        .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
+        .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
+
+    override fun extraAssertions(before: Parcelable, after: Parcelable) {
+        super.extraAssertions(before, after)
+        after as PackageImpl
+        expect.that(after.manifestPackageName).isEqualTo("com.example.test")
+        expect.that(after.isCoreApp).isTrue()
+        expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
+        expect.that(after.longVersionCode).isEqualTo(38654705667)
+        expect.that(after.requestedPermissions)
+            .containsExactlyElementsIn(after.usesPermissions.map { it.name })
+            .inOrder()
+
+        expect.that(after.mimeGroups).containsExactly(
+            "TestActivityName/mimeGroup",
+            "TestReceiverName/mimeGroup",
+            "TestServiceName/mimeGroup",
+            "TestProviderName/mimeGroup"
+        )
+
+        expect.that(after.splitNames).asList()
+            .containsExactly("testSplitNameZero", "testSplitNameOne")
+            .inOrder()
+        expect.that(after.splitCodePaths).asList()
+            .containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
+            .inOrder()
+        expect.that(after.splitRevisionCodes).asList()
+            .containsExactly(10, 11)
+            .inOrder()
+        expect.that(after.splitFlags).asList()
+            .containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
+            .inOrder()
+        expect.that(after.splitClassLoaderNames).asList()
+            .containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
+            .inOrder()
+
+        expect.that(after.splitDependencies).isNotNull()
+        after.splitDependencies?.let {
+            expect.that(it.size()).isEqualTo(2)
+            expect.that(it.get(0)).asList().containsExactly(-1)
+            expect.that(it.get(1)).asList().containsExactly(0)
+        }
+    }
+
+    private fun testKey() = KeyPairGenerator.getInstance("RSA")
+        .generateKeyPair()
+        .public
+
+    private fun <T : ParsedComponent> T.withMimeGroups() = apply {
+        val componentName = name
+        addIntent(ParsedIntentInfo().apply {
+            addMimeGroup("$componentName/mimeGroup")
+        })
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
new file mode 100644
index 0000000..e16a187
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.util.IgnoreableExpect
+import com.google.common.truth.Expect
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import java.util.Objects
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction
+import kotlin.reflect.KFunction1
+import kotlin.reflect.KFunction2
+import kotlin.reflect.KFunction3
+import kotlin.reflect.KVisibility
+import kotlin.reflect.full.allSuperclasses
+import kotlin.reflect.full.createInstance
+import kotlin.reflect.full.isSubclassOf
+import kotlin.reflect.full.memberFunctions
+import kotlin.reflect.full.memberProperties
+import kotlin.reflect.full.staticProperties
+import kotlin.reflect.jvm.jvmErasure
+
+
+@ExperimentalContracts
+abstract class ParcelableComponentTest(
+    private val getterType: KClass<*>,
+    private val setterType: KClass<out Parcelable>
+) {
+
+    companion object {
+        private val DEFAULT_EXCLUDED = listOf(
+            // Java
+            "toString",
+            "equals",
+            "hashCode",
+            // Parcelable
+            "getStability",
+            "describeContents",
+            "writeToParcel",
+            // @DataClass
+            "__metadata"
+        )
+    }
+
+    internal val ignoreableExpect = IgnoreableExpect()
+
+    // Hides internal type
+    @get:Rule
+    val ignoreableAsTestRule: TestRule = ignoreableExpect
+
+    val expect: Expect
+        get() = ignoreableExpect.expect
+
+    protected var testCounter = 1
+
+    protected abstract val defaultImpl: Any
+    protected abstract val creator: Parcelable.Creator<out Parcelable>
+
+    protected open val excludedMethods: Collection<String> = emptyList()
+
+    protected abstract val baseParams: Collection<KFunction1<*, Any?>>
+
+    private val getters = getterType.memberFunctions
+        .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+    private val setters = setterType.memberFunctions
+        .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+    constructor(kClass: KClass<out Parcelable>) : this(kClass, kClass)
+
+    @Before
+    fun checkNoPublicFields() {
+        // Fields are not currently testable, and the idea is to enforce interface access for
+        // immutability purposes, so disallow any public fields from existing.
+        expect.that(getterType.memberProperties.filter { it.visibility == KVisibility.PUBLIC }
+            .filterNot { DEFAULT_EXCLUDED.contains(it.name) })
+            .isEmpty()
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    private fun <ObjectType, ReturnType> buildParams(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+    ): Param? {
+        return buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(
+            getFunction,
+            autoValue(getFunction) as ReturnType ?: return null
+        )
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    private fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> buildParams(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        value: SetType,
+    ): Param? {
+        return getSetByValue<ObjectType, ReturnType, SetType, Any?>(
+            getFunction,
+            findSetFunction(getFunction) ?: return null,
+            value
+        )
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    private fun <ObjectType, ReturnType> findSetFunction(
+        getFunction: KFunction1<ObjectType, ReturnType>
+    ): KFunction2<ObjectType, ReturnType, Any?>? {
+        val getFunctionName = getFunction.name
+        val prefix = when {
+            getFunctionName.startsWith("get") -> "get"
+            getFunctionName.startsWith("is") -> "is"
+            getFunctionName.startsWith("has") -> "has"
+            else -> throw IllegalArgumentException("Unsupported method name $getFunctionName")
+        }
+        val setFunctionName = "set" + getFunctionName.removePrefix(prefix)
+        val setFunction = setters.filter { it.name == setFunctionName }
+            .minByOrNull { it.parameters.size }
+
+        if (setFunction == null) {
+            expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+                .fail()
+            return null
+        }
+
+        return setFunction as KFunction2<ObjectType, ReturnType, Any?>
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    private fun <ObjectType, ReturnType, SetType> findAddFunction(
+        getFunction: KFunction1<ObjectType, ReturnType>
+    ): KFunction2<ObjectType, SetType, Any?>? {
+        val getFunctionName = getFunction.name
+        if (!getFunctionName.startsWith("get")) {
+            throw IllegalArgumentException("Unsupported method name $getFunctionName")
+        }
+
+        val setFunctionName = "add" + getFunctionName.removePrefix("get").run {
+            // Remove plurality
+            when {
+                endsWith("ies") -> "${removeSuffix("ies")}y"
+                endsWith("s") -> removeSuffix("s")
+                else -> this
+            }
+        }
+
+        val setFunction = setters.filter { it.name == setFunctionName }
+            .minByOrNull { it.parameters.size }
+
+        if (setFunction == null) {
+            expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+                .fail()
+            return null
+        }
+
+        return setFunction as KFunction2<ObjectType, SetType, Any?>
+    }
+
+    protected fun <ObjectType, ReturnType> getter(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        valueToSet: ReturnType
+    ) = buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(getFunction, valueToSet)
+
+    protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getter(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        expectedValue: CompareType,
+        valueToSet: SetType
+    ): Param? {
+        return getSetByValue(
+            getFunction,
+            findSetFunction(getFunction) ?: return null,
+            value = expectedValue,
+            transformSet = { valueToSet }
+        )
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    protected fun <ObjectType, ReturnType> adder(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        value: ReturnType,
+    ): Param? {
+        return getSetByValue(
+            getFunction,
+            findAddFunction<ObjectType, Any?, ReturnType>(getFunction) ?: return null,
+            value,
+            transformGet = {
+                // Primitive arrays don't implement Iterable, so cast manually
+                when (it) {
+                    is BooleanArray -> it.singleOrNull()
+                    is IntArray -> it.singleOrNull()
+                    is LongArray -> it.singleOrNull()
+                    is Iterable<*> -> it.singleOrNull()
+                    else -> null
+                }
+            },
+        )
+    }
+
+    /**
+     * Method to provide custom getter and setter logic for values which are not simple primitives
+     * or cannot be directly compared using [Objects.equals].
+     *
+     * @param getFunction the getter function which will be called and marked as tested
+     * @param setFunction the setter function which will be called and marked as tested
+     * @param value the value for comparison through the parcel-unparcel cycle, which can be
+     *          anything, like the [String] ID of an inner object
+     * @param transformGet the function to transform the result of [getFunction] into [value]
+     * @param transformSet the function to transform [value] into an input for [setFunction]
+     * @param compare the function that compares the pre/post-parcel [value] objects
+     */
+    @Suppress("UNCHECKED_CAST")
+    protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getSetByValue(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        setFunction: KFunction2<ObjectType, SetType, Any?>,
+        value: CompareType,
+        transformGet: (ReturnType) -> CompareType = { it as CompareType },
+        transformSet: (CompareType) -> SetType = { it as SetType },
+        compare: (CompareType, CompareType) -> Boolean? = Objects::equals
+    ) = Param(
+        getFunction.name,
+        { transformGet(getFunction.call(it as ObjectType)) },
+        setFunction.name,
+        { setFunction.call(it.first() as ObjectType, transformSet(it[1] as CompareType)) },
+        { value },
+        { first, second -> compare(first as CompareType, second as CompareType) == true }
+    )
+
+    /**
+     * Variant of [getSetByValue] that allows specifying a [setFunction] with 2 inputs.
+     */
+    @Suppress("UNCHECKED_CAST")
+    protected fun <ObjectType, ReturnType, SetType1 : Any?, SetType2 : Any?, CompareType : Any?>
+            getSetByValue2(
+        getFunction: KFunction1<ObjectType, ReturnType>,
+        setFunction: KFunction3<ObjectType, SetType1, SetType2, Any>,
+        value: CompareType,
+        transformGet: (ReturnType) -> CompareType = { it as CompareType },
+        transformSet: (CompareType) -> Pair<SetType1, SetType2> =
+            { it as Pair<SetType1, SetType2> },
+        compare: (CompareType, CompareType) -> Boolean = Objects::equals
+    ) = Param(
+        getFunction.name,
+        { transformGet(getFunction.call(it as ObjectType)) },
+        setFunction.name,
+        {
+            val pair = transformSet(it[1] as CompareType)
+            setFunction.call(it.first() as ObjectType, pair.first, pair.second)
+        },
+        { value },
+        { first, second -> compare(first as CompareType, second as CompareType) }
+    )
+
+    protected fun autoValue(getFunction: KFunction<*>) = when (getFunction.returnType.jvmErasure) {
+        Boolean::class -> (getFunction.call(defaultImpl) as Boolean?)?.not() ?: true
+        CharSequence::class,
+        String::class -> getFunction.name + "TEST"
+        Int::class -> testCounter++
+        Long::class -> (testCounter++).toLong()
+        Float::class -> (testCounter++).toFloat()
+        else -> {
+            expect.withMessage("${getFunction.name} needs to provide value").fail()
+            null
+        }
+    }
+
+    /**
+     * Verifies two instances are equivalent via a series of properties. For use when a public API
+     * class has not implemented equals.
+     */
+    @Suppress("UNCHECKED_CAST")
+    protected fun <T : Any> equalBy(
+        first: T?,
+        second: T?,
+        vararg properties: (T) -> Any?
+    ) = properties.all { property ->
+        first?.let { property(it) } == second?.let { property(it) }
+    }
+
+    @Test
+    fun valueComparison() {
+        val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull()
+        val before = initialObject()
+
+        params.forEach { it.setFunction(arrayOf(before, it.value())) }
+
+        val parcel = Parcel.obtain()
+        writeToParcel(parcel, before)
+
+        val dataSize = parcel.dataSize()
+
+        parcel.setDataPosition(0)
+
+        val after = creator.createFromParcel(parcel)
+
+        expect.withMessage("Mismatched write and read data sizes")
+            .that(parcel.dataPosition())
+            .isEqualTo(dataSize)
+
+        parcel.recycle()
+
+        runAssertions(params, before, after)
+    }
+
+    @Test
+    open fun parcellingSize() {
+        val parcelOne = Parcel.obtain()
+        writeToParcel(parcelOne, initialObject())
+
+        val parcelTwo = Parcel.obtain()
+        initialObject().writeToParcel(parcelTwo, 0)
+
+        val superDataSizes = setterType.allSuperclasses
+            .filter { it.isSubclassOf(Parcelable::class) }
+            .mapNotNull { it.memberFunctions.find { it.name == "writeToParcel" } }
+            .filter { it.isFinal }
+            .map {
+                val parcel = Parcel.obtain()
+                initialObject().writeToParcel(parcel, 0)
+                parcel.dataSize().also { parcel.recycle() }
+            }
+
+        if ((superDataSizes + parcelOne.dataSize() + parcelTwo.dataSize()).distinct().size != 1) {
+            listOf(getterType, setterType).distinct().forEach {
+                val creatorProperties = it.staticProperties.filter { it.name == "CREATOR" }
+                if (creatorProperties.size > 1) {
+                    expect.withMessage(
+                        "Multiple matching CREATOR fields found for" +
+                                it.qualifiedName
+                    )
+                        .that(creatorProperties)
+                        .hasSize(1)
+                } else {
+                    val creator = creatorProperties.single().get()
+                    if (creator !is Parcelable.Creator<*>) {
+                        expect.that(creator).isInstanceOf(Parcelable.Creator::class.java)
+                        return
+                    }
+
+                    parcelTwo.setDataPosition(0)
+                    val parcelable = creator.createFromParcel(parcelTwo)
+                    if (parcelable::class.isSubclassOf(setterType)) {
+                        expect.withMessage(
+                            "${it.qualifiedName} which does not safely override writeToParcel " +
+                                    "cannot contain a subclass CREATOR field"
+                        )
+                            .fail()
+                    }
+                }
+            }
+        }
+
+        parcelOne.recycle()
+        parcelTwo.recycle()
+    }
+
+    private fun runAssertions(params: List<Param>, before: Parcelable, after: Parcelable) {
+        params.forEach {
+            val actual = it.getFunction(after)
+            val expected = it.value()
+            val equal = it.compare(actual, expected)
+            expect.withMessage("${it.getFunctionName} was $actual, expected $expected")
+                .that(equal)
+                .isTrue()
+        }
+
+        extraAssertions(before, after)
+
+        // TODO: Handle method overloads?
+        val expectedFunctions = (getters.map { it.name }
+                + setters.map { it.name }
+                - excludedMethods)
+            .distinct()
+
+        val allTestedFunctions = params.flatMap {
+            listOfNotNull(it.getFunctionName, it.setFunctionName)
+        }
+        expect.that(allTestedFunctions).containsExactlyElementsIn(expectedFunctions)
+    }
+
+    open fun extraParams(): Collection<Param?> = emptyList()
+
+    open fun initialObject(): Parcelable = setterType.createInstance()
+
+    open fun extraAssertions(before: Parcelable, after: Parcelable) {}
+
+    open fun writeToParcel(parcel: Parcel, value: Parcelable) = value.writeToParcel(parcel, 0)
+
+    data class Param(
+        val getFunctionName: String,
+        val getFunction: (Any?) -> Any?,
+        val setFunctionName: String?,
+        val setFunction: (Array<Any?>) -> Unit,
+        val value: () -> Any?,
+        val compare: (Any?, Any?) -> Boolean = Objects::equals
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
new file mode 100644
index 0000000..d506190
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import org.junit.Test
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Verifies the failing side of [ParcelableCreatorValidTest]. The sole difference is the addition
+ * of [TestSubWithCreator.CREATOR].
+ */
+@ExperimentalContracts
+class ParcelableCreatorInvalidTest :
+    ParcelableComponentTest(TestSuperClass::class, TestSubWithCreator::class) {
+
+    override val defaultImpl = TestSubWithCreator()
+
+    override val creator = object : Parcelable.Creator<Parcelable> {
+        override fun createFromParcel(source: Parcel) = TestSubWithCreator(source)
+        override fun newArray(size: Int) = Array<TestSubWithCreator?>(size) { null }
+    }
+
+    override val excludedMethods = listOf("writeSubToParcel")
+
+    override val baseParams = listOf(TestSuperClass::getSuperString)
+
+    override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+        (value as TestSubWithCreator).writeSubToParcel(parcel, 0)
+    }
+
+    @Test
+    override fun parcellingSize() {
+        super.parcellingSize()
+        if (expect.hasFailures()) {
+            // This is a hack to ignore an expected failure result. Doing it this way, rather than
+            // adding a switch in the test itself, prevents it from accidentally passing through a
+            // programming error.
+            ignoreableExpect.ignore()
+        }
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
new file mode 100644
index 0000000..f1bc7b5
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithoutCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Tests the [Parcelable] CREATOR verification by using a mock object with known differences to
+ * ensure that the method succeeds/fails.
+ */
+@ExperimentalContracts
+class ParcelableCreatorValidTest :
+    ParcelableComponentTest(TestSuperClass::class, TestSubWithoutCreator::class) {
+
+    override val defaultImpl = TestSubWithoutCreator()
+
+    override val creator = object : Parcelable.Creator<Parcelable> {
+        override fun createFromParcel(source: Parcel) = TestSubWithoutCreator(source)
+        override fun newArray(size: Int) = Array<TestSubWithoutCreator?>(size) { null }
+    }
+
+    override val excludedMethods = listOf("writeSubToParcel")
+
+    override val baseParams = listOf(TestSuperClass::getSuperString)
+
+    override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+        (value as TestSubWithoutCreator).writeSubToParcel(parcel, 0)
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
new file mode 100644
index 0000000..ece600b
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.ActivityInfo
+import android.content.pm.parsing.component.ParsedActivity
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedActivityTest : ParsedMainComponentTest(ParsedActivity::class) {
+
+    override val defaultImpl = ParsedActivity()
+    override val creator = ParsedActivity.CREATOR
+
+    override val mainComponentSubclassBaseParams = listOf(
+        ParsedActivity::getPermission,
+        ParsedActivity::getColorMode,
+        ParsedActivity::getConfigChanges,
+        ParsedActivity::getDocumentLaunchMode,
+        ParsedActivity::getLaunchMode,
+        ParsedActivity::getLockTaskLaunchMode,
+        ParsedActivity::getMaxAspectRatio,
+        ParsedActivity::getMaxRecents,
+        ParsedActivity::getMinAspectRatio,
+        ParsedActivity::getParentActivityName,
+        ParsedActivity::getPersistableMode,
+        ParsedActivity::getPrivateFlags,
+        ParsedActivity::getRequestedVrComponent,
+        ParsedActivity::getResizeMode,
+        ParsedActivity::getRotationAnimation,
+        ParsedActivity::getScreenOrientation,
+        ParsedActivity::getSoftInputMode,
+        ParsedActivity::getTargetActivity,
+        ParsedActivity::getTaskAffinity,
+        ParsedActivity::getTheme,
+        ParsedActivity::getUiOptions,
+        ParsedActivity::isSupportsSizeChanges,
+    )
+
+    override fun mainComponentSubclassExtraParams() = listOf(
+        getSetByValue(
+            ParsedActivity::getWindowLayout,
+            ParsedActivity::setWindowLayout,
+            ActivityInfo.WindowLayout(1, 1f, 2, 1f, 3, 4, 5),
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    ActivityInfo.WindowLayout::width,
+                    ActivityInfo.WindowLayout::widthFraction,
+                    ActivityInfo.WindowLayout::height,
+                    ActivityInfo.WindowLayout::heightFraction,
+                    ActivityInfo.WindowLayout::gravity,
+                    ActivityInfo.WindowLayout::minWidth,
+                    ActivityInfo.WindowLayout::minHeight
+                )
+            }
+        )
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
new file mode 100644
index 0000000..e739dc7
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedAttribution
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedAttributionTest : ParcelableComponentTest(ParsedAttribution::class) {
+
+    override val defaultImpl = ParsedAttribution("", 0, emptyList())
+    override val creator = ParsedAttribution.CREATOR
+
+    override val baseParams = listOf(
+        ParsedAttribution::getTag,
+        ParsedAttribution::getLabel,
+    )
+
+    override fun extraParams() = listOf(
+        getter(ParsedAttribution::getInheritFrom, listOf("testInheritFrom"))
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
new file mode 100644
index 0000000..0a22f6d
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.PackageManager
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Bundle
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedComponentTest(kClass: KClass<out Parcelable>) :
+    ParcelableComponentTest(kClass) {
+
+    final override val excludedMethods
+        get() = subclassExcludedMethods + listOf(
+            // Method aliases/utilities
+            "getClassName",
+            "getComponentName",
+            "setProperties" // Tested though addProperty
+        )
+
+    open val subclassExcludedMethods: Collection<String> = emptyList()
+
+    final override val baseParams
+        get() = subclassBaseParams + listOf(
+            ParsedComponent::getBanner,
+            ParsedComponent::getDescriptionRes,
+            ParsedComponent::getFlags,
+            ParsedComponent::getIcon,
+            ParsedComponent::getLabelRes,
+            ParsedComponent::getLogo,
+            ParsedComponent::getName,
+            ParsedComponent::getNonLocalizedLabel,
+            ParsedComponent::getPackageName,
+        )
+
+    abstract val subclassBaseParams: Collection<KFunction1<*, Any?>>
+
+    final override fun extraParams() = subclassExtraParams() + listOf(
+        getSetByValue(
+            ParsedComponent::getIntents,
+            ParsedComponent::addIntent,
+            "TestLabel",
+            transformGet = { it.singleOrNull()?.nonLocalizedLabel },
+            transformSet = { ParsedIntentInfo().setNonLocalizedLabel(it) },
+        ),
+        getSetByValue(
+            ParsedComponent::getProperties,
+            ParsedComponent::addProperty,
+            PackageManager.Property(
+                "testPropertyName",
+                "testPropertyValue",
+                "testPropertyClassName",
+                "testPropertyPackageName"
+            ),
+            transformGet = { it["testPropertyName"] },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    PackageManager.Property::getName,
+                    PackageManager.Property::getClassName,
+                    PackageManager.Property::getPackageName,
+                    PackageManager.Property::getString,
+                )
+            }
+        ),
+        getSetByValue(
+            ParsedComponent::getMetaData,
+            ParsedComponent::setMetaData,
+            "testBundleKey" to "testBundleValue",
+            transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+            transformSet = { Bundle().apply { putString(it.first, it.second) } }
+        ),
+    )
+
+    open fun subclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
new file mode 100644
index 0000000..b7a85cc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedInstrumentation
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedInstrumentationTest : ParsedComponentTest(ParsedInstrumentation::class) {
+
+    override val defaultImpl = ParsedInstrumentation()
+    override val creator = ParsedInstrumentation.CREATOR
+
+    override val subclassBaseParams = listOf(
+        ParsedInstrumentation::getTargetPackage,
+        ParsedInstrumentation::getTargetProcesses,
+        ParsedInstrumentation::isFunctionalTest,
+        ParsedInstrumentation::isHandleProfiling,
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
new file mode 100644
index 0000000..e27bdf2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Parcel
+import android.os.Parcelable
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedIntentInfoTest : ParcelableComponentTest(ParsedIntentInfo::class) {
+
+    override val defaultImpl = ParsedIntentInfo()
+
+    override val creator = object : Parcelable.Creator<ParsedIntentInfo> {
+        override fun createFromParcel(source: Parcel) = ParsedIntentInfo(source)
+        override fun newArray(size: Int) = Array<ParsedIntentInfo?>(size) { null }
+    }
+
+    override val excludedMethods = listOf(
+        // Used to parcel
+        "writeIntentInfoToParcel",
+        // All remaining IntentFilter methods, which are out of scope
+        "hasDataPath",
+        "hasDataSchemeSpecificPart",
+        "matchAction",
+        "matchData",
+        "actionsIterator",
+        "addAction",
+        "addCategory",
+        "addDataAuthority",
+        "addDataPath",
+        "addDataScheme",
+        "addDataSchemeSpecificPart",
+        "addDataType",
+        "addDynamicDataType",
+        "addMimeGroup",
+        "asPredicate",
+        "asPredicateWithTypeResolution",
+        "authoritiesIterator",
+        "categoriesIterator",
+        "clearDynamicDataTypes",
+        "countActions",
+        "countCategories",
+        "countDataAuthorities",
+        "countDataPaths",
+        "countDataSchemeSpecificParts",
+        "countDataSchemes",
+        "countDataTypes",
+        "countMimeGroups",
+        "countStaticDataTypes",
+        "dataTypes",
+        "debugCheck",
+        "dump",
+        "dumpDebug",
+        "getAction",
+        "getAutoVerify",
+        "getCategory",
+        "getDataAuthority",
+        "getDataPath",
+        "getDataScheme",
+        "getDataSchemeSpecificPart",
+        "getDataType",
+        "getHosts",
+        "getHostsList",
+        "getMimeGroup",
+        "getOrder",
+        "getPriority",
+        "getVisibilityToInstantApp",
+        "handleAllWebDataURI",
+        "handlesWebUris",
+        "hasAction",
+        "hasCategory",
+        "hasDataAuthority",
+        "hasDataScheme",
+        "hasDataType",
+        "hasExactDataType",
+        "hasExactDynamicDataType",
+        "hasExactStaticDataType",
+        "hasMimeGroup",
+        "isExplicitlyVisibleToInstantApp",
+        "isImplicitlyVisibleToInstantApp",
+        "isVerified",
+        "isVisibleToInstantApp",
+        "match",
+        "matchCategories",
+        "matchDataAuthority",
+        "mimeGroupsIterator",
+        "needsVerification",
+        "pathsIterator",
+        "readFromXml",
+        "schemeSpecificPartsIterator",
+        "schemesIterator",
+        "setAutoVerify",
+        "setOrder",
+        "setPriority",
+        "setVerified",
+        "setVisibilityToInstantApp",
+        "typesIterator",
+        "writeToXml",
+    )
+
+    override val baseParams = listOf(
+        ParsedIntentInfo::getIcon,
+        ParsedIntentInfo::getLabelRes,
+        ParsedIntentInfo::isHasDefault,
+        ParsedIntentInfo::getNonLocalizedLabel,
+    )
+
+    override fun initialObject() = ParsedIntentInfo().apply {
+        addAction("test.ACTION")
+        addDataAuthority("testAuthority", "404")
+        addCategory("test.CATEGORY")
+        addMimeGroup("testMime")
+        addDataPath("testPath", PatternMatcher.PATTERN_LITERAL)
+    }
+
+    override fun extraAssertions(before: Parcelable, after: Parcelable) {
+        super.extraAssertions(before, after)
+        after as ParsedIntentInfo
+        expect.that(after.actionsIterator().asSequence().singleOrNull())
+            .isEqualTo("test.ACTION")
+
+        val authority = after.authoritiesIterator().asSequence().singleOrNull()
+        expect.that(authority?.host).isEqualTo("testAuthority")
+        expect.that(authority?.port).isEqualTo(404)
+
+        expect.that(after.categoriesIterator().asSequence().singleOrNull())
+            .isEqualTo("test.CATEGORY")
+        expect.that(after.mimeGroupsIterator().asSequence().singleOrNull())
+            .isEqualTo("testMime")
+        expect.that(after.hasDataPath("testPath")).isTrue()
+    }
+
+    override fun writeToParcel(parcel: Parcel, value: Parcelable) =
+        ParsedIntentInfo.PARCELER.parcel(value as ParsedIntentInfo, parcel, 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
new file mode 100644
index 0000000..411cb09
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedMainComponent
+import android.content.pm.parsing.component.ParsedService
+import android.os.Parcelable
+import java.util.Arrays
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedMainComponentTest(kClass: KClass<out Parcelable>) :
+    ParsedComponentTest(kClass) {
+
+    final override val subclassBaseParams
+        get() = mainComponentSubclassBaseParams + listOf(
+            ParsedMainComponent::getOrder,
+            ParsedMainComponent::getProcessName,
+            ParsedMainComponent::getSplitName,
+            ParsedMainComponent::isDirectBootAware,
+            ParsedMainComponent::isEnabled,
+            ParsedMainComponent::isExported,
+        )
+
+    abstract val mainComponentSubclassBaseParams: Collection<KFunction1<*, Any?>>
+
+    final override fun subclassExtraParams() = mainComponentSubclassExtraParams() + listOf(
+        getSetByValue(
+            ParsedService::getAttributionTags,
+            ParsedService::setAttributionTags,
+            arrayOf("testAttributionTag"),
+            compare = Arrays::equals
+        ),
+    )
+
+    open fun mainComponentSubclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
new file mode 100644
index 0000000..53c862a
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionGroupTest : ParsedComponentTest(ParsedPermissionGroup::class) {
+
+    override val defaultImpl = ParsedPermissionGroup()
+    override val creator = ParsedPermissionGroup.CREATOR
+
+    override val subclassBaseParams = listOf(
+        ParsedPermissionGroup::getRequestDetailResourceId,
+        ParsedPermissionGroup::getBackgroundRequestDetailResourceId,
+        ParsedPermissionGroup::getBackgroundRequestResourceId,
+        ParsedPermissionGroup::getRequestRes,
+        ParsedPermissionGroup::getPriority,
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
new file mode 100644
index 0000000..bb63e2e2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionTest : ParsedComponentTest(ParsedPermission::class) {
+
+    override val defaultImpl = ParsedPermission()
+    override val creator = ParsedPermission.CREATOR
+
+    override val subclassExcludedMethods = listOf(
+        // Utility methods
+        "isAppOp",
+        "isRuntime",
+        "getProtection",
+        "getProtectionFlags",
+        "calculateFootprint",
+        "setKnownCert", // Tested through setKnownCerts
+    )
+    override val subclassBaseParams = listOf(
+        ParsedPermission::getBackgroundPermission,
+        ParsedPermission::getGroup,
+        ParsedPermission::getRequestRes,
+        ParsedPermission::getProtectionLevel,
+        ParsedPermission::isTree,
+    )
+
+    override fun subclassExtraParams() = listOf(
+        getter(ParsedPermission::getKnownCerts, setOf("testCert")),
+        getSetByValue(
+            ParsedPermission::getParsedPermissionGroup,
+            ParsedPermission::setParsedPermissionGroup,
+            ParsedPermissionGroup().apply { name = "test.permission.group" },
+            compare = { first, second -> equalBy(first, second, ParsedPermissionGroup::getName) }
+        ),
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
new file mode 100644
index 0000000..34f46f2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedProcess
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProcessTest : ParcelableComponentTest(ParsedProcess::class) {
+
+    override val defaultImpl = ParsedProcess()
+    override val creator = ParsedProcess.CREATOR
+
+    override val excludedMethods = listOf(
+        // Copying method
+        "addStateFrom",
+    )
+
+    override val baseParams = listOf(
+        ParsedProcess::getName,
+        ParsedProcess::getGwpAsanMode,
+        ParsedProcess::getMemtagMode,
+        ParsedProcess::getNativeHeapZeroInitialized,
+    )
+
+    override fun extraParams() = listOf(
+        getter(ParsedProcess::getDeniedPermissions, setOf("testDeniedPermission"))
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
new file mode 100644
index 0000000..e6d5c0f
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.PathPermission
+import android.content.pm.parsing.component.ParsedProvider
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProviderTest : ParsedMainComponentTest(ParsedProvider::class) {
+
+    override val defaultImpl = ParsedProvider()
+    override val creator = ParsedProvider.CREATOR
+
+    override val mainComponentSubclassBaseParams = listOf(
+        ParsedProvider::getAuthority,
+        ParsedProvider::isSyncable,
+        ParsedProvider::getReadPermission,
+        ParsedProvider::getWritePermission,
+        ParsedProvider::isGrantUriPermissions,
+        ParsedProvider::isForceUriPermissions,
+        ParsedProvider::isMultiProcess,
+        ParsedProvider::getInitOrder,
+    )
+
+    override fun mainComponentSubclassExtraParams() = listOf(
+        getSetByValue(
+            ParsedProvider::getUriPermissionPatterns,
+            ParsedProvider::setUriPermissionPatterns,
+            PatternMatcher("testPattern", PatternMatcher.PATTERN_LITERAL),
+            transformGet = { it?.singleOrNull() },
+            transformSet = { arrayOf(it) },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    PatternMatcher::getPath,
+                    PatternMatcher::getType
+                )
+            }
+        ),
+        getSetByValue(
+            ParsedProvider::getPathPermissions,
+            ParsedProvider::setPathPermissions,
+            PathPermission(
+                "testPermissionPattern",
+                PatternMatcher.PATTERN_LITERAL,
+                "test.READ_PERMISSION",
+                "test.WRITE_PERMISSION"
+            ),
+            transformGet = { it?.singleOrNull() },
+            transformSet = { arrayOf(it) },
+            compare = { first, second ->
+                equalBy(
+                    first, second,
+                    PatternMatcher::getPath,
+                    PatternMatcher::getType,
+                    PathPermission::getReadPermission,
+                    PathPermission::getWritePermission,
+                )
+            }
+        )
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
new file mode 100644
index 0000000..5530184
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedService
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedServiceTest : ParsedMainComponentTest(ParsedService::class) {
+
+    override val defaultImpl = ParsedService()
+    override val creator = ParsedService.CREATOR
+
+    override val mainComponentSubclassBaseParams = listOf(
+        ParsedService::getForegroundServiceType,
+        ParsedService::getPermission,
+    )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
new file mode 100644
index 0000000..1131c72
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedUsesPermissionTest : ParcelableComponentTest(ParsedUsesPermission::class) {
+
+    override val defaultImpl = ParsedUsesPermission("", 0)
+    override val creator = ParsedUsesPermission.CREATOR
+
+    override val baseParams = listOf(
+        ParsedUsesPermission::getName,
+        ParsedUsesPermission::getUsesPermissionFlags
+    )
+
+    override fun initialObject() = ParsedUsesPermission("", 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
new file mode 100644
index 0000000..581d2b2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithCreator extends TestSuperClass {
+
+    @NonNull
+    public static final Parcelable.Creator<TestSubWithCreator> CREATOR =
+            new Parcelable.Creator<TestSubWithCreator>() {
+                @Override
+                public TestSubWithCreator createFromParcel(Parcel source) {
+                    return new TestSubWithCreator(source);
+                }
+
+                @Override
+                public TestSubWithCreator[] newArray(int size) {
+                    return new TestSubWithCreator[size];
+                }
+            };
+
+    @Nullable
+    private String subString;
+
+    public TestSubWithCreator() {
+    }
+
+    public TestSubWithCreator(@NonNull Parcel in) {
+        super(in);
+        subString = in.readString();
+    }
+
+    public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeString(subString);
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
new file mode 100644
index 0000000..4264a11
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithoutCreator extends TestSuperClass {
+
+    @Nullable
+    private String subString;
+
+    public TestSubWithoutCreator() {
+    }
+
+    public TestSubWithoutCreator(@NonNull Parcel in) {
+        super(in);
+        subString = in.readString();
+    }
+
+    public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeString(subString);
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
new file mode 100644
index 0000000..a009786
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.parsing.parcelling.java;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+@DataClass(genGetters = true, genSetters = true, genBuilder = false, genAidl = false,
+        genParcelable = true, genConstructor = false)
+public class TestSuperClass implements Parcelable {
+
+    @Nullable
+    private String superString;
+
+    public TestSuperClass() {
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public @Nullable String getSuperString() {
+        return superString;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull TestSuperClass setSuperString(@NonNull String value) {
+        superString = value;
+        return this;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (superString != null) flg |= 0x1;
+        dest.writeByte(flg);
+        if (superString != null) dest.writeString(superString);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected TestSuperClass(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        String _superString = (flg & 0x1) == 0 ? null : in.readString();
+
+        this.superString = _superString;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<TestSuperClass> CREATOR
+            = new Parcelable.Creator<TestSuperClass>() {
+        @Override
+        public TestSuperClass[] newArray(int size) {
+            return new TestSuperClass[size];
+        }
+
+        @Override
+        public TestSuperClass createFromParcel(@NonNull android.os.Parcel in) {
+            return new TestSuperClass(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1624381019144L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java",
+            inputSignatures = "private @android.annotation.Nullable java.lang.String superString\nclass TestSuperClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genAidl=false, genParcelable=true, genConstructor=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
new file mode 100644
index 0000000..afb18f5
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.util
+
+import com.google.common.truth.Expect
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * Wrapper for [Expect] which supports ignoring any failures. This should be used with caution, but
+ * it allows a base test to be written which doesn't switch success/failure in the test itself,
+ * preventing any logic errors from causing the test to accidentally succeed.
+ */
+internal class IgnoreableExpect : TestRule {
+
+    val expect = Expect.create()
+
+    private var ignore = false
+
+    override fun apply(base: Statement?, description: Description?): Statement {
+        return object : Statement() {
+            override fun evaluate() {
+                ignore = false
+                try {
+                    expect.apply(base, description).evaluate()
+                } catch (t: Throwable) {
+                    if (!ignore) {
+                        throw t
+                    }
+                }
+            }
+        }
+    }
+
+    fun ignore() {
+        ignore = true
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index a205a1d..1ac28ab 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -1340,11 +1340,19 @@
                 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
         director.start(createMockSensorManager());
 
-        ArgumentCaptor<ProximityActiveListener> captor =
+        ArgumentCaptor<ProximityActiveListener> ProximityCaptor =
                 ArgumentCaptor.forClass(ProximityActiveListener.class);
         verify(mSensorManagerInternalMock).addProximityActiveListener(any(Executor.class),
-                captor.capture());
-        ProximityActiveListener listener = captor.getValue();
+                ProximityCaptor.capture());
+        ProximityActiveListener proximityListener = ProximityCaptor.getValue();
+
+        ArgumentCaptor<DisplayListener> DisplayCaptor =
+                ArgumentCaptor.forClass(DisplayListener.class);
+        verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+                eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+                        | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+                        | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+        DisplayListener displayListener = DisplayCaptor.getValue();
 
         // Verify that there is no proximity vote initially
         Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -1353,13 +1361,38 @@
         when(mDisplayManagerInternalMock.getRefreshRateForDisplayAndSensor(eq(DISPLAY_ID), eq(null),
                   eq(Sensor.STRING_TYPE_PROXIMITY))).thenReturn(new RefreshRateRange(60, 60));
 
+        when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+
         // Set the proximity to active and verify that we added a vote.
-        listener.onProximityActive(true);
+        proximityListener.onProximityActive(true);
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+        assertVoteForRefreshRate(vote, 60.f);
+
+        // Set the display state to doze and verify that the vote is gone
+        when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+        displayListener.onDisplayAdded(DISPLAY_ID);
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+        assertNull(vote);
+
+        // Set the display state to on and verify that we added the vote back.
+        when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+        displayListener.onDisplayChanged(DISPLAY_ID);
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+        assertVoteForRefreshRate(vote, 60.f);
+
+        // Set the display state to doze and verify that the vote is gone
+        when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+        displayListener.onDisplayAdded(DISPLAY_ID);
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+        assertNull(vote);
+
+        // Remove the display to cause the doze state to be removed
+        displayListener.onDisplayRemoved(DISPLAY_ID);
         vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
         assertVoteForRefreshRate(vote, 60.f);
 
         // Turn prox off and verify vote is gone.
-        listener.onProximityActive(false);
+        proximityListener.onProximityActive(false);
         vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
         assertNull(vote);
     }
@@ -1710,6 +1743,11 @@
             return null;
         }
 
+        @Override
+        public boolean isDozeState(Display d) {
+            return false;
+        }
+
         void notifyPeakRefreshRateChanged() {
             if (mPeakRefreshRateObserver != null) {
                 mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
new file mode 100644
index 0000000..00e3bf1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.hdmi.RequestSadAction.RequestSadCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public class RequestSadActionTest {
+
+    private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+    private static final ArrayList<Integer> CODECS_TO_QUERY_1 = new ArrayList<Integer>(
+            Arrays.asList(Constants.AUDIO_CODEC_LPCM, Constants.AUDIO_CODEC_DD,
+                    Constants.AUDIO_CODEC_MPEG1, Constants.AUDIO_CODEC_MP3));
+    private static final ArrayList<Integer> CODECS_TO_QUERY_2 = new ArrayList<Integer>(
+            Arrays.asList(Constants.AUDIO_CODEC_MPEG2, Constants.AUDIO_CODEC_AAC,
+                    Constants.AUDIO_CODEC_DTS, Constants.AUDIO_CODEC_ATRAC));
+    private static final ArrayList<Integer> CODECS_TO_QUERY_3 = new ArrayList<Integer>(
+            Arrays.asList(Constants.AUDIO_CODEC_ONEBITAUDIO, Constants.AUDIO_CODEC_DDP,
+                    Constants.AUDIO_CODEC_DTSHD, Constants.AUDIO_CODEC_TRUEHD));
+    private static final ArrayList<Integer> CODECS_TO_QUERY_4 = new ArrayList<Integer>(
+            Arrays.asList(Constants.AUDIO_CODEC_DST, Constants.AUDIO_CODEC_WMAPRO,
+                    Constants.AUDIO_CODEC_MAX));
+
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecController mHdmiCecController;
+    private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
+    private FakeNativeWrapper mNativeWrapper;
+    private Looper mMyLooper;
+    private TestLooper mTestLooper = new TestLooper();
+    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+    private List<byte[]> mSupportedSads;
+    private RequestSadCallback mCallback =
+            new RequestSadCallback() {
+                @Override
+                public void onRequestSadDone(
+                        List<byte[]> supportedSads) {
+                    mSupportedSads = supportedSads;
+                }
+            };
+    @Mock
+    private IPowerManager mIPowerManagerMock;
+    @Mock
+    private IThermalService mIThermalServiceMock;
+
+    private static byte[] concatenateSads(List<byte[]> sads) {
+        byte[] concatenatedSads = new byte[sads.size() * 3];
+        for (int i = 0; i < sads.size(); i++) {
+            for (int j = 0; j < 3; j++) {
+                concatenatedSads[3 * i + j] = sads.get(i)[j];
+            }
+        }
+        return concatenatedSads;
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        Context context = InstrumentationRegistry.getTargetContext();
+        mMyLooper = mTestLooper.getLooper();
+
+        mHdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext(),
+                        Collections.emptyList()) {
+                    @Override
+                    boolean isControlEnabled() {
+                        return true;
+                    }
+
+                    @Override
+                    void wakeUp() {
+                    }
+
+                    @Override
+                    protected void writeStringSystemProperty(String key, String value) {
+                        // do nothing
+                    }
+
+                    @Override
+                    boolean isPowerStandbyOrTransient() {
+                        return false;
+                    }
+
+                    @Override
+                    protected PowerManager getPowerManager() {
+                        return new PowerManager(context, mIPowerManagerMock,
+                                mIThermalServiceMock, new Handler(mMyLooper));
+                    }
+                };
+
+        mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
+        mHdmiCecLocalDeviceTv.init();
+        mHdmiControlService.setIoLooper(mMyLooper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
+        mNativeWrapper = new FakeNativeWrapper();
+        mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+                mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+        mHdmiControlService.setCecController(mHdmiCecController);
+        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+        mLocalDevices.add(mHdmiCecLocalDeviceTv);
+        mHdmiControlService.initService();
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mNativeWrapper.setPhysicalAddress(0x0000);
+        mTestLooper.dispatchAll();
+        mNativeWrapper.clearResultMessages();
+    }
+
+    @Test
+    public void noResponse_queryAgain_emptyResult() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                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);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(0);
+    }
+
+    @Test
+    public void featureAbort_dontQueryAgain_emptyResult() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+        HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+                Constants.ABORT_INVALID_OPERAND);
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(featureAbort);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(featureAbort);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(featureAbort);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        action.processCommand(featureAbort);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(0);
+    }
+
+    @Test
+    public void allSupported_completeResult() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_1 = new byte[]{
+                0x01, 0x18, 0x4A,
+                0x02, 0x64, 0x5A,
+                0x03, 0x4B, 0x00,
+                0x04, 0x20, 0x0A};
+        HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response1);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_2 = new byte[]{
+                0x05, 0x18, 0x4A,
+                0x06, 0x64, 0x5A,
+                0x07, 0x4B, 0x00,
+                0x08, 0x20, 0x0A};
+        HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response2);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_3 = new byte[]{
+                0x09, 0x18, 0x4A,
+                0x0A, 0x64, 0x5A,
+                0x0B, 0x4B, 0x00,
+                0x0C, 0x20, 0x0A};
+        HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response3);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_4 = new byte[]{
+                0x0D, 0x18, 0x4A,
+                0x0E, 0x64, 0x5A,
+                0x0F, 0x4B, 0x00};
+        HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        action.processCommand(response4);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(15);
+        assertThat(Arrays.equals(sadsToRespond_1,
+                concatenateSads(mSupportedSads.subList(0, 4)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_2,
+                concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_3,
+                concatenateSads(mSupportedSads.subList(8, 12)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_4,
+                concatenateSads(mSupportedSads.subList(12, 15)))).isTrue();
+    }
+
+    @Test
+    public void subsetSupported_subsetResult() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_1 = new byte[]{
+                0x01, 0x18, 0x4A,
+                0x03, 0x4B, 0x00,
+                0x04, 0x20, 0x0A};
+        HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response1);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_2 = new byte[]{
+                0x08, 0x20, 0x0A};
+        HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response2);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_3 = new byte[]{
+                0x09, 0x18, 0x4A,
+                0x0A, 0x64, 0x5A,
+                0x0B, 0x4B, 0x00,
+                0x0C, 0x20, 0x0A};
+        HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response3);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_4 = new byte[]{
+                0x0F, 0x4B, 0x00};
+        HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        action.processCommand(response4);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(9);
+        assertThat(Arrays.equals(sadsToRespond_1,
+                concatenateSads(mSupportedSads.subList(0, 3)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_2,
+                concatenateSads(mSupportedSads.subList(3, 4)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_3,
+                concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+        assertThat(Arrays.equals(sadsToRespond_4,
+                concatenateSads(mSupportedSads.subList(8, 9)))).isTrue();
+    }
+
+    @Test
+    public void invalidCodecs_emptyResults() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_1 = new byte[]{
+                0x20, 0x18, 0x4A,
+                0x21, 0x64, 0x5A,
+                0x22, 0x4B, 0x00,
+                0x23, 0x20, 0x0A};
+        HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response1);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_2 = new byte[]{
+                0x24, 0x18, 0x4A,
+                0x25, 0x64, 0x5A,
+                0x26, 0x4B, 0x00,
+                0x27, 0x20, 0x0A};
+        HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response2);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_3 = new byte[]{
+                0x28, 0x18, 0x4A,
+                0x29, 0x64, 0x5A,
+                0x2A, 0x4B, 0x00,
+                0x2B, 0x20, 0x0A};
+        HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response3);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_4 = new byte[]{
+                0x2C, 0x18, 0x4A,
+                0x2D, 0x64, 0x5A,
+                0x2E, 0x4B, 0x00};
+        HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        action.processCommand(response4);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(0);
+    }
+
+    @Test
+    public void invalidMessageLength_queryAgain() {
+        RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+                mCallback);
+        action.start();
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_1 = new byte[]{
+                0x01, 0x18,
+                0x02, 0x64, 0x5A,
+                0x03, 0x4B, 0x00,
+                0x04, 0x20, 0x0A};
+        HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), 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();
+
+        HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_2 = new byte[]{
+                0x05, 0x18, 0x4A,
+                0x06, 0x64, 0x5A,
+                0x07,
+                0x08, 0x20, 0x0A};
+        HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response2);
+        mTestLooper.dispatchAll();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_3 = new byte[0];
+        HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response3);
+        mTestLooper.dispatchAll();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                Constants.ADDR_AUDIO_SYSTEM,
+                CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+        byte[] sadsToRespond_4 = new byte[]{
+                0x0D, 0x18, 0x4A,
+                0x0E, 0x64, 0x5A,
+                0x0F, 0x4B};
+        HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                Constants.ADDR_AUDIO_SYSTEM,
+                mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        mNativeWrapper.clearResultMessages();
+        action.processCommand(response4);
+        mTestLooper.dispatchAll();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        assertThat(mSupportedSads.size()).isEqualTo(0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 8b8a7e6..2bda120 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -40,6 +40,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -232,6 +233,21 @@
     }
 
     @Test
+    public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any());
+
+        assertThrows(RuntimeException.class,
+                () -> mApexManager.getStagedApexInfos(testParamsWithChildren()));
+    }
+
+    @Test
+    public void testGetStagedApexInfos_returnsEmptyArrayOnError() throws RemoteException {
+        doThrow(ServiceSpecificException.class).when(mApexService).getStagedApexInfos(any());
+
+        assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0);
+    }
+
+    @Test
     public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException {
         doAnswer(invocation -> {
             throw new Exception();
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
index e15b5f5..2f51994 100644
--- a/services/tests/servicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -1,3 +1,7 @@
 include /services/core/java/com/android/server/pm/OWNERS
 
 per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+
+# apex support
+per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index e8c5fb3..38b98ca 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -949,7 +949,7 @@
                 .addConfigPreference(new ConfigurationInfo())
                 .addReqFeature(new FeatureInfo())
                 .addFeatureGroup(new FeatureGroupInfo())
-                .setCompileSdkVersionCodename("foo23")
+                .setCompileSdkVersionCodeName("foo23")
                 .setCompileSdkVersion(100)
                 .setOverlayCategory("foo24")
                 .setOverlayIsStatic(true)
diff --git a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
index 65a9759..4a25323 100644
--- a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
+++ b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
@@ -19,19 +19,31 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.time.Clock;
+import java.time.ZoneOffset;
+
 /** Test that the ledger records transactions correctly. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class LedgerTest {
 
+    @Before
+    public void setUp() {
+        TareUtils.sSystemClock = Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
+    }
+
     @Test
     public void testInitialState() {
         final Ledger ledger = new Ledger();
@@ -72,4 +84,45 @@
         assertEquals(1, ledger.get24HourSum(1, 27 * HOUR_IN_MILLIS));
         assertEquals(0, ledger.get24HourSum(1, 28 * HOUR_IN_MILLIS));
     }
+
+    @Test
+    public void testRemoveOldTransactions() {
+        final Ledger ledger = new Ledger();
+        ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+        assertNull(ledger.getEarliestTransaction());
+
+        final long now = getCurrentTimeMillis();
+        Ledger.Transaction transaction1 = new Ledger.Transaction(
+                now - 48 * HOUR_IN_MILLIS, now - 40 * HOUR_IN_MILLIS, 1, null, 4800);
+        Ledger.Transaction transaction2 = new Ledger.Transaction(
+                now - 24 * HOUR_IN_MILLIS, now - 23 * HOUR_IN_MILLIS, 1, null, 600);
+        Ledger.Transaction transaction3 = new Ledger.Transaction(
+                now - 22 * HOUR_IN_MILLIS, now - 21 * HOUR_IN_MILLIS, 1, null, 600);
+        // Instant event
+        Ledger.Transaction transaction4 = new Ledger.Transaction(
+                now - 20 * HOUR_IN_MILLIS, now - 20 * HOUR_IN_MILLIS, 1, null, 500);
+        // Recent event
+        Ledger.Transaction transaction5 = new Ledger.Transaction(
+                now - 5 * MINUTE_IN_MILLIS, now - MINUTE_IN_MILLIS, 1, null, 400);
+        ledger.recordTransaction(transaction1);
+        ledger.recordTransaction(transaction2);
+        ledger.recordTransaction(transaction3);
+        ledger.recordTransaction(transaction4);
+        ledger.recordTransaction(transaction5);
+
+        assertEquals(transaction1, ledger.getEarliestTransaction());
+        ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+        assertEquals(transaction2, ledger.getEarliestTransaction());
+        ledger.removeOldTransactions(23 * HOUR_IN_MILLIS);
+        assertEquals(transaction3, ledger.getEarliestTransaction());
+        // Shouldn't delete transaction3 yet since there's still a piece of it within the min age
+        // window.
+        ledger.removeOldTransactions(21 * HOUR_IN_MILLIS + 30 * MINUTE_IN_MILLIS);
+        assertEquals(transaction3, ledger.getEarliestTransaction());
+        // Instant event should be removed as soon as we hit the exact threshold.
+        ledger.removeOldTransactions(20 * HOUR_IN_MILLIS);
+        assertEquals(transaction5, ledger.getEarliestTransaction());
+        ledger.removeOldTransactions(0);
+        assertNull(ledger.getEarliestTransaction());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 61b5c2b..4cc4d55 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -83,7 +83,7 @@
 @Presubmit
 public class VibrationThreadTest {
 
-    private static final int TEST_TIMEOUT_MILLIS = 1_000;
+    private static final int TEST_TIMEOUT_MILLIS = 900;
     private static final int UID = Process.ROOT_UID;
     private static final int VIBRATOR_ID = 1;
     private static final String PACKAGE_NAME = "package";
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 41f2246..54406c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1616,6 +1616,21 @@
     }
 
     @Test
+    public void testRemoveImmediatelyWithFinishingActivity() throws RemoteException {
+        final ActivityRecord activity = createActivityWithTask();
+        final WindowProcessController wpc = activity.app;
+        activity.makeFinishingLocked();
+        assertTrue(activity.finishing);
+
+        activity.getTask().removeImmediately("test");
+
+        verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
+                isA(DestroyActivityItem.class));
+        assertFalse(wpc.hasActivities());
+        assertEquals(DESTROYING, activity.getState());
+    }
+
+    @Test
     public void testRemoveFromHistory() {
         final ActivityRecord activity = createActivityWithTask();
         final Task rootTask = activity.getRootTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index aa56183..17288c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -53,9 +53,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
 import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -895,36 +892,6 @@
         assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
     }
 
-    @UseTestDisplay(addWindows = W_INPUT_METHOD)
-    @Test
-    public void testAdjustImeInsetsVisibilityWhenTaskSwitchIsAnimating() {
-        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
-        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
-        controller.getImeSourceProvider().setWindow(mImeWindow, null, null);
-
-        // Simulate app requests IME with updating all windows Insets State when IME is above app.
-        mDisplayContent.setImeLayeringTarget(app);
-        mDisplayContent.setImeInputTarget(app);
-        assertTrue(mDisplayContent.shouldImeAttachedToApp());
-        controller.getImeSourceProvider().scheduleShowImePostLayout(app);
-        controller.getImeSourceProvider().getSource().setVisible(true);
-        controller.updateAboveInsetsState(mImeWindow, false);
-
-        // Simulate task switching animation happens when switching app to app2.
-        spyOn(app);
-        spyOn(app2);
-        doReturn(true).when(app).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
-        doReturn(true).when(app2).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
-        app.mActivityRecord.mLastImeShown = true;
-
-        // Verify the IME insets is visible on app, but not for app2 during task animating.
-        InsetsState stateApp = app.getInsetsState();
-        InsetsState stateApp2 = app2.getInsetsState();
-        assertTrue(stateApp.getSource(ITYPE_IME).isVisible());
-        assertFalse(stateApp2.getSource(ITYPE_IME).isVisible());
-    }
-
     @UseTestDisplay(addWindows = { W_ACTIVITY })
     @Test
     public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 965f126..734172f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -36,6 +36,7 @@
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.media.AudioFormat;
+import android.media.AudioManagerInternal;
 import android.media.permission.Identity;
 import android.media.permission.PermissionUtil;
 import android.os.Binder;
@@ -44,6 +45,7 @@
 import android.os.IRemoteCallback;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SharedMemory;
@@ -275,6 +277,7 @@
             LocalServices.getService(PermissionManagerServiceInternal.class)
                     .setHotwordDetectionServiceProvider(null);
             mIdentity = null;
+            updateServiceUidForAudioPolicy(Process.INVALID_UID);
         }
         mCancellationTaskFuture.cancel(/* may interrupt */ true);
         if (mAudioFlinger != null) {
@@ -893,6 +896,8 @@
         connection.run(service -> service.ping(new IRemoteCallback.Stub() {
             @Override
             public void sendResult(Bundle bundle) throws RemoteException {
+                // TODO: Exit if the service has been unbound already (though there's a very low
+                // chance this happens).
                 if (DEBUG) {
                     Slog.d(TAG, "updating hotword UID " + Binder.getCallingUid());
                 }
@@ -902,10 +907,21 @@
                 LocalServices.getService(PermissionManagerServiceInternal.class)
                         .setHotwordDetectionServiceProvider(() -> uid);
                 mIdentity = new HotwordDetectionServiceIdentity(uid, mVoiceInteractionServiceUid);
+                updateServiceUidForAudioPolicy(uid);
             }
         }));
     }
 
+    private void updateServiceUidForAudioPolicy(int uid) {
+        mScheduledExecutorService.execute(() -> {
+            final AudioManagerInternal audioManager =
+                    LocalServices.getService(AudioManagerInternal.class);
+            if (audioManager != null) {
+                audioManager.setHotwordDetectionServiceUid(uid);
+            }
+        });
+    }
+
     private static void bestEffortClose(Closeable closeable) {
         try {
             closeable.close();
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
new file mode 100644
index 0000000..131611d
--- /dev/null
+++ b/tests/InputMethodStressTest/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "InputMethodStressTest",
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.runner"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.uiautomator_uiautomator",
+        "compatibility-device-util-axt",
+        "platform-test-annotations",
+        "truth-prebuilt",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    sdk_version: "31",
+}
diff --git a/tests/InputMethodStressTest/AndroidManifest.xml b/tests/InputMethodStressTest/AndroidManifest.xml
new file mode 100644
index 0000000..e5d6518
--- /dev/null
+++ b/tests/InputMethodStressTest/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.inputmethod.stresstest">
+
+    <application>
+        <activity android:name=".TestActivity"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+         android:targetPackage="com.android.inputmethod.stresstest">
+    </instrumentation>
+</manifest>
diff --git a/tests/InputMethodStressTest/AndroidTest.xml b/tests/InputMethodStressTest/AndroidTest.xml
new file mode 100644
index 0000000..b194010
--- /dev/null
+++ b/tests/InputMethodStressTest/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="InputMethod integration/regression test">
+    <option name="test-suite-tag" value="apct" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="InputMethodStressTest.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.inputmethod.stresstest" />
+    </test>
+</configuration>
diff --git a/tests/InputMethodStressTest/OWNERS b/tests/InputMethodStressTest/OWNERS
new file mode 100644
index 0000000..6bb4b17
--- /dev/null
+++ b/tests/InputMethodStressTest/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
new file mode 100644
index 0000000..5427fd8
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.stresstest;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.platform.test.annotations.RootPermissionTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+@RootPermissionTest
+@RunWith(AndroidJUnit4.class)
+public class ImeOpenCloseStressTest {
+
+    private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+    private static final int NUM_TEST_ITERATIONS = 100;
+
+    private Instrumentation mInstrumentation;
+
+    @Test
+    public void test() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        Intent intent = new Intent()
+                .setAction(Intent.ACTION_MAIN)
+                .setClass(mInstrumentation.getContext(), TestActivity.class)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        TestActivity activity = (TestActivity) mInstrumentation.startActivitySync(intent);
+        eventually(() -> assertThat(callOnMainSync(activity::hasWindowFocus)).isTrue(), TIMEOUT);
+        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
+            mInstrumentation.runOnMainSync(activity::showIme);
+            eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isTrue(), TIMEOUT);
+            mInstrumentation.runOnMainSync(activity::hideIme);
+            eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isFalse(), TIMEOUT);
+        }
+    }
+
+    private <V> V callOnMainSync(Callable<V> callable) {
+        AtomicReference<V> result = new AtomicReference<>();
+        AtomicReference<Exception> thrownException = new AtomicReference<>();
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                result.set(callable.call());
+            } catch (Exception e) {
+                thrownException.set(e);
+            }
+        });
+        if (thrownException.get() != null) {
+            throw new RuntimeException("Exception thrown from Main thread", thrownException.get());
+        }
+        return result.get();
+    }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
new file mode 100644
index 0000000..7baf037
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.stresstest;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowInsets;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+public class TestActivity extends Activity {
+
+    private EditText mEditText;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        LinearLayout rootView = new LinearLayout(this);
+        rootView.setOrientation(LinearLayout.VERTICAL);
+        mEditText = new EditText(this);
+        rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+        setContentView(rootView);
+    }
+
+    public boolean hasWindowFocus() {
+        return mEditText.hasWindowFocus();
+    }
+
+    public boolean isImeShown() {
+        WindowInsets insets = mEditText.getRootWindowInsets();
+        return insets.isVisible(WindowInsets.Type.ime());
+    }
+
+    public void showIme() {
+        mEditText.requestFocus();
+        InputMethodManager imm = getSystemService(InputMethodManager.class);
+        imm.showSoftInput(mEditText, 0);
+    }
+
+    public void hideIme() {
+        InputMethodManager imm = getSystemService(InputMethodManager.class);
+        imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+    }
+}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 05c46ed..7a668a5 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -54,7 +54,6 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -203,194 +202,6 @@
     }
 
     /**
-     * Test that multiple available rollbacks are properly persisted.
-     */
-    @Test
-    public void testAvailableRollbackPersistence() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            Uninstall.packages(TestApp.B);
-            Install.single(TestApp.B1).commit();
-            Install.single(TestApp.B2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // Both test apps should now be available for rollback.
-            RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A);
-            assertThat(rollbackA).isNotNull();
-            assertThat(rollbackA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
-            assertThat(rollbackB).isNotNull();
-            assertThat(rollbackB).packagesContainsExactly(
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Reload the persisted data.
-            rm.reloadPersistedData();
-
-            // The apps should still be available for rollback.
-            rollbackA = waitForAvailableRollback(TestApp.A);
-            assertThat(rollbackA).isNotNull();
-            assertThat(rollbackA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            rollbackB = waitForAvailableRollback(TestApp.B);
-            assertThat(rollbackB).isNotNull();
-            assertThat(rollbackB).packagesContainsExactly(
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Rollback of B should not rollback A
-            RollbackUtils.rollback(rollbackB.getRollbackId());
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that available multi-package rollbacks are properly persisted.
-     */
-    @Test
-    public void testAvailableMultiPackageRollbackPersistence() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A, TestApp.B);
-            Install.multi(TestApp.A1, TestApp.B1).commit();
-            Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // The app should now be available for rollback.
-            RollbackInfo availableA = waitForAvailableRollback(TestApp.A);
-            assertThat(availableA).isNotNull();
-            assertThat(availableA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            RollbackInfo availableB = waitForAvailableRollback(TestApp.B);
-            assertThat(availableB).isNotNull();
-            assertThat(availableB).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Assert they're both the same rollback
-            assertThat(availableA).hasRollbackId(availableB.getRollbackId());
-
-            // Reload the persisted data.
-            rm.reloadPersistedData();
-
-            // The apps should still be available for rollback.
-            availableA = waitForAvailableRollback(TestApp.A);
-            assertThat(availableA).isNotNull();
-            assertThat(availableA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            availableB = waitForAvailableRollback(TestApp.B);
-            assertThat(availableB).isNotNull();
-            assertThat(availableB).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Rollback of B should rollback A as well
-            RollbackUtils.rollback(availableB.getRollbackId());
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
-            RollbackInfo committedA = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.A);
-            assertThat(committedA).isNotNull();
-            assertThat(committedA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            RollbackInfo committedB = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.A);
-            assertThat(committedB).isNotNull();
-            assertThat(committedB).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Assert they're both the same rollback
-            assertThat(committedA).hasRollbackId(committedB.getRollbackId());
-            assertThat(committedA).hasRollbackId(availableA.getRollbackId());
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that recently committed rollback data is properly persisted.
-     */
-    @Test
-    public void testRecentlyCommittedRollbackPersistence() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            // The app should now be available for rollback.
-            RollbackInfo available = waitForAvailableRollback(TestApp.A);
-            assertThat(available).isNotNull();
-
-            // Roll back the app.
-            TestApp cause = new TestApp("Foo", "com.android.tests.rollback.testapp.Foo",
-                    /*versionCode*/ 42, /*isApex*/ false);
-            RollbackUtils.rollback(available.getRollbackId(), cause);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-            // Verify the recent rollback has been recorded.
-            RollbackInfo committed = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.A);
-            assertThat(committed).isNotNull();
-            assertThat(committed).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-            assertThat(committed).causePackagesContainsExactly(cause);
-
-            // Reload the persisted data.
-            rm.reloadPersistedData();
-
-            // Verify the recent rollback is still recorded.
-            committed = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.A);
-            assertThat(committed).isNotNull();
-            assertThat(committed).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-            assertThat(committed).causePackagesContainsExactly(cause);
-            assertThat(committed).hasRollbackId(available.getRollbackId());
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
      * Test the scheduling aspect of rollback expiration.
      */
     @Test
@@ -739,203 +550,6 @@
         }
     }
 
-    /**
-     * Test that the MANAGE_ROLLBACKS permission is required to call
-     * RollbackManager APIs.
-     */
-    @Test
-    public void testManageRollbacksPermission() throws Exception {
-        // We shouldn't be allowed to call any of the RollbackManager APIs
-        // without the MANAGE_ROLLBACKS permission.
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-
-        try {
-            rm.getAvailableRollbacks();
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-
-        try {
-            rm.getRecentlyCommittedRollbacks();
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-
-        try {
-            // TODO: What if the implementation checks arguments for non-null
-            // first? Then this test isn't valid.
-            rm.commitRollback(0, Collections.emptyList(), null);
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-
-        try {
-            rm.reloadPersistedData();
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-
-        try {
-            rm.expireRollbackForPackage(TestApp.A);
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-    }
-
-    /**
-     * Test that you cannot enable rollback for a package without the
-     * MANAGE_ROLLBACKS permission.
-     */
-    @Test
-    public void testEnableRollbackPermission() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES);
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-            Install.single(TestApp.A2).setEnableRollback().commit();
-
-            // We expect v2 of the app was installed, but rollback has not
-            // been enabled.
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-            assertThat(
-                getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that you cannot enable rollback for a non-module package when
-     * holding the MANAGE_ROLLBACKS permission.
-     */
-    @Test
-    public void testNonModuleEnableRollback() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-            Install.single(TestApp.A2).setEnableRollback().commit();
-
-            // We expect v2 of the app was installed, but rollback has not
-            // been enabled because the test app is not a module.
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-            assertThat(
-                getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test rollback of multi-package installs is implemented.
-     */
-    @Test
-    public void testMultiPackage() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            // Prep installation of the test apps.
-            Uninstall.packages(TestApp.A, TestApp.B);
-            Install.multi(TestApp.A1, TestApp.B1).commit();
-            processUserData(TestApp.A);
-            processUserData(TestApp.B);
-            Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-            processUserData(TestApp.A);
-            processUserData(TestApp.B);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // TestApp.A should now be available for rollback.
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            assertThat(rollback).isNotNull();
-            assertThat(rollback).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Rollback the app. It should cause both test apps to be rolled
-            // back.
-            RollbackUtils.rollback(rollback.getRollbackId());
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
-            // We should see recent rollbacks listed for both A and B.
-            Thread.sleep(1000);
-            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.A);
-
-            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
-                    rm.getRecentlyCommittedRollbacks(), TestApp.B);
-            assertThat(rollback).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1),
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            assertThat(rollbackA).hasRollbackId(rollbackB.getRollbackId());
-
-            processUserData(TestApp.A);
-            processUserData(TestApp.B);
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test failure to enable rollback for multi-package installs.
-     * If any one of the packages fail to enable rollback, we shouldn't enable
-     * rollback for any package.
-     */
-    @Test
-    public void testMultiPackageEnableFail() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A, TestApp.B);
-            Install.single(TestApp.A1).commit();
-            // We should fail to enable rollback here because TestApp B is not
-            // already installed.
-            Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            assertThat(getUniqueRollbackInfoForPackage(
-                    rm.getAvailableRollbacks(), TestApp.A)).isNull();
-            assertThat(getUniqueRollbackInfoForPackage(
-                    rm.getAvailableRollbacks(), TestApp.B)).isNull();
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
     @Test
     @Ignore("b/120200473")
     /**