Merge "add shell user permissions for Asistant GTS tests"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 736ee18..f2d10ac 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -2296,31 +2296,35 @@
 
         @Override
         public void onAppAdded(int uid) {
-            final long nowElapsed = sElapsedRealtimeClock.millis();
-            mTempAllowlistCache.put(uid, true);
-            final ArraySet<String> packages = getPackagesForUid(uid);
-            if (packages != null) {
-                final int userId = UserHandle.getUserId(uid);
-                for (int i = packages.size() - 1; i >= 0; --i) {
-                    Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
-                    if (t != null) {
-                        t.onStateChangedLocked(nowElapsed, true);
+            synchronized (mLock) {
+                final long nowElapsed = sElapsedRealtimeClock.millis();
+                mTempAllowlistCache.put(uid, true);
+                final ArraySet<String> packages = getPackagesForUidLocked(uid);
+                if (packages != null) {
+                    final int userId = UserHandle.getUserId(uid);
+                    for (int i = packages.size() - 1; i >= 0; --i) {
+                        Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
+                        if (t != null) {
+                            t.onStateChangedLocked(nowElapsed, true);
+                        }
                     }
-                }
-                if (maybeUpdateConstraintForUidLocked(uid)) {
-                    mStateChangedListener.onControllerStateChanged();
+                    if (maybeUpdateConstraintForUidLocked(uid)) {
+                        mStateChangedListener.onControllerStateChanged();
+                    }
                 }
             }
         }
 
         @Override
         public void onAppRemoved(int uid) {
-            final long nowElapsed = sElapsedRealtimeClock.millis();
-            final long endElapsed = nowElapsed + mEJTempAllowlistGracePeriodMs;
-            mTempAllowlistCache.delete(uid);
-            mTempAllowlistGraceCache.put(uid, endElapsed);
-            Message msg = mHandler.obtainMessage(MSG_END_GRACE_PERIOD, uid, 0);
-            mHandler.sendMessageDelayed(msg, mEJTempAllowlistGracePeriodMs);
+            synchronized (mLock) {
+                final long nowElapsed = sElapsedRealtimeClock.millis();
+                final long endElapsed = nowElapsed + mEJTempAllowlistGracePeriodMs;
+                mTempAllowlistCache.delete(uid);
+                mTempAllowlistGraceCache.put(uid, endElapsed);
+                Message msg = mHandler.obtainMessage(MSG_END_GRACE_PERIOD, uid, 0);
+                mHandler.sendMessageDelayed(msg, mEJTempAllowlistGracePeriodMs);
+            }
         }
     }
 
@@ -2351,7 +2355,7 @@
     }
 
     @Nullable
-    private ArraySet<String> getPackagesForUid(final int uid) {
+    private ArraySet<String> getPackagesForUidLocked(final int uid) {
         ArraySet<String> packages = mUidToPackageCache.get(uid);
         if (packages == null) {
             try {
@@ -2475,7 +2479,7 @@
                             // Update Timers first.
                             if (mPkgTimers.indexOfKey(userId) >= 0
                                     || mEJPkgTimers.indexOfKey(userId) >= 0) {
-                                final ArraySet<String> packages = getPackagesForUid(uid);
+                                final ArraySet<String> packages = getPackagesForUidLocked(uid);
                                 if (packages != null) {
                                     for (int i = packages.size() - 1; i >= 0; --i) {
                                         Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
@@ -2544,7 +2548,7 @@
                             if (DEBUG) {
                                 Slog.d(TAG, uid + " is now out of grace period");
                             }
-                            final ArraySet<String> packages = getPackagesForUid(uid);
+                            final ArraySet<String> packages = getPackagesForUidLocked(uid);
                             if (packages != null) {
                                 final int userId = UserHandle.getUserId(uid);
                                 final long nowElapsed = sElapsedRealtimeClock.millis();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3495f95..faf784d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1927,6 +1927,7 @@
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
     field public static final String ETHERNET_SERVICE = "ethernet";
     field public static final String EUICC_CARD_SERVICE = "euicc_card";
+    field public static final String FONT_SERVICE = "font";
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
     field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
@@ -2588,6 +2589,14 @@
 
 }
 
+package android.graphics.fonts {
+
+  public class FontManager {
+    method @Nullable public android.text.FontConfig getFontConfig();
+  }
+
+}
+
 package android.hardware {
 
   public final class Sensor {
@@ -11879,7 +11888,6 @@
 
   public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable {
     ctor public DataService.DataServiceProvider(int);
-    method public void cancelHandover(int, @NonNull android.telephony.data.DataServiceCallback);
     method public abstract void close();
     method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
     method public final int getSlotIndex();
@@ -11890,15 +11898,12 @@
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
-    method public void startHandover(int, @NonNull android.telephony.data.DataServiceCallback);
   }
 
   public class DataServiceCallback {
     method public void onApnUnthrottled(@NonNull String);
     method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
     method public void onDeactivateDataCallComplete(int);
-    method public void onHandoverCancelled(int);
-    method public void onHandoverStarted(int);
     method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>);
     method public void onSetDataProfileComplete(int);
     method public void onSetInitialAttachApnComplete(int);
@@ -13451,6 +13456,51 @@
 
 }
 
+package android.text {
+
+  public final class FontConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.text.FontConfig.Alias> getAliases();
+    method @NonNull public java.util.List<android.text.FontConfig.FontFamily> getFontFamilies();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
+  }
+
+  public static final class FontConfig.Alias implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public String getName();
+    method @NonNull public String getOriginal();
+    method @IntRange(from=0, to=1000) public int getWeight();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
+  }
+
+  public static final class FontConfig.Font implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.io.File getFile();
+    method @Nullable public String getFontFamilyName();
+    method @NonNull public String getFontVariationSettings();
+    method @NonNull public android.graphics.fonts.FontStyle getStyle();
+    method public int getTtcIndex();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
+  }
+
+  public static final class FontConfig.FontFamily implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.text.FontConfig.Font> getFontList();
+    method @NonNull public android.os.LocaleList getLocaleList();
+    method @Nullable public String getName();
+    method public int getVariant();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.FontFamily> CREATOR;
+    field public static final int VARIANT_COMPACT = 1; // 0x1
+    field public static final int VARIANT_DEFAULT = 0; // 0x0
+    field public static final int VARIANT_ELEGANT = 2; // 0x2
+  }
+
+}
+
 package android.util {
 
   public class EventLog {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5957292..c237d7d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -627,6 +627,7 @@
     field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
     field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
     field public static final String DREAM_SERVICE = "dream";
+    field public static final String FONT_SERVICE = "font";
     field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
@@ -819,6 +820,14 @@
 
 }
 
+package android.graphics.fonts {
+
+  public class FontManager {
+    method @Nullable public android.text.FontConfig getFontConfig();
+  }
+
+}
+
 package android.hardware {
 
   public final class SensorPrivacyManager {
@@ -2019,6 +2028,47 @@
 
 package android.text {
 
+  public final class FontConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.text.FontConfig.Alias> getAliases();
+    method @NonNull public java.util.List<android.text.FontConfig.FontFamily> getFontFamilies();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
+  }
+
+  public static final class FontConfig.Alias implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public String getName();
+    method @NonNull public String getOriginal();
+    method @IntRange(from=0, to=1000) public int getWeight();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
+  }
+
+  public static final class FontConfig.Font implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.io.File getFile();
+    method @Nullable public String getFontFamilyName();
+    method @NonNull public String getFontVariationSettings();
+    method @NonNull public android.graphics.fonts.FontStyle getStyle();
+    method public int getTtcIndex();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
+  }
+
+  public static final class FontConfig.FontFamily implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.text.FontConfig.Font> getFontList();
+    method @NonNull public android.os.LocaleList getLocaleList();
+    method @Nullable public String getName();
+    method public int getVariant();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.FontFamily> CREATOR;
+    field public static final int VARIANT_COMPACT = 1; // 0x1
+    field public static final int VARIANT_DEFAULT = 0; // 0x0
+    field public static final int VARIANT_ELEGANT = 2; // 0x2
+  }
+
   public static final class Selection.MemoryTextWatcher implements android.text.TextWatcher {
     ctor public Selection.MemoryTextWatcher();
     method public void afterTextChanged(android.text.Editable);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5b0ad22..e084c01 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -72,6 +72,7 @@
 import android.content.rollback.RollbackManagerFrameworkInitializer;
 import android.debug.AdbManager;
 import android.debug.IAdbManager;
+import android.graphics.fonts.FontManager;
 import android.hardware.ConsumerIrManager;
 import android.hardware.ISerialManager;
 import android.hardware.SensorManager;
@@ -216,6 +217,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.app.ISoundTriggerService;
 import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.graphics.fonts.IFontManager;
 import com.android.internal.net.INetworkWatchlistManager;
 import com.android.internal.os.IDropBoxManagerService;
 import com.android.internal.policy.PhoneLayoutInflater;
@@ -344,6 +346,14 @@
                 return new TextClassificationManager(ctx);
             }});
 
+        registerService(Context.FONT_SERVICE, FontManager.class,
+                new CachedServiceFetcher<FontManager>() {
+            @Override
+            public FontManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE);
+                return FontManager.create(IFontManager.Stub.asInterface(b));
+            }});
+
         registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
                 new CachedServiceFetcher<ClipboardManager>() {
             @Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3f7479b..6df4304 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4478,6 +4478,18 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.graphics.fonts.FontManager} for font services.
+     *
+     * @see #getSystemService(String)
+     * @see android.graphics.fonts.FontManager
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final String FONT_SERVICE = "font";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link com.android.server.attention.AttentionManagerService} for attention services.
      *
      * @see #getSystemService(String)
diff --git a/core/java/android/graphics/fonts/FontManager.java b/core/java/android/graphics/fonts/FontManager.java
new file mode 100644
index 0000000..ea6cf2f
--- /dev/null
+++ b/core/java/android/graphics/fonts/FontManager.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 android.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.RemoteException;
+import android.text.FontConfig;
+import android.util.Log;
+
+import com.android.internal.graphics.fonts.IFontManager;
+
+import java.util.Objects;
+
+/**
+ * This class gives you control of system installed font files.
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.FONT_SERVICE)
+public class FontManager {
+    private static final String TAG = "FontManager";
+    private final @NonNull IFontManager mIFontManager;
+
+    private FontManager(@NonNull IFontManager iFontManager) {
+        mIFontManager = iFontManager;
+    }
+
+    /**
+     * Returns the system font configuration.
+     *
+     * This information is expected to be used by system font updater. If you are looking for APIs
+     * about drawing text and/or high-level system font information, use
+     * {@link android.graphics.Typeface} or {@link SystemFonts} instead.
+     *
+     * @return The current font configuration. null if failed to fetch information from the system
+     *         service.
+     */
+    public @Nullable FontConfig getFontConfig() {
+        try {
+            return mIFontManager.getFontConfig();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to call getFontConfig", e);
+            return null;
+        }
+    }
+
+    /**
+     * Factory method of the FontManager.
+     *
+     * Do not use this method directly. Use getSystemService(Context.FONT_SERVICE) instead.
+     *
+     * @return A new instance of FontManager
+     * @hide
+     */
+    public static FontManager create(@NonNull IFontManager iFontManager) {
+        Objects.requireNonNull(iFontManager);
+        return new FontManager(iFontManager);
+    }
+}
diff --git a/core/java/android/graphics/fonts/SystemFontState.aidl b/core/java/android/graphics/fonts/SystemFontState.aidl
new file mode 100644
index 0000000..19b20f2
--- /dev/null
+++ b/core/java/android/graphics/fonts/SystemFontState.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.graphics.fonts;
+
+/** @hide */
+parcelable SystemFontState;
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index aced9c7..c3b6c05 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -22,7 +22,9 @@
 oneway interface IUdfpsOverlayController {
     const int REASON_UNKNOWN = 0;
     const int REASON_ENROLL = 1;
-    const int REASON_AUTH = 2;
+    const int REASON_AUTH_BP = 2; // BiometricPrompt
+    const int REASON_AUTH_FPM_KEYGUARD = 3; // FingerprintManager usage from Keyguard
+    const int REASON_AUTH_FPM_OTHER = 4; // Other FingerprintManager usage
 
     // Shows the overlay.
     void showUdfpsOverlay(int sensorId, int reason);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 743713c..ac685f7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10347,6 +10347,7 @@
          * or moving onto external storage. (0 = false, 1 = true)
          * @hide
          */
+         @Readable
         public static final String FORCE_ALLOW_ON_EXTERNAL = "force_allow_on_external";
 
         /**
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index e1a9a05..f7710e6 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -17,6 +17,7 @@
 package android.service.voice;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
@@ -28,6 +29,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -47,24 +49,27 @@
     private boolean mSupportsLaunchFromKeyguard;
     private boolean mSupportsLocalInteraction;
 
-    public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
-            throws PackageManager.NameNotFoundException {
-        this(pm, pm.getServiceInfo(comp, PackageManager.GET_META_DATA));
-    }
-
-    public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
+    /**
+     * Loads the service metadata published by the component. Success is indicated by
+     * {@link #getParseError()}.
+     *
+     * @param pm A PackageManager from which the XML can be loaded.
+     * @param comp The {@link VoiceInteractionService} component.
+     */
+    public VoiceInteractionServiceInfo(
+            @NonNull PackageManager pm, @NonNull ComponentName comp, int userHandle)
             throws PackageManager.NameNotFoundException {
         this(pm, getServiceInfoOrThrow(comp, userHandle));
     }
 
-    static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
+    @NonNull
+    private static ServiceInfo getServiceInfoOrThrow(@NonNull ComponentName comp, int userHandle)
             throws PackageManager.NameNotFoundException {
         try {
             ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(comp,
                     PackageManager.GET_META_DATA
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                     userHandle);
             if (si != null) {
                 return si;
@@ -74,20 +79,23 @@
         throw new PackageManager.NameNotFoundException(comp.toString());
     }
 
-    public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) {
-        if (si == null) {
-            mParseError = "Service not available";
-            return;
-        }
+    /**
+     * Loads the service metadata published by the component. Success is indicated by
+     * {@link #getParseError()}.
+     *
+     * @param pm A PackageManager from which the XML can be loaded; usually the PackageManager
+     *           from which {@code si} was originally retrieved.
+     * @param si The {@link VoiceInteractionService} info.
+     */
+    public VoiceInteractionServiceInfo(@NonNull PackageManager pm, @NonNull ServiceInfo si) {
         if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) {
             mParseError = "Service does not require permission "
                     + Manifest.permission.BIND_VOICE_INTERACTION;
             return;
         }
 
-        XmlResourceParser parser = null;
-        try {
-            parser = si.loadXmlMetaData(pm, VoiceInteractionService.SERVICE_META_DATA);
+        try (XmlResourceParser parser = si.loadXmlMetaData(pm,
+                VoiceInteractionService.SERVICE_META_DATA)) {
             if (parser == null) {
                 mParseError = "No " + VoiceInteractionService.SERVICE_META_DATA
                         + " meta-data for " + si.packageName;
@@ -134,20 +142,10 @@
                 mParseError = "No recognitionService specified";
                 return;
             }
-        } catch (XmlPullParserException e) {
+        } catch (XmlPullParserException | IOException | PackageManager.NameNotFoundException e) {
             mParseError = "Error parsing voice interation service meta-data: " + e;
             Log.w(TAG, "error parsing voice interaction service meta-data", e);
             return;
-        } catch (IOException e) {
-            mParseError = "Error parsing voice interation service meta-data: " + e;
-            Log.w(TAG, "error parsing voice interaction service meta-data", e);
-            return;
-        } catch (PackageManager.NameNotFoundException e) {
-            mParseError = "Error parsing voice interation service meta-data: " + e;
-            Log.w(TAG, "error parsing voice interaction service meta-data", e);
-            return;
-        } finally {
-            if (parser != null) parser.close();
         }
         mServiceInfo = si;
     }
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 8492363..82d7399 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -22,51 +22,66 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontStyle;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.Build;
 import android.os.LocaleList;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 import java.io.File;
 import java.lang.annotation.Retention;
+import java.util.ArrayList;
 import java.util.List;
 
 
 /**
  * Font configuration descriptions for System fonts.
- * @hide  // TODO Make this SystemApi.
+ *
+ * FontConfig represents the configuration for the fonts installed on the system. It is made of list
+ * of font families and aliases.
+ *
+ * @see FontFamily
+ * @see Alias
+ * @hide
  */
-public final class FontConfig {
-    private final @NonNull List<Family> mFamilies;
+@SystemApi
+@TestApi
+public final class FontConfig implements Parcelable {
+    private final @NonNull List<FontFamily> mFamilies;
     private final @NonNull List<Alias> mAliases;
 
     /**
-     * Construct a SystemFontConfig instance.
+     * Construct a FontConfig instance.
      *
      * @param families a list of font families.
      * @param aliases a list of aliases.
      *
      * @hide Only system server can create this instance and passed via IPC.
      */
-    public FontConfig(@NonNull List<Family> families, @NonNull List<Alias> aliases) {
+    public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases) {
         mFamilies = families;
         mAliases = aliases;
     }
 
     /**
-     * Returns the ordered list of families included in the system fonts.
+     * Returns the ordered list of font families available in the system.
      *
      * @return a list of font families.
+     * @see FontFamily
      */
-    public @NonNull List<Family> getFontFamilies() {
+    public @NonNull List<FontFamily> getFontFamilies() {
         return mFamilies;
     }
 
     /**
-     * Returns the list of aliases defined for the font families in the system fonts.
+     * Returns the list of aliases for mapping font families with other names.
      *
      * @return a list of font families.
+     * @see Alias
      */
     public @NonNull List<Alias> getAliases() {
         return mAliases;
@@ -75,106 +90,167 @@
     /**
      * Returns the ordered list of families included in the system fonts.
      * @deprecated Use getFontFamilies instead.
+     * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public @NonNull Family[] getFamilies() {
-        return mFamilies.toArray(new Family[0]);
+    public @NonNull FontFamily[] getFamilies() {
+        return mFamilies.toArray(new FontFamily[0]);
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelableList(mFamilies, flags);
+        dest.writeParcelableList(mAliases, flags);
+    }
+
+    public static final @NonNull Creator<FontConfig> CREATOR = new Creator<FontConfig>() {
+        @Override
+        public FontConfig createFromParcel(Parcel source) {
+            List<FontFamily> families = source.readParcelableList(new ArrayList<>(),
+                    FontFamily.class.getClassLoader());
+            List<Alias> aliases = source.readParcelableList(new ArrayList<>(),
+                    Alias.class.getClassLoader());
+            return new FontConfig(families, aliases);
+        }
+
+        @Override
+        public FontConfig[] newArray(int size) {
+            return new FontConfig[size];
+        }
+    };
+
     /**
-     * A class represents single font entry in system font configuration.
+     * Represents single font entry in system font configuration.
+     *
+     * A font is the most primitive unit of drawing character shapes. A font in system configuration
+     * is always referring a single OpenType compliant regular file in the file system.
+     *
+     * @see android.graphics.fonts.Font
      */
-    public static final class Font {
-        private final @NonNull File mFilePath;
-        private final @Nullable File mOriginalPath;
+    public static final class Font implements Parcelable {
+        private final @NonNull File mFile;
+        private final @Nullable File mOriginalFile;
         private final @NonNull FontStyle mStyle;
         private final @IntRange(from = 0) int mIndex;
         private final @NonNull String mFontVariationSettings;
-        private final @Nullable String mFallback;
+        private final @Nullable String mFontFamilyName;
 
         /**
          * Construct a Font instance.
          *
          * @hide Only system server can create this instance and passed via IPC.
          */
-        public Font(@NonNull File filePath, @Nullable File originalPath, @NonNull FontStyle style,
+        public Font(@NonNull File file, @Nullable File originalFile, @NonNull FontStyle style,
                 @IntRange(from = 0) int index, @NonNull String fontVariationSettings,
-                @Nullable String fallback) {
-            mFilePath = filePath;
-            mOriginalPath = originalPath;
+                @Nullable String fontFamilyName) {
+            mFile = file;
+            mOriginalFile = originalFile;
             mStyle = style;
             mIndex = index;
             mFontVariationSettings = fontVariationSettings;
-            mFallback = fallback;
+            mFontFamilyName = fontFamilyName;
         }
 
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeString8(mFile.getAbsolutePath());
+            dest.writeString8(mOriginalFile == null ? null : mOriginalFile.getAbsolutePath());
+            dest.writeInt(mStyle.getWeight());
+            dest.writeInt(mStyle.getSlant());
+            dest.writeInt(mIndex);
+            dest.writeString8(mFontVariationSettings);
+            dest.writeString8(mFontFamilyName);
+        }
+
+        public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
+
+            @Override
+            public Font createFromParcel(Parcel source) {
+                File path = new File(source.readString8());
+                String originalPathStr = source.readString8();
+                File originalPath = originalPathStr == null ? null : new File(originalPathStr);
+                int weight = source.readInt();
+                int slant = source.readInt();
+                int index = source.readInt();
+                String varSettings = source.readString8();
+                String fallback = source.readString8();
+
+                return new Font(path, originalPath, new FontStyle(weight, slant), index,
+                        varSettings, fallback);
+            }
+
+            @Override
+            public Font[] newArray(int size) {
+                return new Font[size];
+            }
+        };
+
         /**
-         * Returns a file to the font file.
-         *
-         * @return a font file.
+         * Returns the font file.
          */
-        public @NonNull File getFilePath() {
-            return mFilePath;
+        public @NonNull File getFile() {
+            return mFile;
         }
 
         /**
-         * Returns an original font file in the system directory.
+         * Returns the original font file in the system directory.
          *
          * If the font file is not updated, returns null.
          *
          * @return returns the original font file in the system if the font file is updated. Returns
          *         null if the font file is not updated.
+         * @hide
          */
-        public @Nullable File getOriginalPath() {
-            return mOriginalPath;
+        public @Nullable File getOriginalFile() {
+            return mOriginalFile;
         }
 
         /**
-         * Returns a font style.
-         *
-         * @return a font style.
+         * Returns the font style.
          */
         public @NonNull FontStyle getStyle() {
             return mStyle;
         }
 
-        /**
-         * Returns a font index.
-         *
-         * @return a font index.
-         */
-        public @IntRange(from = 0) int getIndex() {
-            return mIndex;
-        }
 
         /**
          * Return a font variation settings.
-         *
-         * @return a font variation settings.
          */
         public @NonNull String getFontVariationSettings() {
             return mFontVariationSettings;
         }
 
         /**
-         * Returns font family name that uses this font as a fallback.
+         * A {@link Font} can be configured to be in the {@code Fallback List} for a
+         * {@link FontFamily}.
          *
-         * If this font is a fallback for the default font family, this is null.
+         * For example a serif Hebrew [Font] can be defined in the {@code Fallback List} for
+         * {@code "serif"} {@link FontFamily}.
          *
-         * @return a font family name.
+         * If the return value is not {@code null}, then the font will be used in the
+         * {@code Fallback List} of that {@link FontFamily}.
+         *
+         * If the return value is {@code null}, then the font will be used in {@code Fallback List}
+         * of all {@link FontFamily}s.
          */
-        public @Nullable String getFallback() {
-            return mFallback;
+        public @Nullable String getFontFamilyName() {
+            return mFontFamilyName;
         }
 
         /**
          * Returns the index to be used to access this font when accessing a TTC file.
-         * @deprecated Use getIndex instead.
-         * @hide
          */
-        @Deprecated
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public int getTtcIndex() {
             return mIndex;
         }
@@ -214,48 +290,46 @@
     }
 
     /**
-     * A class represents alias between named font families.
+     * Alias provides an alternative name for an existing font family.
      *
-     * In the system font configuration, an font family can be an alias of another font family with
+     * In the system font configuration, a font family can be an alias of another font family with
      * different font weight. For example, "sans-serif-medium" can be a medium weight of
-     * sans-serif font family.
+     * "sans-serif" font family. In this example, {@link #getName()} returns "sans-serif-medium" and
+     * {@link #getOriginal()} return "sans-serif". The font family that doesn't have name can not be
+     * an original of the alias.
      */
-    public static final class Alias {
-        private final @NonNull String mAliasName;
-        private final @NonNull String mReferName;
+    public static final class Alias implements Parcelable {
+        private final @NonNull String mName;
+        private final @NonNull String mOriginal;
         private final @IntRange(from = 0, to = 1000) int mWeight;
 
         /**
          * Construct an alias instance.
          *
-         * @param aliasName an alias of the named font family.
-         * @param referName a referring font family name.
-         * @param weight a font weight of the referring font family.
+         * @param name alias for the font family.
+         * @param original original font family name.
+         * @param weight font weight of the original font family.
          * @hide Only system server can create this instance and passed via IPC.
          */
-        public Alias(@NonNull String aliasName, @NonNull String referName,
+        public Alias(@NonNull String name, @NonNull String original,
                 @IntRange(from = 0, to = 1000) int weight) {
-            mAliasName = aliasName;
-            mReferName = referName;
+            mName = name;
+            mOriginal = original;
             mWeight = weight;
         }
 
         /**
-         * An alias of the named font family.
-         *
-         * @return an alias of the named font family.
+         * Alias for the font family
          */
-        public @NonNull String getAliasName() {
-            return mAliasName;
+        public @NonNull String getName() {
+            return mName;
         }
 
         /**
-         * A name of font family referring from {@link #getAliasName()}
-         *
-         * @return a referring font family name.
+         * The name of the original font family.
          */
-        public @NonNull String getReferName() {
-            return mReferName;
+        public @NonNull String getOriginal() {
+            return mOriginal;
         }
 
         /**
@@ -266,17 +340,47 @@
         public @IntRange(from = 0, to = 1000) int getWeight() {
             return mWeight;
         }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeString8(mName);
+            dest.writeString8(mOriginal);
+            dest.writeInt(mWeight);
+        }
+
+        public static final @NonNull Creator<Alias> CREATOR = new Creator<Alias>() {
+
+            @Override
+            public Alias createFromParcel(Parcel source) {
+                String alias = source.readString8();
+                String referName = source.readString8();
+                int weight = source.readInt();
+                return new Alias(alias, referName, weight);
+            }
+
+            @Override
+            public Alias[] newArray(int size) {
+                return new Alias[size];
+            }
+        };
     }
 
     /**
-     * A class represents single font family entry in system font configuration.
+     * Represents a font family in the system font configuration.
      *
-     * <p>
-     * A font family is a bundle of fonts for drawing text in various styles.
-     * For example, regular style font and bold style font can be bundled into a single font family,
-     * then system will select the correct style font from family for drawing.
+     * A {@link FontFamily} is a list of {@link Font}s for drawing text in various styles such as
+     * weight, slant.
+     *
+     * For example, a {@link FontFamily} can include the regular and bold styles of a {@link Font}.
+     *
+     * @see android.graphics.fonts.FontFamily
      */
-    public static final class Family {
+    public static final class FontFamily implements Parcelable {
         private final @NonNull List<Font> mFonts;
         private final @Nullable String mName;
         private final @Nullable LocaleList mLocaleList;
@@ -319,7 +423,7 @@
          *
          * @hide Only system server can create this instance and passed via IPC.
          */
-        public Family(@NonNull List<Font> fonts, @Nullable String name,
+        public FontFamily(@NonNull List<Font> fonts, @Nullable String name,
                 @Nullable LocaleList localeList, @Variant int variant) {
             mFonts = fonts;
             mName = name;
@@ -328,7 +432,7 @@
         }
 
         /**
-         * Returns a list of font files in this family.
+         * Returns the list of {@link Font}s in this {@link FontFamily}.
          *
          * @return a list of font files.
          */
@@ -337,61 +441,77 @@
         }
 
         /**
-         * Returns a family name if this family defines a new fallback.
+         * Returns the name of the {@link FontFamily}.
          *
-         * @return non-null if a family name is associated. Otherwise null.
+         * When the name of a {@link FontFamily} is not null, this name is used to create a new
+         * {@code Fallback List}, and that {@code Fallback List}. Fallback List is the
+         * main building block for a {@link android.graphics.Typeface}.
+         *
+         * For example, if the {@link FontFamily} has the name "serif", then the system will create
+         * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
+         * {@code Typeface.create("serif", Typeface.NORMAL);}
+         *
+         * When the name of a {@link FontFamily} is null, it will be appended to all of the
+         * {@code Fallback List}s.
          */
-        public @Nullable String getFallbackName() {
+        public @Nullable String getName() {
             return mName;
         }
 
         /**
-         * Returns a locale list if associated.
+         * Returns the locale list if available.
          *
-         * @return non-null if a locale list is associated. Otherwise null.
+         * The locale list will be used for deciding which font family should be used in fallback
+         * list.
+         *
+         * @return non-null if a locale list is available. Otherwise null.
          */
         public @NonNull LocaleList getLocaleList() {
             return mLocaleList;
         }
 
         /**
-         * Returns a text height variant.
-         *
-         * @return text height variant.
+         * Returns the text height variant.
          */
-        public @Variant int getTextHeightVariant() {
-            return mVariant;
-        }
-
-        /**
-         * Returns a family variant associated.
-         *
-         * @return a family variant.
-         * @deprecated Use getTextHeightVariant instead.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public @Variant int getVariant() {
             return mVariant;
         }
 
-        /**
-         * Returns a family name if associated.
-         *
-         * @return non-null if a family name is associated. Otherwise null.
-         * @deprecated Use getFallbackName instead.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public @Nullable String getName() {
-            return mName;
+        @Override
+        public int describeContents() {
+            return 0;
         }
 
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeParcelableList(mFonts, flags);
+            dest.writeString8(mName);
+            dest.writeString8(mLocaleList.toLanguageTags());
+            dest.writeInt(mVariant);
+        }
+
+        public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() {
+
+            @Override
+            public FontFamily createFromParcel(Parcel source) {
+                List<Font> fonts = source.readParcelableList(
+                        new ArrayList<>(), Font.class.getClassLoader());
+                String name = source.readString8();
+                String langTags = source.readString8();
+                int variant = source.readInt();
+
+                return new FontFamily(fonts, name, LocaleList.forLanguageTags(langTags), variant);
+            }
+
+            @Override
+            public FontFamily[] newArray(int size) {
+                return new FontFamily[size];
+            }
+        };
+
         /**
          * Returns the list of fonts included in this family.
-         * @deprecated Use getFontFiles instead
+         * @deprecated Use getFontList instead
          * @hide
          */
         @Deprecated
diff --git a/core/java/android/text/method/TranslationTransformationMethod.java b/core/java/android/text/method/TranslationTransformationMethod.java
new file mode 100644
index 0000000..cf66ac7
--- /dev/null
+++ b/core/java/android/text/method/TranslationTransformationMethod.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.method;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.translation.TranslationRequest;
+import android.widget.TextView;
+
+import java.util.regex.Pattern;
+
+/**
+ * Transforms source text into an translated string.
+ *
+ * @hide
+ */
+public class TranslationTransformationMethod implements TransformationMethod2 {
+
+    private static final String TAG = "TranslationTransformationMethod";
+    private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
+
+    @NonNull
+    private TranslationRequest mTranslationRequest;
+    @Nullable
+    private TransformationMethod mOriginalTranslationMethod;
+    private boolean mAllowLengthChanges;
+
+    /**
+     * @param request the translated result from translation service.
+     * @param method the {@link TextView}'s original {@link TransformationMethod}
+     */
+    public TranslationTransformationMethod(@NonNull TranslationRequest request,
+            @Nullable TransformationMethod method) {
+        mTranslationRequest = request;
+        mOriginalTranslationMethod = method;
+    }
+
+    /**
+     * Returns the {@link TextView}'s original {@link TransformationMethod}. This can be used to
+     * restore to show if the user pauses or finish the ui translation.
+     */
+    public TransformationMethod getOriginalTransformationMethod() {
+        return mOriginalTranslationMethod;
+    }
+
+    @Override
+    public CharSequence getTransformation(CharSequence source, View view) {
+        if (!mAllowLengthChanges) {
+            Log.w(TAG, "Caller did not enable length changes; not transforming to translated text");
+            return source;
+        }
+        CharSequence translatedText = mTranslationRequest.getTranslationText();
+        if (TextUtils.isEmpty(translatedText) || isWhitespace(translatedText.toString())) {
+            return source;
+        } else {
+            // TODO(b/174283799): apply the spans to the text
+            return translatedText;
+        }
+    }
+
+    @Override
+    public void onFocusChanged(View view, CharSequence sourceText,
+            boolean focused, int direction,
+            Rect previouslyFocusedRect) {
+        // do nothing
+    }
+
+    @Override
+    public void setLengthChangesAllowed(boolean allowLengthChanges) {
+        mAllowLengthChanges = allowLengthChanges;
+    }
+
+    private boolean isWhitespace(String text) {
+        return PATTERN_WHITESPACE.matcher(text.substring(0, text.length())).matches();
+    }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 04fe897..5c0e156 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -139,6 +139,7 @@
 import android.view.inspector.InspectableProperty;
 import android.view.inspector.InspectableProperty.EnumEntry;
 import android.view.inspector.InspectableProperty.FlagEntry;
+import android.view.translation.TranslationRequest;
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
@@ -30630,4 +30631,72 @@
             mPrivateFlags4 &= ~PFLAG4_DETACHED;
         }
     }
+
+    /**
+     * Returns a {@link TranslationRequest} to the {@link onStartUiTranslation} which represents
+     * the content to be translated.
+     *
+     * <p>The default implementation does nothing and return null.</p>
+     *
+     * @hide
+     *
+     * @return the {@link TranslationRequest} which contains the information to be translated.
+     */
+    @Nullable
+    //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+    public TranslationRequest onCreateTranslationRequest() {
+        return null;
+    }
+
+    /**
+     * Called when the user wants to show the original text instead of the translated text.
+     *
+     * @hide
+     *
+     * <p> The default implementation does nothing.
+     */
+    //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+    public void onPauseUiTranslation() {
+        // no-op
+    }
+
+    /**
+     * User can switch back to show the original text, this method called when the user wants to
+     * re-show the translated text again.
+     *
+     * @hide
+     *
+     * <p> The default implementation does nothing.</p>
+     */
+    //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+    public void onRestoreUiTranslation() {
+        // no-op
+    }
+
+    /**
+     * Called when the user finish the Ui translation and no longer to show the translated text.
+     *
+     * @hide
+     *
+     * <p> The default implementation does nothing.</p>
+     */
+    //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+    public void onFinishUiTranslation() {
+        // no-op
+    }
+
+    /**
+     * Called when the request from {@link onStartUiTranslation} is completed by the translation
+     * service so that the translation result can be shown.
+     *
+     * @hide
+     *
+     * <p> The default implementation does nothing.</p>
+     *
+     * @param request the translated information which can be shown in the view.
+     */
+    //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+    public void onTranslationComplete(@NonNull TranslationRequest request) {
+        // no-op
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b866025..8cfbca8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -129,6 +129,7 @@
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
 import android.text.method.TransformationMethod2;
+import android.text.method.TranslationTransformationMethod;
 import android.text.method.WordIterator;
 import android.text.style.CharacterStyle;
 import android.text.style.ClickableSpan;
@@ -193,6 +194,7 @@
 import android.view.textclassifier.TextLinks;
 import android.view.textservice.SpellCheckerSubtype;
 import android.view.textservice.TextServicesManager;
+import android.view.translation.TranslationRequest;
 import android.widget.RemoteViews.RemoteView;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -732,6 +734,7 @@
     private MovementMethod mMovement;
 
     private TransformationMethod mTransformation;
+    private TranslationTransformationMethod mTranslationTransformation;
     @UnsupportedAppUsage
     private boolean mAllowTransformationLengthChange;
     @UnsupportedAppUsage
@@ -13814,4 +13817,121 @@
             Log.d(LOG_TAG, location + ": " + String.format(msgFormat, msgArgs));
         }
     }
+
+    /**
+     * Provides a {@link TranslationRequest} that represents the content to be translated via
+     * translation service.
+     *
+     * <p>NOTE: When overriding the method, it should not translate the password. We also suggest
+     * that not translating the text is selectable or editable. We use the transformation method to
+     * implement showing the translated text. The TextView does not support the transformation
+     * method text length change. If the text is selectable or editable, it will crash while
+     * selecting the text. To support it, it needs broader changes to text APIs, we only allow to
+     * translate non selectable and editable text now.
+     *
+     * @hide
+     */
+    @Nullable
+    @Override
+    public TranslationRequest onCreateTranslationRequest() {
+        if (mText == null || mText.length() == 0) {
+            return null;
+        }
+        // Not translate password, editable text and not important for translation
+        // TODO(b/177214256): support selectable text translation. It needs to broader changes to
+        //  text selection apis, not support in S.
+        boolean isPassword = isAnyPasswordInputType() || hasPasswordTransformationMethod();
+        if (isTextEditable() || isPassword || isTextSelectable()) {
+            return null;
+        }
+        // TODO(b/176488462): apply the view's important for translation property
+        // TODO(b/174283799): remove the spans from the mText and save the spans informatopn
+        TranslationRequest request =
+                new TranslationRequest.Builder()
+                        .setAutofillId(getAutofillId())
+                        .setTranslationText(mText)
+                        .build();
+        return request;
+    }
+
+    /**
+     * Provides the implementation that pauses the ongoing Ui translation, it will show the original
+     * text instead of the translated text and restore the original transformation method.
+     *
+     * <p>NOTE: If this method is overridden, other translation related methods such as
+     * {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+     * should also be overridden.
+     *
+     * @hide
+     */
+    @Override
+    public void onPauseUiTranslation() {
+        // Restore to original text content.
+        if (mTranslationTransformation != null) {
+            setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+        }
+    }
+
+    /**
+     * Provides the implementation that restoes the paused Ui translation, it will show the
+     * translated text again if the text had been translated. This method will replace the current
+     * tansformation method with {@link TranslationTransformationMethod}.
+     *
+     * <p>NOTE: If this method is overridden, other translation related methods such as
+     * {@link onPauseUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+     * should also be overridden.
+     *
+     * @hide
+     */
+    @Override
+    public void onRestoreUiTranslation() {
+        if (mTranslationTransformation != null) {
+            setTransformationMethod(mTranslationTransformation);
+        } else {
+            Log.w(LOG_TAG, "onResumeTranslatedText(): no translated text.");
+        }
+    }
+
+    /**
+     * Provides the implementation that finishes the current Ui translation and it's no longer to
+     * show the translated text. This method restores the original transformation method and resets
+     * the saved {@link TranslationTransformationMethod}.
+     *
+     * <p>NOTE: If this method is overridden, other translation related methods such as
+     * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onTranslationComplete}
+     * should also be overridden.
+     *
+     * @hide
+     */
+    @Override
+    public void onFinishUiTranslation() {
+        // Restore to original text content and clear TranslationTransformation
+        if (mTranslationTransformation != null) {
+            setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+            mTranslationTransformation = null;
+        }
+    }
+
+    /**
+     * Default {@link TextView} implementation after the translation request is done by the
+     * translation service, it's ok to show the translated text. This method will save the original
+     * transformation method and replace the current transformation method with
+     * {@link TranslationTransformationMethod}.
+     *
+     * <p>NOTE: If this method is overridden, other translation related methods such as
+     * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}
+     * should also be overridden.
+     *
+     * @hide
+     */
+    @Override
+    public void onTranslationComplete(@NonNull TranslationRequest data) {
+        // Show the translated text.
+        TransformationMethod originalTranslationMethod = mTranslationTransformation != null
+                ? mTranslationTransformation.getOriginalTransformationMethod() : mTransformation;
+        mTranslationTransformation =
+                new TranslationTransformationMethod(data, originalTranslationMethod);
+        // TODO(b/178353965): well-handle setTransformationMethod.
+        setTransformationMethod(mTranslationTransformation);
+    }
 }
diff --git a/core/java/com/android/internal/graphics/fonts/IFontManager.aidl b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
new file mode 100644
index 0000000..a11c7ef
--- /dev/null
+++ b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
@@ -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 com.android.internal.graphics.fonts;
+
+import android.text.FontConfig;
+import android.graphics.fonts.SystemFontState;
+
+/**
+ * System private interface for talking with
+ * {@link com.android.server.graphics.fonts.FontManagerService}.
+ * @hide
+ */
+interface IFontManager {
+    FontConfig getFontConfig();
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 4b343af..fda87be 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -103,7 +103,7 @@
      */
     public static final int PROFILE_FROM_SHELL = 1 << 15;
 
-    /**
+    /*
      * Enable using the ART app image startup cache
      */
     public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
@@ -116,6 +116,13 @@
      */
     public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
 
+    /**
+     * Disable runtime access to {@link android.annotation.TestApi} annotated members.
+     *
+     * <p>This only takes effect if Hidden API access restrictions are enabled as well.
+     */
+    public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
+
     public static final int MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20);
     /**
      * Enable pointer tagging in this process.
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 60157bd..43a14dc 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -203,8 +203,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"የዳሳሽ ማሳወቂያ አገልግሎት"</string>
     <string name="twilight_service" msgid="8964898045693187224">"የውጋገን አገልግሎት"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"የሰዓት ሰቅ አንባቢ (ግንኙነት የለም)"</string>
-    <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
-    <skip />
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"የGNSS ጊዜ ዝመኔ አገልግሎት"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string>
@@ -2205,12 +2204,8 @@
     <string name="window_magnification_prompt_content" msgid="4166711383253283838">"አሁን የተወሰነ ወይም ሁሉንም ማያ ገጽዎን ማጉላት ይችላሉ"</string>
     <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string>
     <string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ለመቀጠል፣ &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ወደ መሳሪያዎ ማይክሮፎን መድረስ ይፈልጋል።"</string>
+    <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ለመቀጠል፣ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; የመሣሪያዎን ካሜራ መድረስ ይፈልጋል።"</string>
+    <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"አብራ"</string>
+    <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ዳሳሽ ግላዊነት"</string>
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index c413c33..b6eb959 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -203,8 +203,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"ছেন্সৰ জাননী সেৱা"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight সেৱা"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"সময় মণ্ডল চিনাক্তকাৰী (সংযোগ নাই)"</string>
-    <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
-    <skip />
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS সময় আপডে’ট প্ৰদান কৰা সেৱা"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string>
@@ -2205,12 +2204,8 @@
     <string name="window_magnification_prompt_content" msgid="4166711383253283838">"আপুনি সকলো অথবা কেইখনমান স্ক্ৰীন বিবৰ্ধন কৰিব পাৰে"</string>
     <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string>
     <string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"অব্যাহত ৰাখিবলৈ &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;এ আপোনাৰ ডিভাইচৰ মাইক্ৰ’ফ’ন এক্সেছ কৰাৰ আৱশ্যক।"</string>
+    <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"অব্যাহত ৰাখিবলৈ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;এ আপোনাৰ ডিভাইচৰ কেমেৰা এক্সেছ কৰাৰ আৱশ্যক।"</string>
+    <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"অন কৰক"</string>
+    <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ছেন্সৰ সম্পৰ্কীয় গোপনীয়তাৰ নীতি"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 51ca3da..6c54eb1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -205,8 +205,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obavještavanja putem senzora"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Usluga Twilight"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string>
-    <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
-    <skip />
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS usluga za ažuriranje vremena"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -2239,12 +2238,8 @@
     <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sada možete uvećati dio ekrana ili cijeli ekran"</string>
     <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
     <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Da nastavite, aplikaciji &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; je potreban pristup mikrofonu vašeg uređaja."</string>
+    <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Da nastavite, aplikaciji &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; je potreban pristup kameri vašeg uređaja."</string>
+    <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Uključi"</string>
+    <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatnost senzora"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 084250e..98d715b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -203,8 +203,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"سرویس اعلان حسگر"</string>
     <string name="twilight_service" msgid="8964898045693187224">"‏سرویس Twilight"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"شناساگر منطقه زمانی (بدون اتصال)"</string>
-    <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
-    <skip />
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"‏سرویس به‌روزرسانی زمان GNSS"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمی‌توان استفاده کرد. دستگاه شما در این لحظه پاک می‌شود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string>
@@ -2205,12 +2204,8 @@
     <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اکنون می‌توانید بخشی از صفحه یا کل آن را درشت کنید"</string>
     <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string>
     <string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"‏برای ادامه دادن، &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; باید به میکروفون دستگاه دسترسی داشته باشد."</string>
+    <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‏برای ادامه دادن، &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; باید به دوربین دستگاه دسترسی داشته باشد."</string>
+    <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"روشن کردن"</string>
+    <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"حریم‌خصوصی حسگر"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 58d47c4..e34bf8b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -203,8 +203,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification de capteur"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Service de crépuscule"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Détecteur de fuseau horaire (aucune connectivité)"</string>
-    <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
-    <skip />
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"Service d\'actualisation de l\'heure GNSS"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -2205,12 +2204,8 @@
     <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir une partie ou la totalité de votre écran"</string>
     <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
     <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Pour continuer, vous devez accorder l\'accès au microphone de votre appareil à l\'application &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Pour continuer, vous devez accorder l\'accès à l\'appareil photo de votre appareil à l\'application &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activer"</string>
+    <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Confidentialité des capteurs"</string>
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index fac6dbc..b309e4a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -57,7 +57,7 @@
     <string name="imei" msgid="2157082351232630390">"IMEI"</string>
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
     <string name="ClipMmi" msgid="4110549342447630629">"आगमन कलर ID"</string>
-    <string name="ClirMmi" msgid="6752346475055446417">"बहिर्गमन कल गर्ने व्यक्तिको ID लुकाउनुहोस्"</string>
+    <string name="ClirMmi" msgid="6752346475055446417">"आफ्नो नाम र टेलिफोन नम्बर लुकाएर टेलिफोन गर्नुहोस्"</string>
     <string name="ColpMmi" msgid="4736462893284419302">"लाइन ID जोडियो"</string>
     <string name="ColrMmi" msgid="5889782479745764278">"जोडिएको लाइन ID प्रतिबन्ध"</string>
     <string name="CfMmi" msgid="8390012691099787178">"कल अगाडि बढाउँदै"</string>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index ff38117..c8ff95d 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -100,10 +100,10 @@
             @NonNull FontCustomizationParser.Result customization,
             @Nullable Map<String, File> updatableFontMap)
             throws XmlPullParserException, IOException {
-        List<FontConfig.Family> families = new ArrayList<>();
+        List<FontConfig.FontFamily> families = new ArrayList<>();
         List<FontConfig.Alias> aliases = new ArrayList<>(customization.getAdditionalAliases());
 
-        Map<String, FontConfig.Family> oemNamedFamilies =
+        Map<String, FontConfig.FontFamily> oemNamedFamilies =
                 customization.getAdditionalNamedFamilies();
 
         parser.require(XmlPullParser.START_TAG, null, "familyset");
@@ -111,8 +111,8 @@
             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
             String tag = parser.getName();
             if (tag.equals("family")) {
-                FontConfig.Family family = readFamily(parser, fontDir, updatableFontMap);
-                String name = family.getFallbackName();
+                FontConfig.FontFamily family = readFamily(parser, fontDir, updatableFontMap);
+                String name = family.getName();
                 if (name == null || !oemNamedFamilies.containsKey(name)) {
                     // The OEM customization overrides system named family. Skip if OEM
                     // customization XML defines the same named family.
@@ -132,7 +132,7 @@
     /**
      * Read family tag in fonts.xml or oem_customization.xml
      */
-    public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir,
+    public static FontConfig.FontFamily readFamily(XmlPullParser parser, String fontDir,
             @Nullable Map<String, File> updatableFontMap)
             throws XmlPullParserException, IOException {
         final String name = parser.getAttributeValue(null, "name");
@@ -148,15 +148,15 @@
                 skip(parser);
             }
         }
-        int intVariant = FontConfig.Family.VARIANT_DEFAULT;
+        int intVariant = FontConfig.FontFamily.VARIANT_DEFAULT;
         if (variant != null) {
             if (variant.equals("compact")) {
-                intVariant = FontConfig.Family.VARIANT_COMPACT;
+                intVariant = FontConfig.FontFamily.VARIANT_COMPACT;
             } else if (variant.equals("elegant")) {
-                intVariant = FontConfig.Family.VARIANT_ELEGANT;
+                intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
             }
         }
-        return new FontConfig.Family(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
+        return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
     }
 
     /** Matches leading and trailing XML whitespace. */
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f1866cd..a0568bf 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1151,10 +1151,10 @@
 
         for (int i = 0; i < aliases.size(); ++i) {
             final FontConfig.Alias alias = aliases.get(i);
-            if (outSystemFontMap.containsKey(alias.getAliasName())) {
+            if (outSystemFontMap.containsKey(alias.getName())) {
                 continue; // If alias and named family are conflict, use named family.
             }
-            final Typeface base = outSystemFontMap.get(alias.getReferName());
+            final Typeface base = outSystemFontMap.get(alias.getOriginal());
             if (base == null) {
                 // The missing target is a valid thing, some configuration don't have font files,
                 // e.g. wear devices. Just skip this alias.
@@ -1163,7 +1163,7 @@
             final int weight = alias.getWeight();
             final Typeface newFace = weight == 400 ? base :
                     new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
-            outSystemFontMap.put(alias.getAliasName(), newFace);
+            outSystemFontMap.put(alias.getName(), newFace);
         }
     }
 
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index 1ad6fbe..42033ba 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -17,7 +17,7 @@
 package android.graphics.fonts;
 
 import static android.text.FontConfig.Alias;
-import static android.text.FontConfig.Family;
+import static android.text.FontConfig.FontFamily;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -46,7 +46,7 @@
      * Represents a customization XML
      */
     public static class Result {
-        private final Map<String, Family> mAdditionalNamedFamilies;
+        private final Map<String, FontFamily> mAdditionalNamedFamilies;
         private final List<Alias> mAdditionalAliases;
 
         public Result() {
@@ -54,13 +54,13 @@
             mAdditionalAliases = Collections.emptyList();
         }
 
-        public Result(Map<String, Family> additionalNamedFamilies,
+        public Result(Map<String, FontFamily> additionalNamedFamilies,
                 List<Alias> additionalAliases) {
             mAdditionalNamedFamilies = additionalNamedFamilies;
             mAdditionalAliases = additionalAliases;
         }
 
-        public Map<String, Family> getAdditionalNamedFamilies() {
+        public Map<String, FontFamily> getAdditionalNamedFamilies() {
             return mAdditionalNamedFamilies;
         }
 
@@ -85,11 +85,11 @@
         return readFamilies(parser, fontDir, updatableFontMap);
     }
 
-    private static Map<String, Family> validateAndTransformToMap(List<Family> families) {
-        HashMap<String, Family> namedFamily = new HashMap<>();
+    private static Map<String, FontFamily> validateAndTransformToMap(List<FontFamily> families) {
+        HashMap<String, FontFamily> namedFamily = new HashMap<>();
         for (int i = 0; i < families.size(); ++i) {
-            final Family family = families.get(i);
-            final String name = family.getFallbackName();
+            final FontFamily family = families.get(i);
+            final String name = family.getName();
             if (name == null) {
                 throw new IllegalArgumentException("new-named-family requires name attribute");
             }
@@ -106,7 +106,7 @@
             @NonNull String fontDir,
             @Nullable Map<String, File> updatableFontMap
     ) throws XmlPullParserException, IOException {
-        List<Family> families = new ArrayList<>();
+        List<FontFamily> families = new ArrayList<>();
         List<Alias> aliases = new ArrayList<>();
         parser.require(XmlPullParser.START_TAG, null, "fonts-modification");
         while (parser.next() != XmlPullParser.END_TAG) {
@@ -126,7 +126,7 @@
     private static void readFamily(
             @NonNull XmlPullParser parser,
             @NonNull String fontDir,
-            @NonNull List<Family> out,
+            @NonNull List<FontFamily> out,
             @Nullable Map<String, File> updatableFontMap)
             throws XmlPullParserException, IOException {
         final String customizationType = parser.getAttributeValue(null, "customizationType");
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 2f0c26f..c29c194 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -109,7 +109,7 @@
          * @return a font family
          */
         public @NonNull FontFamily build() {
-            return build("", FontConfig.Family.VARIANT_DEFAULT, true /* isCustomFallback */);
+            return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */);
         }
 
         /** @hide */
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 6aa50db..a41215f 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -117,12 +117,12 @@
         }
     }
 
-    private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
+    private static void pushFamilyToFallback(@NonNull FontConfig.FontFamily xmlFamily,
             @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
             @NonNull Map<String, ByteBuffer> cache) {
 
         final String languageTags = xmlFamily.getLocaleList().toLanguageTags();
-        final int variant = xmlFamily.getTextHeightVariant();
+        final int variant = xmlFamily.getVariant();
 
         final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
         final ArrayMap<String, ArrayList<FontConfig.Font>> specificFallbackFonts =
@@ -130,7 +130,7 @@
 
         // Collect default fallback and specific fallback fonts.
         for (final FontConfig.Font font : xmlFamily.getFonts()) {
-            final String fallbackName = font.getFallback();
+            final String fallbackName = font.getFontFamilyName();
             if (fallbackName == null) {
                 defaultFonts.add(font);
             } else {
@@ -144,14 +144,14 @@
         }
 
         final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
-                xmlFamily.getFallbackName(), defaultFonts, languageTags, variant, cache);
+                xmlFamily.getName(), defaultFonts, languageTags, variant, cache);
 
         // Insert family into fallback map.
         for (int i = 0; i < fallbackMap.size(); i++) {
             String name = fallbackMap.keyAt(i);
             final ArrayList<FontConfig.Font> fallback = specificFallbackFonts.get(name);
             if (fallback == null) {
-                String familyName = xmlFamily.getFallbackName();
+                String familyName = xmlFamily.getName();
                 if (defaultFamily != null
                         // do not add myself to the fallback chain.
                         && (familyName == null || !familyName.equals(name))) {
@@ -159,7 +159,7 @@
                 }
             } else {
                 final FontFamily family = createFontFamily(
-                        xmlFamily.getFallbackName(), fallback, languageTags, variant, cache);
+                        xmlFamily.getName(), fallback, languageTags, variant, cache);
                 if (family != null) {
                     fallbackMap.valueAt(i).add(family);
                 } else if (defaultFamily != null) {
@@ -174,7 +174,7 @@
     private static @Nullable FontFamily createFontFamily(@NonNull String familyName,
             @NonNull List<FontConfig.Font> fonts,
             @NonNull String languageTags,
-            @FontConfig.Family.Variant int variant,
+            @FontConfig.FontFamily.Variant int variant,
             @NonNull Map<String, ByteBuffer> cache) {
         if (fonts.size() == 0) {
             return null;
@@ -183,7 +183,7 @@
         FontFamily.Builder b = null;
         for (int i = 0; i < fonts.size(); i++) {
             final FontConfig.Font fontConfig = fonts.get(i);
-            final String fullPath = fontConfig.getFilePath().getAbsolutePath();
+            final String fullPath = fontConfig.getFile().getAbsolutePath();
             ByteBuffer buffer = cache.get(fullPath);
             if (buffer == null) {
                 if (cache.containsKey(fullPath)) {
@@ -201,7 +201,7 @@
                 font = new Font.Builder(buffer, new File(fullPath), languageTags)
                         .setWeight(fontConfig.getStyle().getWeight())
                         .setSlant(fontConfig.getStyle().getSlant())
-                        .setTtcIndex(fontConfig.getIndex())
+                        .setTtcIndex(fontConfig.getTtcIndex())
                         .setFontVariationSettings(fontConfig.getFontVariationSettings())
                         .build();
             } catch (IOException e) {
@@ -217,13 +217,13 @@
         return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */);
     }
 
-    private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
+    private static void appendNamedFamily(@NonNull FontConfig.FontFamily xmlFamily,
             @NonNull HashMap<String, ByteBuffer> bufferCache,
             @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackListMap) {
-        final String familyName = xmlFamily.getFallbackName();
+        final String familyName = xmlFamily.getName();
         final FontFamily family = createFontFamily(
                 familyName, xmlFamily.getFontList(),
-                xmlFamily.getLocaleList().toLanguageTags(), xmlFamily.getTextHeightVariant(),
+                xmlFamily.getLocaleList().toLanguageTags(), xmlFamily.getVariant(),
                 bufferCache);
         if (family == null) {
             return;
@@ -281,12 +281,12 @@
     public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig) {
         final Map<String, FontFamily[]> fallbackMap = new HashMap<>();
         final HashMap<String, ByteBuffer> bufferCache = new HashMap<>();
-        final List<FontConfig.Family> xmlFamilies = fontConfig.getFontFamilies();
+        final List<FontConfig.FontFamily> xmlFamilies = fontConfig.getFontFamilies();
 
         final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
         // First traverse families which have a 'name' attribute to create fallback map.
-        for (final FontConfig.Family xmlFamily : xmlFamilies) {
-            final String familyName = xmlFamily.getFallbackName();
+        for (final FontConfig.FontFamily xmlFamily : xmlFamilies) {
+            final String familyName = xmlFamily.getName();
             if (familyName == null) {
                 continue;
             }
@@ -295,10 +295,10 @@
 
         // Then, add fallback fonts to the each fallback map.
         for (int i = 0; i < xmlFamilies.size(); i++) {
-            final FontConfig.Family xmlFamily = xmlFamilies.get(i);
+            final FontConfig.FontFamily xmlFamily = xmlFamilies.get(i);
             // The first family (usually the sans-serif family) is always placed immediately
             // after the primary family in the fallback.
-            if (i == 0 || xmlFamily.getFallbackName() == null) {
+            if (i == 0 || xmlFamily.getName() == null) {
                 pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache);
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index dd43139..1df2a4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -157,7 +157,6 @@
         });
         options.setLaunchCookie(launchCookie);
         options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        options.setTaskAlwaysOnTop(true);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 67f4cd2..29458ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -140,6 +140,7 @@
                             + getBubbleKey());
                 }
                 try {
+                    options.setTaskAlwaysOnTop(true);
                     if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
                         options.setApplyActivityFlagsForBubbles(true);
                         mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index eb03ab0..4e582c2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -129,7 +129,6 @@
 
         verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
         assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
-        assertThat(options.getTaskAlwaysOnTop()).isTrue();
     }
 
     @Test
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 2a3704d..d40de76 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -28,7 +28,7 @@
 import java.util.TreeSet;
 
 /**
- * Class to provide information about the audio devices.
+ * Provides information about an audio device.
  */
 public final class AudioDeviceInfo {
 
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 7192c07..4d835b2 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -23,7 +23,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.TvInputService;
@@ -54,6 +53,7 @@
 import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.util.Log;
 
 import com.android.internal.util.FrameworkStatsLog;
@@ -352,7 +352,7 @@
                 profile, new HandlerExecutor(mHandler), mResourceListener, clientId);
         mClientId = clientId[0];
 
-        mUserId = ActivityManager.getCurrentUser();
+        mUserId = Process.myUid();
     }
 
     /**
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 597278b..d70b8c2 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -20,13 +20,13 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.app.ActivityManager;
 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;
 import android.media.tv.tuner.filter.Filter;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.util.Log;
 
 import com.android.internal.util.FrameworkStatsLog;
@@ -98,7 +98,7 @@
     private native long nativeRead(byte[] bytes, long offset, long size);
 
     private DvrPlayback() {
-        mUserId = ActivityManager.getCurrentUser();
+        mUserId = Process.myUid();
         mSegmentId = (sInstantId & 0x0000ffff) << 16;
         sInstantId++;
     }
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index 2f2cd96..0f9f2e7 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -19,12 +19,12 @@
 import android.annotation.BytesLong;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.app.ActivityManager;
 import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.Tuner.Result;
 import android.media.tv.tuner.TunerUtils;
 import android.media.tv.tuner.filter.Filter;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.util.Log;
 
 import com.android.internal.util.FrameworkStatsLog;
@@ -61,7 +61,7 @@
     private native long nativeWrite(byte[] bytes, long offset, long size);
 
     private DvrRecorder() {
-        mUserId = ActivityManager.getCurrentUser();
+        mUserId = Process.myUid();
         mSegmentId = (sInstantId & 0x0000ffff) << 16;
         sInstantId++;
     }
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index b9fccf9..d1954a6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -416,10 +416,8 @@
     <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"የማያ ገጽ ቀረጻ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ጀምር"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"አቁም"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ለመቀጠል፣ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ወደ መሳሪያዎ ማይክሮፎን መድረስ ይፈልጋል።"</string>
+    <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ለመቀጠል፣ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; የመሣሪያዎን ካሜራ መድረስ ይፈልጋል።"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"መተግበሪያዎችን ለመቀየር ወደ ላይ ያንሸራትቱ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ቀኝ ይጎትቱ"</string>
@@ -442,8 +440,7 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"ለመክፈት ዳግም መታ ያድርጉ"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"ለመክፈት በጣት ወደ ላይ ጠረግ ያድርጉ"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string>
-    <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
-    <skip />
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ይህ መሳሪያ ንብረትነቱ የ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ነው"</string>
     <string name="phone_hint" msgid="6682125338461375925">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 39f9b86..8abb5ed 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -416,10 +416,8 @@
     <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্ৰীন ৰেকর্ড"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"অব্যাহত ৰাখিবলৈ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;এ আপোনাৰ ডিভাইচৰ মাইক্ৰ’ফ’ন এক্সেছ কৰাৰ আৱশ্যক।"</string>
+    <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"অব্যাহত ৰাখিবলৈ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;এ আপোনাৰ ডিভাইচৰ কেমেৰা এক্সেছ কৰাৰ আৱশ্যক।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"খৰতকীয়াকৈ আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ সোঁফালে টানক"</string>
@@ -442,8 +440,7 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"খুলিবলৈ পুনৰাই টিপক"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"খুলিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
-    <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
-    <skip />
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ৰ"</string>
     <string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index aa80bd8..d2f0c0d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -418,10 +418,8 @@
     <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snimanje ekrana"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Započnite"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavite"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Da nastavite, aplikaciji &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; je potreban pristup mikrofonu vašeg uređaja."</string>
+    <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Da nastavite, aplikaciji &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; je potreban pristup kameri vašeg uređaja."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite prema gore za promjenu aplikacije"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno za brzu promjenu aplikacija"</string>
@@ -444,8 +442,7 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da otvorite"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string>
-    <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
-    <skip />
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="6682125338461375925">"Prevucite preko ikone da otvorite telefon"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6f7044c..dccea5a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -416,10 +416,8 @@
     <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ضبط کردن صفحه‌نمایش"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"‏برای ادامه دادن، &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; باید به میکروفون دستگاه دسترسی داشته باشد."</string>
+    <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"‏برای ادامه دادن، &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; باید به دوربین دستگاه دسترسی داشته باشد."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامه‌ها،‌ تند به‌بالا بکشید"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابه‌جایی سریع میان برنامه‌ها، به چپ بکشید"</string>
@@ -442,8 +440,7 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"دوباره ضربه بزنید تا باز شود"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند به‌بالا بکشید"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند به‌بالا بکشید"</string>
-    <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
-    <skip />
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏برای استفاده از NFC، قفل را باز کنید"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string>
     <string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a2df616..2e36a92 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -416,10 +416,8 @@
     <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Enregistrement d\'écran"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string>
-    <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
-    <skip />
-    <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
-    <skip />
+    <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Pour continuer, vous devez accorder l\'accès au microphone de votre appareil à l\'application &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Pour continuer, vous devez accorder l\'accès à l\'appareil photo de votre appareil à l\'application &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayez vers le haut pour changer d\'application"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Balayez l\'écran vers la droite pour changer rapidement d\'application"</string>
@@ -442,8 +440,7 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Touchez à nouveau pour ouvrir"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Balayez l\'écran vers le haut pour ouvrir"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
-    <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
-    <skip />
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="6682125338461375925">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 93d2f75..0a17828 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -86,10 +86,10 @@
     <bool name="config_navigation_bar_enable_auto_dim_no_visible_wallpaper">true</bool>
 
     <!-- The maximum number of tiles in the QuickQSPanel -->
-    <integer name="quick_qs_panel_max_columns">4</integer>
+    <integer name="quick_qs_panel_max_columns">6</integer>
 
     <!-- The number of columns in the QuickSettings -->
-    <integer name="quick_settings_num_columns">4</integer>
+    <integer name="quick_settings_num_columns">3</integer>
 
     <!-- The number of rows in the QuickSettings -->
     <integer name="quick_settings_max_rows">3</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
new file mode 100644
index 0000000..5fc2e53
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.R;
+
+/**
+ * Abstract base class for animations that should be drawn when the finger is not touching the
+ * sensor area.
+ */
+public abstract class UdfpsAnimation extends Drawable {
+    abstract void updateColor();
+
+    @NonNull protected final Context mContext;
+    @NonNull protected final Drawable mFingerprintDrawable;
+
+    public UdfpsAnimation(@NonNull Context context) {
+        mContext = context;
+        mFingerprintDrawable = context.getResources().getDrawable(R.drawable.ic_fingerprint, null);
+    }
+
+    public void onSensorRectUpdated(@NonNull RectF sensorRect) {
+        int margin =  (int) (sensorRect.bottom - sensorRect.top) / 5;
+        mFingerprintDrawable.setBounds(
+                (int) sensorRect.left + margin,
+                (int) sensorRect.top + margin,
+                (int) sensorRect.right - margin,
+                (int) sensorRect.bottom - margin);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java
new file mode 100644
index 0000000..1a2a492
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.R;
+
+/**
+ * UDFPS animations that should be shown when enrolling.
+ */
+public class UdfpsAnimationEnroll extends UdfpsAnimation {
+    private static final String TAG = "UdfpsAnimationEnroll";
+
+    @Nullable private RectF mSensorRect;
+    @NonNull private final Paint mSensorPaint;
+
+    UdfpsAnimationEnroll(@NonNull Context context) {
+        super(context);
+
+        mSensorPaint = new Paint(0 /* flags */);
+        mSensorPaint.setAntiAlias(true);
+        mSensorPaint.setColor(Color.WHITE);
+        mSensorPaint.setShadowLayer(UdfpsView.SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK);
+        mSensorPaint.setStyle(Paint.Style.FILL);
+    }
+
+    @Override
+    void updateColor() {
+        mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
+    }
+
+    @Override
+    public void onSensorRectUpdated(@NonNull RectF sensorRect) {
+        super.onSensorRectUpdated(sensorRect);
+        mSensorRect = sensorRect;
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        final boolean isNightMode = (mContext.getResources().getConfiguration().uiMode
+                & Configuration.UI_MODE_NIGHT_YES) != 0;
+        if (!isNightMode) {
+            if (mSensorRect != null) {
+                canvas.drawOval(mSensorRect, mSensorPaint);
+            }
+        }
+        mFingerprintDrawable.draw(canvas);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+    }
+
+    @Override
+    public int getOpacity() {
+        return 0;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java
new file mode 100644
index 0000000..7563e73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * UDFPS animations that should be shown when authenticating via FingerprintManager, excluding
+ * keyguard.
+ */
+public class UdfpsAnimationFpmOther extends UdfpsAnimation {
+
+    UdfpsAnimationFpmOther(@NonNull Context context) {
+        super(context);
+    }
+
+    @Override
+    void updateColor() {
+
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        mFingerprintDrawable.draw(canvas);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+    }
+
+    @Override
+    public int getOpacity() {
+        return 0;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
new file mode 100644
index 0000000..3e46a65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.util.MathUtils;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+
+/**
+ * UDFPS animations that should be shown when authenticating on keyguard.
+ */
+public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiver,
+        StatusBarStateController.StateListener {
+
+    private static final String TAG = "UdfpsAnimationKeyguard";
+
+    @NonNull private final View mParent;
+    @NonNull private final Context mContext;
+    private final int mMaxBurnInOffsetX;
+    private final int mMaxBurnInOffsetY;
+
+    // AOD anti-burn-in offsets
+    private float mInterpolatedDarkAmount;
+    private float mBurnInOffsetX;
+    private float mBurnInOffsetY;
+
+    UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context,
+            @NonNull StatusBarStateController statusBarStateController) {
+        super(context);
+        mParent = parent;
+        mContext = context;
+
+        mMaxBurnInOffsetX = context.getResources()
+                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
+        mMaxBurnInOffsetY = context.getResources()
+                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
+
+        statusBarStateController.addCallback(this);
+    }
+
+    private void updateAodPositionAndColor() {
+        mBurnInOffsetX = MathUtils.lerp(0f,
+                getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
+                        - mMaxBurnInOffsetX,
+                mInterpolatedDarkAmount);
+        mBurnInOffsetY = MathUtils.lerp(0f,
+                getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
+                        - 0.5f * mMaxBurnInOffsetY,
+                mInterpolatedDarkAmount);
+        updateColor();
+        mParent.postInvalidate();
+    }
+
+    @Override
+    public void dozeTimeTick() {
+        updateAodPositionAndColor();
+    }
+
+    @Override
+    public void onDozeAmountChanged(float linear, float eased) {
+        mInterpolatedDarkAmount = eased;
+        updateAodPositionAndColor();
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        canvas.save();
+        canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
+        mFingerprintDrawable.draw(canvas);
+        canvas.restore();
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+    }
+
+    @Override
+    public int getOpacity() {
+        return 0;
+    }
+
+    @Override
+    public void updateColor() {
+        final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
+                R.attr.wallpaperTextColor);
+        final int ambientDisplayIconColor = Color.WHITE;
+        mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
+                ambientDisplayIconColor, mInterpolatedDarkAmount));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 1cafb4c..a2b2bea8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -81,6 +81,7 @@
     private final WindowManager mWindowManager;
     private final SystemSettings mSystemSettings;
     private final DelayableExecutor mFgExecutor;
+    private final StatusBarStateController mStatusBarStateController;
     // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
     // sensors, this, in addition to a lot of the code here, will be updated.
     @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -181,6 +182,7 @@
         mWindowManager = windowManager;
         mSystemSettings = systemSettings;
         mFgExecutor = fgExecutor;
+        mStatusBarStateController = statusBarStateController;
 
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
@@ -208,7 +210,6 @@
 
         mHbmSupported = !TextUtils.isEmpty(mHbmPath);
         mView.setHbmSupported(mHbmSupported);
-        statusBarStateController.addCallback(mView);
 
         // This range only consists of the minimum and maximum values, which only cover
         // non-high-brightness mode.
@@ -340,7 +341,7 @@
             if (!mIsOverlayShowing) {
                 try {
                     Log.v(TAG, "showUdfpsOverlay | adding window");
-                    mView.setShowReason(reason);
+                    mView.setUdfpsAnimation(getUdfpsAnimationForReason(reason));
                     mWindowManager.addView(mView, computeLayoutParams());
                     mView.setOnTouchListener(mOnTouchListener);
                     mIsOverlayShowing = true;
@@ -353,11 +354,27 @@
         });
     }
 
+    @Nullable
+    private UdfpsAnimation getUdfpsAnimationForReason(int reason) {
+        Log.d(TAG, "getUdfpsAnimationForReason: " + reason);
+        switch (reason) {
+            case IUdfpsOverlayController.REASON_ENROLL:
+                return new UdfpsAnimationEnroll(mContext);
+            case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
+                return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController);
+            case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
+                return new UdfpsAnimationFpmOther(mContext);
+            default:
+                Log.d(TAG, "Animation for reason " + reason + " not supported yet");
+                return null;
+        }
+    }
+
     private void hideUdfpsOverlay() {
         mFgExecutor.execute(() -> {
             if (mIsOverlayShowing) {
                 Log.v(TAG, "hideUdfpsOverlay | removing window");
-                mView.setShowReason(IUdfpsOverlayController.REASON_UNKNOWN);
+                mView.setUdfpsAnimation(null);
                 mView.setOnTouchListener(null);
                 // Reset the controller back to its starting state.
                 onFingerUp();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 033a355..4cb8101 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -16,45 +16,34 @@
 
 package com.android.systemui.biometrics;
 
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.MathUtils;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewTreeObserver;
 
-import com.android.internal.graphics.ColorUtils;
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 
 /**
  * A full screen view with a configurable illumination dot and scrim.
  */
-public class UdfpsView extends View implements DozeReceiver,
-        StatusBarStateController.StateListener {
+public class UdfpsView extends View implements DozeReceiver {
     private static final String TAG = "UdfpsView";
 
     // Values in pixels.
-    private static final float SENSOR_SHADOW_RADIUS = 2.0f;
-    private static final float SENSOR_OUTLINE_WIDTH = 2.0f;
+    public static final float SENSOR_SHADOW_RADIUS = 2.0f;
 
     private static final int DEBUG_TEXT_SIZE_PX = 32;
 
@@ -65,8 +54,7 @@
     @NonNull private final RectF mSensorRect;
     @NonNull private final Paint mSensorPaint;
     private final float mSensorTouchAreaCoefficient;
-    private final int mMaxBurnInOffsetX;
-    private final int mMaxBurnInOffsetY;
+
 
     // Stores rounded up values from mSensorRect. Necessary for APIs that only take Rect (not RecF).
     @NonNull private final Rect mTouchableRegion;
@@ -75,17 +63,11 @@
     // mInsetsListener to restrict the touchable region and allow the touches outside of the sensor
     // to propagate to the rest of the UI.
     @NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;
-    @NonNull private final Drawable mFingerprintDrawable;
+    @Nullable private UdfpsAnimation mUdfpsAnimation;
 
     // Used to obtain the sensor location.
     @NonNull private FingerprintSensorPropertiesInternal mSensorProps;
 
-    // AOD anti-burn-in offsets
-    private float mInterpolatedDarkAmount;
-    private float mBurnInOffsetX;
-    private float mBurnInOffsetY;
-
-    private int mShowReason;
     private boolean mShowScrimAndDot;
     private boolean mIsHbmSupported;
     @Nullable private String mDebugMessage;
@@ -110,10 +92,6 @@
             a.recycle();
         }
 
-        mMaxBurnInOffsetX = getResources()
-                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
-        mMaxBurnInOffsetY = getResources()
-                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
 
         mScrimRect = new Rect();
         mScrimPaint = new Paint(0 /* flags */);
@@ -131,8 +109,6 @@
         mDebugTextPaint.setColor(Color.BLUE);
         mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);
 
-        mFingerprintDrawable = getResources().getDrawable(R.drawable.ic_fingerprint, null);
-
         mTouchableRegion = new Rect();
         // When the device is rotated, it's important that mTouchableRegion is updated before
         // this listener is called. This listener is usually called shortly after onLayout.
@@ -149,39 +125,20 @@
         mSensorProps = properties;
     }
 
-    /**
-     * @param reason See {@link android.hardware.fingerprint.IUdfpsOverlayController}
-     */
-    void setShowReason(int reason) {
-        mShowReason = reason;
+    void setUdfpsAnimation(@Nullable UdfpsAnimation animation) {
+        mUdfpsAnimation = animation;
     }
 
+
     @Override
     public void dozeTimeTick() {
-        updateAodPositionAndColor();
-    }
-
-    @Override
-    public void onDozeAmountChanged(float linear, float eased) {
-        mInterpolatedDarkAmount = eased;
-        updateAodPositionAndColor();
-    }
-
-    private void updateAodPositionAndColor() {
-        mBurnInOffsetX = MathUtils.lerp(0f,
-                getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
-                        - mMaxBurnInOffsetX,
-                mInterpolatedDarkAmount);
-        mBurnInOffsetY = MathUtils.lerp(0f,
-                getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
-                        - 0.5f * mMaxBurnInOffsetY,
-                mInterpolatedDarkAmount);
-        updateColor();
-        postInvalidate();
+        if (mUdfpsAnimation instanceof DozeReceiver) {
+            ((DozeReceiver) mUdfpsAnimation).dozeTimeTick();
+        }
     }
 
     // The "h" and "w" are the display's height and width relative to its current rotation.
-    private void updateSensorRect(int h, int w) {
+    protected void updateSensorRect(int h, int w) {
         // mSensorProps coordinates assume portrait mode.
         mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
                 mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
@@ -202,12 +159,9 @@
                 // Do nothing to stay in portrait mode.
         }
 
-        int margin =  (int) (mSensorRect.bottom - mSensorRect.top) / 5;
-        mFingerprintDrawable.setBounds(
-                (int) mSensorRect.left + margin,
-                (int) mSensorRect.top + margin,
-                (int) mSensorRect.right - margin,
-                (int) mSensorRect.bottom - margin);
+        if (mUdfpsAnimation != null) {
+            mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect));
+        }
     }
 
     @Override
@@ -239,14 +193,8 @@
     }
 
     private void updateColor() {
-        if (mShowReason == IUdfpsOverlayController.REASON_AUTH) {
-            final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
-                    com.android.systemui.R.attr.wallpaperTextColor);
-            final int ambientDisplayIconColor = Color.WHITE;
-            mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
-                    ambientDisplayIconColor, mInterpolatedDarkAmount));
-        } else if (mShowReason == IUdfpsOverlayController.REASON_ENROLL) {
-            mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
+        if (mUdfpsAnimation != null) {
+            mUdfpsAnimation.updateColor();
         }
     }
 
@@ -266,9 +214,6 @@
             canvas.drawRect(mScrimRect, mScrimPaint);
         }
 
-        // Translation should affect everything but the scrim.
-        canvas.save();
-        canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
         if (!TextUtils.isEmpty(mDebugMessage)) {
             canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint);
         }
@@ -277,17 +222,11 @@
             // draw dot (white circle)
             canvas.drawOval(mSensorRect, mSensorPaint);
         } else {
-            final boolean isNightMode = (getResources().getConfiguration().uiMode
-                    & Configuration.UI_MODE_NIGHT_YES) != 0;
-            if (mShowReason == IUdfpsOverlayController.REASON_ENROLL && !isNightMode) {
-                canvas.drawOval(mSensorRect, mSensorPaint);
+            if (mUdfpsAnimation != null) {
+                mUdfpsAnimation.draw(canvas);
             }
-            // draw fingerprint icon
-            mFingerprintDrawable.draw(canvas);
         }
 
-        canvas.restore();
-
         if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) {
             post(mRunAfterShowingScrimAndDot);
             mRunAfterShowingScrimAndDot = null;
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 c2c4ad8..d7a3537 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -92,6 +92,10 @@
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
             "gestures.back_timeout", 250);
 
+    // Temporary log until b/176302696 is resolved
+    static final boolean DEBUG_MISSING_GESTURE = true;
+    static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
+
     private ISystemGestureExclusionListener mGestureExclusionListener =
             new ISystemGestureExclusionListener.Stub() {
                 @Override
@@ -223,8 +227,12 @@
             new NavigationEdgeBackPlugin.BackCallback() {
                 @Override
                 public void triggerBack() {
-                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
-                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+                    boolean sendDown = sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+                    boolean sendUp = sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+                    if (DEBUG_MISSING_GESTURE) {
+                        Log.d(DEBUG_MISSING_GESTURE_TAG, "Triggered back: down=" + sendDown
+                                + ", up=" + sendUp);
+                    }
 
                     mOverviewProxyService.notifyBackAction(true, (int) mDownPoint.x,
                             (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
@@ -694,6 +702,9 @@
                 if (action == MotionEvent.ACTION_POINTER_DOWN) {
                     if (mAllowGesture) {
                         logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_MULTI_TOUCH);
+                        if (DEBUG_MISSING_GESTURE) {
+                            Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back: multitouch");
+                        }
                         // We do not support multi touch for back gesture
                         cancelGesture(ev);
                     }
@@ -704,6 +715,12 @@
                         if (mAllowGesture) {
                             logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
                             cancelGesture(ev);
+                            if (DEBUG_MISSING_GESTURE) {
+                                Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back [longpress]: "
+                                        + ev.getEventTime()
+                                        + "  " + ev.getDownTime()
+                                        + "  " + mLongPressTimeout);
+                            }
                         }
                         mLogGesture = false;
                         return;
@@ -714,6 +731,10 @@
                         if (mAllowGesture) {
                             logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_VERTICAL_MOVE);
                             cancelGesture(ev);
+                            if (DEBUG_MISSING_GESTURE) {
+                                Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back [vertical move]: "
+                                        + dy + "  " + dx + "  " + mTouchSlop);
+                            }
                         }
                         mLogGesture = false;
                         return;
@@ -769,7 +790,7 @@
         }
     }
 
-    private void sendEvent(int action, int code) {
+    private boolean sendEvent(int action, int code) {
         long when = SystemClock.uptimeMillis();
         final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
                 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
@@ -777,7 +798,8 @@
                 InputDevice.SOURCE_KEYBOARD);
 
         ev.setDisplayId(mContext.getDisplay().getDisplayId());
-        InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+        return InputManager.getInstance()
+                .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
     }
 
     public void setInsets(int leftInset, int rightInset) {
@@ -803,6 +825,7 @@
         pw.println("  mEdgeWidthRight=" + mEdgeWidthRight);
         pw.println("  mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
         pw.println("  mPredictionLog=" + String.join(";", mPredictionLog));
+        pw.println("  mEdgeBackPlugin=" + mEdgeBackPlugin);
     }
 
     private boolean isGestureBlockingActivityRunning() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index fbbda5f..ac9f183 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -18,6 +18,9 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE;
+import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
+
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -29,6 +32,7 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.os.VibrationEffect;
+import android.util.Log;
 import android.util.MathUtils;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
@@ -461,6 +465,10 @@
                 handleMoveEvent(event);
                 break;
             case MotionEvent.ACTION_UP:
+                if (DEBUG_MISSING_GESTURE) {
+                    Log.d(DEBUG_MISSING_GESTURE_TAG,
+                            "NavigationBarEdgePanel ACTION_UP, mTriggerBack=" + mTriggerBack);
+                }
                 if (mTriggerBack) {
                     triggerBack();
                 } else {
@@ -471,6 +479,9 @@
                 mVelocityTracker = null;
                 break;
             case MotionEvent.ACTION_CANCEL:
+                if (DEBUG_MISSING_GESTURE) {
+                    Log.d(DEBUG_MISSING_GESTURE_TAG, "NavigationBarEdgePanel ACTION_CANCEL");
+                }
                 cancelBack();
                 mRegionSamplingHelper.stop();
                 mVelocityTracker.recycle();
@@ -661,6 +672,9 @@
         mAngleOffset = 0;
         mTranslationAnimation.setSpring(mRegularTranslationSpring);
         // Reset the arrow to the side
+        if (DEBUG_MISSING_GESTURE) {
+            Log.d(DEBUG_MISSING_GESTURE_TAG, "reset mTriggerBack=false");
+        }
         setTriggerBack(false /* triggerBack */, false /* animated */);
         setDesiredTranslation(0, false /* animated */);
         setCurrentTranslation(0);
@@ -696,6 +710,9 @@
             mDisappearAmount = 0.0f;
             setAlpha(1f);
             // And animate it go to back by default!
+            if (DEBUG_MISSING_GESTURE) {
+                Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=true");
+            }
             setTriggerBack(true /* triggerBack */, true /* animated */);
         }
 
@@ -736,6 +753,14 @@
         if (Math.abs(yOffset) > Math.abs(x - mStartX) * 2) {
             triggerBack = false;
         }
+        if (DEBUG_MISSING_GESTURE && mTriggerBack != triggerBack) {
+            Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=" + triggerBack
+                    + ", mTotalTouchDelta=" + mTotalTouchDelta
+                    + ", mMinDeltaForSwitch=" + mMinDeltaForSwitch
+                    + ", yOffset=" + yOffset
+                    + ", x=" + x
+                    + ", mStartX=" + mStartX);
+        }
         setTriggerBack(triggerBack, true /* animated */);
 
         if (!mTriggerBack) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 2dfac1b..fa1f7c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -146,7 +146,8 @@
         RecyclerView recyclerView = mView.getRecyclerView();
         recyclerView.setAdapter(mTileAdapter);
         mTileAdapter.getItemTouchHelper().attachToRecyclerView(recyclerView);
-        GridLayoutManager layout = new GridLayoutManager(getContext(), TileAdapter.NUM_COLUMNS) {
+        GridLayoutManager layout =
+                new GridLayoutManager(getContext(), mTileAdapter.getNumColumns()) {
             @Override
             public void onInitializeAccessibilityNodeInfoForItem(RecyclerView.Recycler recycler,
                     RecyclerView.State state, View host, AccessibilityNodeInfoCompat info) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 036fa86..507048c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -61,7 +61,6 @@
     private static final long DRAG_LENGTH = 100;
     private static final float DRAG_SCALE = 1.2f;
     public static final long MOVE_DURATION = 150;
-    public static final int NUM_COLUMNS = 4;
 
     private static final int TYPE_TILE = 0;
     private static final int TYPE_EDIT = 1;
@@ -99,6 +98,7 @@
     private final UiEventLogger mUiEventLogger;
     private final AccessibilityDelegateCompat mAccessibilityDelegate;
     private RecyclerView mRecyclerView;
+    private final int mNumColumns;
 
     @Inject
     public TileAdapter(Context context, QSTileHost qsHost, UiEventLogger uiEventLogger) {
@@ -109,6 +109,7 @@
         mDecoration = new TileItemDecoration(context);
         mMarginDecoration = new MarginTileDecoration();
         mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
+        mNumColumns = context.getResources().getInteger(R.integer.quick_settings_num_columns);
         mAccessibilityDelegate = new TileAdapterDelegate();
     }
 
@@ -122,6 +123,10 @@
         mRecyclerView = null;
     }
 
+    public int getNumColumns() {
+        return mNumColumns;
+    }
+
     public ItemTouchHelper getItemTouchHelper() {
         return mItemTouchHelper;
     }
@@ -602,7 +607,7 @@
         public int getSpanSize(int position) {
             final int type = getItemViewType(position);
             if (type == TYPE_EDIT || type == TYPE_DIVIDER || type == TYPE_HEADER) {
-                return NUM_COLUMNS;
+                return mNumColumns;
             } else {
                 return 1;
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index c052563..ed3cf9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -162,7 +162,7 @@
     @Test
     public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mFgExecutor.runAllReady();
         verify(mWindowManager).addView(eq(mUdfpsView), any());
     }
@@ -170,7 +170,7 @@
     @Test
     public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
         mFgExecutor.runAllReady();
         verify(mWindowManager).removeView(eq(mUdfpsView));
@@ -184,7 +184,7 @@
 
         // GIVEN that the overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mFgExecutor.runAllReady();
         // WHEN ACTION_DOWN is received
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -205,7 +205,7 @@
     public void aodInterrupt() throws RemoteException {
         // GIVEN that the overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mFgExecutor.runAllReady();
         // WHEN fingerprint is requested because of AOD interrupt
         mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
@@ -223,7 +223,7 @@
     public void cancelAodInterrupt() throws RemoteException {
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         // WHEN it is cancelled
@@ -236,7 +236,7 @@
     public void aodInterruptTimeout() throws RemoteException {
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
-                IUdfpsOverlayController.REASON_AUTH);
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         // WHEN it times out
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9aadcf8..b6232a0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -325,8 +325,6 @@
     private boolean mRestrictBackground;
 
     private final Context mContext;
-    // The Context is created for UserHandle.ALL.
-    private final Context mUserAllContext;
     private final Dependencies mDeps;
     // 0 is full bad, 100 is full good
     private int mDefaultInetConditionPublished = 0;
@@ -1162,8 +1160,8 @@
         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
 
-        mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
-        mUserAllContext.registerReceiver(
+        final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
+        userAllContext.registerReceiver(
                 mIntentReceiver,
                 intentFilter,
                 null /* broadcastPermission */,
@@ -1179,7 +1177,7 @@
         intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addDataScheme("package");
-        mUserAllContext.registerReceiver(
+        userAllContext.registerReceiver(
                 mIntentReceiver,
                 intentFilter,
                 null /* broadcastPermission */,
@@ -1188,7 +1186,7 @@
         // Listen to lockdown VPN reset.
         intentFilter = new IntentFilter();
         intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET);
-        mUserAllContext.registerReceiver(
+        userAllContext.registerReceiver(
                 mIntentReceiver, intentFilter, NETWORK_STACK, mHandler);
 
         mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNMS);
@@ -2352,7 +2350,7 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
             }
             try {
-                mUserAllContext.sendStickyBroadcast(intent, options);
+                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 780c026..7fe1ccc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6043,10 +6043,18 @@
                 abiOverride, zygotePolicyFlags);
     }
 
-    // TODO: Move to ProcessList?
     @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
             boolean disableHiddenApiChecks, String abiOverride, int zygotePolicyFlags) {
+        return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
+                false /* disableTestApiChecks */, abiOverride, zygotePolicyFlags);
+    }
+
+    // TODO: Move to ProcessList?
+    @GuardedBy("this")
+    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+            boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+            String abiOverride, int zygotePolicyFlags) {
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6081,7 +6089,7 @@
             mPersistentStartingProcesses.add(app);
             mProcessList.startProcessLocked(app, new HostingRecord("added application",
                     customProcess != null ? customProcess : app.processName),
-                    zygotePolicyFlags, disableHiddenApiChecks, abiOverride);
+                    zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks, abiOverride);
         }
 
         return app;
@@ -14398,10 +14406,11 @@
                     mUsageStatsService.reportEvent(ii.targetPackage, userId,
                             UsageEvents.Event.SYSTEM_INTERACTION);
                 }
-                app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, abiOverride,
-                        ZYGOTE_POLICY_FLAG_EMPTY);
+                app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
+                        disableTestApiChecks, abiOverride, ZYGOTE_POLICY_FLAG_EMPTY);
             }
 
+
             app.setActiveInstrumentation(activeInstr);
             activeInstr.mFinished = false;
             activeInstr.mSourceUid = callingUid;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1c98fd6..2273779 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1748,7 +1748,8 @@
      */
     @GuardedBy("mService")
     boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
-            int zygotePolicyFlags, boolean disableHiddenApiChecks, String abiOverride) {
+            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+            String abiOverride) {
         if (app.pendingStart) {
             return true;
         }
@@ -1888,6 +1889,10 @@
                     throw new IllegalStateException("Invalid API policy: " + policy);
                 }
                 runtimeFlags |= policyBits;
+
+                if (disableTestApiChecks) {
+                    runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
+                }
             }
 
             String useAppImageCache = SystemProperties.get(
@@ -2337,7 +2342,8 @@
     final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
             int zygotePolicyFlags, String abiOverride) {
         return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
-                false /* disableHiddenApiChecks */, abiOverride);
+                false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
+                abiOverride);
     }
 
     @GuardedBy("mService")
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 55ac248..d87af42 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -50,6 +50,7 @@
 import android.hardware.biometrics.PromptInfo;
 import android.hardware.biometrics.SensorProperties;
 import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.Binder;
 import android.os.Build;
 import android.os.RemoteException;
@@ -61,6 +62,7 @@
 
 import com.android.internal.R;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 
 import java.util.List;
@@ -478,4 +480,14 @@
                 throw new IllegalArgumentException("Unknown strength: " + strength);
         }
     }
+
+    public static int getUdfpsAuthReason(@NonNull AuthenticationClient<?> client) {
+        if (client.isKeyguard()) {
+            return IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD;
+        } else if (client.isBiometricPrompt()) {
+            return IUdfpsOverlayController.REASON_AUTH_BP;
+        } else {
+            return IUdfpsOverlayController.REASON_AUTH_FPM_OTHER;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 3f6ae64..14433fb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -53,6 +53,7 @@
     @Nullable private final TaskStackListener mTaskStackListener;
     private final LockoutTracker mLockoutTracker;
     private final boolean mIsRestricted;
+    private final boolean mIsKeyguard;
 
     protected final long mOperationId;
 
@@ -65,7 +66,7 @@
             int targetUserId, long operationId, boolean restricted, @NonNull String owner,
             int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
             int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
-            @NonNull LockoutTracker lockoutTracker) {
+            @NonNull LockoutTracker lockoutTracker, boolean isKeyguard) {
         super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
                 statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
         mIsStrongBiometric = isStrongBiometric;
@@ -75,6 +76,7 @@
         mTaskStackListener = taskStackListener;
         mLockoutTracker = lockoutTracker;
         mIsRestricted = restricted;
+        mIsKeyguard = isKeyguard;
     }
 
     public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
@@ -114,6 +116,10 @@
         return mIsRestricted;
     }
 
+    public boolean isKeyguard() {
+        return mIsKeyguard;
+    }
+
     @Override
     protected boolean isCryptoOperation() {
         return mOperationId != 0;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 80f337f..a7bfc4b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -67,11 +67,11 @@
             @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
             boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
             boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
-            @NonNull LockoutCache lockoutCache) {
+            @NonNull LockoutCache lockoutCache, boolean isKeyguard) {
         super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
                 owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
-                lockoutCache);
+                lockoutCache, isKeyguard);
         mUsageStats = usageStats;
         mLockoutCache = lockoutCache;
         mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 632cc4b..d60bb79 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -116,9 +116,9 @@
         try {
             // TODO(b/172593978): Pass features.
             // TODO(b/174619156): Handle accessibility enrollment.
-            mCancellationSignal = getFreshDaemon().enroll(mSequentialId, EnrollmentType.DEFAULT,
+            mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
                     HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
-                    mPreviewSurface);
+                    EnrollmentType.DEFAULT, new byte[0], mPreviewSurface);
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting enroll", e);
             onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 20318e3..f7feffd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -451,7 +451,7 @@
                         mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
                         operationId, restricted, opPackageName, cookie,
                         false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
-                        mUsageStats, mSensors.get(sensorId).getLockoutCache());
+                        mUsageStats, mSensors.get(sensorId).getLockoutCache(), isKeyguard);
                 mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
             } catch (RemoteException e) {
                 Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 9b00ba6..f49601a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -357,6 +357,16 @@
         }
 
         @Override
+        public void onFeaturesRetrieved(byte[] features, int enrollmentId) {
+
+        }
+
+        @Override
+        public void onFeatureSet(int enrollmentId, byte feature) {
+
+        }
+
+        @Override
         public void onEnrollmentsRemoved(int[] enrollmentIds) {
             mHandler.post(() -> {
                 final BaseClientMonitor client = mScheduler.getCurrentClient();
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
index dc1efa0..1d57073 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
@@ -49,8 +49,8 @@
             }
 
             @Override
-            public ICancellationSignal enroll(int cookie, byte enrollmentType,
-                    HardwareAuthToken hat, NativeHandle previewSurface) {
+            public ICancellationSignal enroll(int cookie, HardwareAuthToken hat,
+                    byte enrollmentType, byte[] features, NativeHandle previewSurface) {
                 return null;
             }
 
@@ -75,6 +75,17 @@
             }
 
             @Override
+            public void getFeatures(int cookie, int enrollmentId) {
+
+            }
+
+            @Override
+            public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId,
+                    byte feature, boolean enabled) {
+
+            }
+
+            @Override
             public void getAuthenticatorId(int cookie) {
 
             }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
index 189c726..23e6988 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
@@ -50,8 +50,8 @@
     }
 
     @Override
-    public ICancellationSignal enroll(int cookie, byte enrollmentType, HardwareAuthToken hat,
-            NativeHandle previewSurface) {
+    public ICancellationSignal enroll(int cookie, HardwareAuthToken hat, byte enrollmentType,
+            byte[] features, NativeHandle previewSurface) {
         return null;
     }
 
@@ -86,6 +86,17 @@
     }
 
     @Override
+    public void getFeatures(int cookie, int enrollmentId) {
+
+    }
+
+    @Override
+    public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId, byte feature,
+            boolean enabled) {
+
+    }
+
+    @Override
     public void getAuthenticatorId(int cookie) {
         Slog.d(TAG, "getAuthenticatorId");
         // Immediately return a value so the framework can continue with subsequent requests.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 7010d96..775d8d4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -646,7 +646,7 @@
             final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
                     mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
                     cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
-                    statsClient, mLockoutTracker, mUsageStats);
+                    statsClient, mLockoutTracker, mUsageStats, isKeyguard);
             mScheduler.scheduleClientMonitor(client);
         });
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 9dc8439..0b78dd0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -66,12 +66,12 @@
             @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
             @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
             boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
-            boolean isStrongBiometric, int statsClient,
-            @NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats) {
+            boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
+            @NonNull UsageStats usageStats, boolean isKeyguard) {
         super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
                 owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
-                lockoutTracker);
+                lockoutTracker, isKeyguard);
         mNotificationManager = context.getSystemService(NotificationManager.class);
         mUsageStats = usageStats;
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index bd57fea..f9527d9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -30,6 +30,7 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutCache;
@@ -58,11 +59,11 @@
             boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
             int sensorId, boolean isStrongBiometric, int statsClient,
             @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
-            @Nullable IUdfpsOverlayController udfpsOverlayController) {
+            @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
         super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
                 cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
-                lockoutCache);
+                lockoutCache, isKeyguard);
         mLockoutCache = lockoutCache;
         mUdfpsOverlayController = udfpsOverlayController;
     }
@@ -87,7 +88,7 @@
 
     @Override
     protected void startHalOperation() {
-        UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+        UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
                 mUdfpsOverlayController);
         try {
             mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index b4bb4f8..9611192 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -70,7 +70,8 @@
 
     @Override
     protected void startHalOperation() {
-        UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+        UdfpsHelper.showUdfpsOverlay(getSensorId(),
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
                 mUdfpsOverlayController);
         try {
             mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 727184f..f845024 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -466,7 +466,7 @@
                         operationId, restricted, opPackageName, cookie,
                         false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
                         mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
-                        mUdfpsOverlayController);
+                        mUdfpsOverlayController, isKeyguard);
                 mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
             } catch (RemoteException e) {
                 Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 589db6c..83a3d94 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -30,6 +30,7 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutTracker;
@@ -48,7 +49,6 @@
 
     private static final String TAG = "Biometrics/FingerprintAuthClient";
 
-    private final boolean mIsKeyguard;
     private final LockoutFrameworkImpl mLockoutFrameworkImpl;
     @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
 
@@ -63,10 +63,9 @@
         super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
                 owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
-                lockoutTracker);
+                lockoutTracker, isKeyguard);
         mLockoutFrameworkImpl = lockoutTracker;
         mUdfpsOverlayController = udfpsOverlayController;
-        mIsKeyguard = isKeyguard;
     }
 
     @Override
@@ -120,7 +119,7 @@
 
     @Override
     protected void startHalOperation() {
-        UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+        UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
                 mUdfpsOverlayController);
         try {
             // GroupId was never used. In fact, groupId is always the same as userId.
@@ -170,8 +169,4 @@
             }
         }
     }
-
-    public boolean isKeyguard() {
-        return mIsKeyguard;
-    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 6318139..7989dca 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -83,7 +83,8 @@
 
     @Override
     protected void startHalOperation() {
-        UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+        UdfpsHelper.showUdfpsOverlay(getSensorId(),
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
                 mUdfpsOverlayController);
         try {
             getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 425e3ab..bda4240 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -23,12 +23,17 @@
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.FontFileUtil;
 import android.graphics.fonts.SystemFonts;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.os.SharedMemory;
 import android.system.ErrnoException;
 import android.text.FontConfig;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.graphics.fonts.IFontManager;
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.security.FileIntegrityService;
@@ -38,6 +43,7 @@
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.nio.ByteBuffer;
 import java.nio.NioUtils;
 import java.nio.channels.FileChannel;
@@ -46,21 +52,25 @@
 
 /** A service for managing system fonts. */
 // TODO(b/173619554): Add API to update fonts.
-public final class FontManagerService {
-
+public final class FontManagerService extends IFontManager.Stub {
     private static final String TAG = "FontManagerService";
 
     // TODO: make this a DeviceConfig flag.
     private static final boolean ENABLE_FONT_UPDATES = false;
     private static final String FONT_FILES_DIR = "/data/fonts/files";
 
+    @Override
+    public FontConfig getFontConfig() throws RemoteException {
+        return getCurrentFontSettings().getSystemFontConfig();
+    }
+
     /** Class to manage FontManagerService's lifecycle. */
     public static final class Lifecycle extends SystemService {
         private final FontManagerService mService;
 
         public Lifecycle(@NonNull Context context) {
             super(context);
-            mService = new FontManagerService();
+            mService = new FontManagerService(context);
         }
 
         @Override
@@ -76,10 +86,11 @@
                             return mService.getCurrentFontSettings().getSerializedSystemFontMap();
                         }
                     });
+            publishBinderService(Context.FONT_SERVICE, mService);
         }
     }
 
-    private static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
+    /* package */ static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
         @Override
         public String getPostScriptName(File file) throws IOException {
             ByteBuffer buffer = mmap(file);
@@ -133,7 +144,8 @@
     @Nullable
     private SystemFontSettings mCurrentFontSettings = null;
 
-    private FontManagerService() {
+    private FontManagerService(Context context) {
+        mContext = context;
         mUpdatableFontDir = createUpdatableFontDir();
     }
 
@@ -148,8 +160,16 @@
                 new OtfFontFileParser(), new FsverityUtilImpl());
     }
 
+
     @NonNull
-    private SystemFontSettings getCurrentFontSettings() {
+    private final Context mContext;
+
+    @NonNull
+    public Context getContext() {
+        return mContext;
+    }
+
+    @NonNull /* package */ SystemFontSettings getCurrentFontSettings() {
         synchronized (FontManagerService.this) {
             if (mCurrentFontSettings == null) {
                 mCurrentFontSettings = SystemFontSettings.create(mUpdatableFontDir);
@@ -174,7 +194,22 @@
         }
     }
 
-    private static class SystemFontSettings {
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+            @Nullable String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
+        new FontManagerShellCommand(this).dumpAll(new IndentingPrintWriter(writer, "  "));
+    }
+
+    @Override
+    public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+            @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+            @NonNull String[] args) {
+        return new FontManagerShellCommand(this).exec(this,
+                in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args);
+    }
+
+    /* package */ static class SystemFontSettings {
         private final @NonNull SharedMemory mSerializedSystemFontMap;
         private final @NonNull FontConfig mSystemFontConfig;
         private final @NonNull Map<String, FontFamily[]> mSystemFallbackMap;
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
new file mode 100644
index 0000000..acb5826
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
@@ -0,0 +1,269 @@
+/*
+ * 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.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.fonts.Font;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.FontVariationAxis;
+import android.os.ShellCommand;
+import android.text.FontConfig;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.util.DumpUtils;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A shell command implementation of font service.
+ */
+public class FontManagerShellCommand extends ShellCommand {
+    private static final String TAG = "FontManagerShellCommand";
+
+    @NonNull private final FontManagerService mService;
+
+    FontManagerShellCommand(@NonNull FontManagerService service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        return execCommand(this, cmd);
+    }
+
+    @Override
+    public void onHelp() {
+        dumpHelp(getOutPrintWriter());
+    }
+
+    /* package */ void dumpAll(@NonNull IndentingPrintWriter w) {
+        final FontManagerService.SystemFontSettings settings = mService.getCurrentFontSettings();
+        dumpFontConfig(w, settings.getSystemFontConfig());
+    }
+
+    private void dumpSingleFontConfig(
+            @NonNull IndentingPrintWriter w,
+            @NonNull FontConfig.Font font
+    ) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("style = ");
+        sb.append(font.getStyle());
+        sb.append(", path = ");
+        sb.append(font.getFile().getAbsolutePath());
+        if (font.getTtcIndex() != 0) {
+            sb.append(", index = ");
+            sb.append(font.getTtcIndex());
+        }
+        if (!font.getFontVariationSettings().isEmpty()) {
+            sb.append(", axes = ");
+            sb.append(font.getFontVariationSettings());
+        }
+        if (font.getFontFamilyName() != null) {
+            sb.append(", fallback = ");
+            sb.append(font.getFontFamilyName());
+        }
+        w.println(sb.toString());
+
+        if (font.getOriginalFile() != null) {
+            w.increaseIndent();
+            w.println("Font is updated from " + font.getOriginalFile());
+            w.decreaseIndent();
+        }
+    }
+
+    private void dumpFontConfig(
+            @NonNull IndentingPrintWriter w,
+            @NonNull FontConfig fontConfig
+    ) {
+        // Dump named font family first.
+        List<FontConfig.FontFamily> families = fontConfig.getFontFamilies();
+
+        w.println("Named Font Families");
+        w.increaseIndent();
+        for (int i = 0; i < families.size(); ++i) {
+            final FontConfig.FontFamily family = families.get(i);
+
+            // Here, only dump the named family only.
+            if (family.getName() == null) continue;
+
+            w.println("Named Family (" + family.getName() + ")");
+            final List<FontConfig.Font> fonts = family.getFontList();
+            w.increaseIndent();
+            for (int j = 0; j < fonts.size(); ++j) {
+                dumpSingleFontConfig(w, fonts.get(j));
+            }
+            w.decreaseIndent();
+        }
+        w.decreaseIndent();
+
+        // Dump Fallback fonts.
+        w.println("Dump Fallback Families");
+        w.increaseIndent();
+        int c = 0;
+        for (int i = 0; i < families.size(); ++i) {
+            final FontConfig.FontFamily family = families.get(i);
+
+            // Skip named font family since they are already dumped.
+            if (family.getName() != null) continue;
+
+            StringBuilder sb = new StringBuilder("Fallback Family [");
+            sb.append(c++);
+            sb.append("]: lang=\"");
+            sb.append(family.getLocaleList().toLanguageTags());
+            if (family.getVariant() != FontConfig.FontFamily.VARIANT_DEFAULT) {
+                sb.append("\", variant=");
+                switch (family.getVariant()) {
+                    case FontConfig.FontFamily.VARIANT_COMPACT:
+                        sb.append("Compact");
+                        break;
+                    case FontConfig.FontFamily.VARIANT_ELEGANT:
+                        sb.append("Elegant");
+                        break;
+                    default:
+                        sb.append("Unknown");
+                        break;
+                }
+            }
+            w.println(sb.toString());
+
+            final List<FontConfig.Font> fonts = family.getFontList();
+            w.increaseIndent();
+            for (int j = 0; j < fonts.size(); ++j) {
+                dumpSingleFontConfig(w, fonts.get(j));
+            }
+            w.decreaseIndent();
+        }
+        w.decreaseIndent();
+
+        // Dump aliases
+        w.println("Dump Family Aliases");
+        w.increaseIndent();
+        List<FontConfig.Alias> aliases = fontConfig.getAliases();
+        for (int i = 0; i < aliases.size(); ++i) {
+            final FontConfig.Alias alias = aliases.get(i);
+            w.println("alias = " + alias.getName() + ", reference = " + alias.getOriginal()
+                    + ", width = " + alias.getWeight());
+        }
+        w.decreaseIndent();
+    }
+
+    private static void dumpHelp(@NonNull PrintWriter w) {
+        w.println("Font service (font) commands");
+        w.println("help");
+        w.println("    Print this help text.");
+        w.println();
+        w.println("dump [family name]");
+        w.println("    Dump all font files in the specified family name.");
+        w.println("    Dump current system font configuration if no family name was specified.");
+    }
+
+    private void dumpFallback(@NonNull IndentingPrintWriter writer,
+            @NonNull FontFamily[] families) {
+        for (FontFamily family : families) {
+            dumpFamily(writer, family);
+        }
+    }
+
+    private void dumpFamily(@NonNull IndentingPrintWriter writer, @NonNull FontFamily family) {
+        StringBuilder sb = new StringBuilder("Family:");
+        if (family.getLangTags() != null) {
+            sb.append(" langTag = ");
+            sb.append(family.getLangTags());
+        }
+        if (family.getVariant() != FontConfig.FontFamily.VARIANT_DEFAULT) {
+            sb.append(" variant = ");
+            switch (family.getVariant()) {
+                case FontConfig.FontFamily.VARIANT_COMPACT:
+                    sb.append("Compact");
+                    break;
+                case FontConfig.FontFamily.VARIANT_ELEGANT:
+                    sb.append("Elegant");
+                    break;
+                default:
+                    sb.append("UNKNOWN");
+                    break;
+            }
+
+        }
+        writer.println(sb.toString());
+        for (int i = 0; i < family.getSize(); ++i) {
+            writer.increaseIndent();
+            try {
+                dumpFont(writer, family.getFont(i));
+            } finally {
+                writer.decreaseIndent();
+            }
+        }
+    }
+
+    private void dumpFont(@NonNull IndentingPrintWriter writer, @NonNull Font font) {
+        File file = font.getFile();
+        StringBuilder sb = new StringBuilder();
+        sb.append(font.getStyle());
+        sb.append(", path = ");
+        sb.append(file == null ? "[Not a file]" : file.getAbsolutePath());
+        if (font.getTtcIndex() != 0) {
+            sb.append(", index = ");
+            sb.append(font.getTtcIndex());
+        }
+        FontVariationAxis[] axes = font.getAxes();
+        if (axes != null && axes.length != 0) {
+            sb.append(", axes = \"");
+            sb.append(FontVariationAxis.toFontVariationSettings(axes));
+            sb.append("\"");
+        }
+        writer.println(sb.toString());
+    }
+
+    private int execCommand(@NonNull ShellCommand shell, @NonNull String cmd) {
+        final Context ctx = mService.getContext();
+        if (cmd == null) {
+            return shell.handleDefaultCommands(null);
+        }
+
+        final FontManagerService.SystemFontSettings settings = mService.getCurrentFontSettings();
+
+        switch (cmd) {
+            case "dump":
+                if (!DumpUtils.checkDumpPermission(ctx, TAG, shell.getErrPrintWriter())) {
+                    return 1;
+                }
+                final IndentingPrintWriter writer =
+                        new IndentingPrintWriter(shell.getOutPrintWriter(), "  ");
+                String nextArg = shell.getNextArg();
+                if (nextArg == null) {
+                    dumpFontConfig(writer, settings.getSystemFontConfig());
+                } else {
+                    final Map<String, FontFamily[]> fallbackMap = settings.getSystemFallbackMap();
+                    FontFamily[] families = fallbackMap.get(nextArg);
+                    if (families == null) {
+                        writer.println("Font Family \"" + nextArg + "\" not found");
+                    } else {
+                        dumpFallback(writer, families);
+                    }
+                }
+                return 0;
+            default:
+                shell.handleDefaultCommands(cmd);
+        }
+        return 0;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 35653f9..285145a 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -277,7 +277,8 @@
         @interface Phase {}
 
         /**
-         * Stops once we are done with preferred display calculation.
+         * Stops once we are done with preferred display calculation. The result returned from this
+         * phase is only guaranteed to have a display area which display is the launch display.
          */
         int PHASE_DISPLAY = 0;
 
@@ -287,9 +288,14 @@
         int PHASE_WINDOWING_MODE = 1;
 
         /**
+         * Stops once we are done with display area calculation.
+         */
+        int PHASE_DISPLAY_AREA = 2;
+
+        /**
          * Stops once we are done with window bounds calculation.
          */
-        int PHASE_BOUNDS = 2;
+        int PHASE_BOUNDS = 3;
 
         /**
          * Returns the launch params that the provided activity launch params should be overridden
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 12f8611..37a73fc 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -89,6 +89,8 @@
     private final Rect mTmpStableBounds = new Rect();
     private final int[] mTmpDirections = new int[2];
 
+    private TaskDisplayArea mTmpDisplayArea;
+
     private StringBuilder mLogBuilder;
 
     TaskLaunchParamsModifier(ActivityTaskSupervisor supervisor) {
@@ -127,15 +129,15 @@
             return RESULT_SKIP;
         }
 
-        // STEP 1: Determine the display area to launch the activity/task.
-        final TaskDisplayArea taskDisplayArea = getPreferredLaunchTaskDisplayArea(task,
+        // STEP 1: Determine the suggested display area to launch the activity/task.
+        final TaskDisplayArea suggestedDisplayArea = getPreferredLaunchTaskDisplayArea(task,
                 options, source, currentParams, activity, request);
-        outParams.mPreferredTaskDisplayArea = taskDisplayArea;
-        // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
-        final DisplayContent display = taskDisplayArea.mDisplayContent;
+        outParams.mPreferredTaskDisplayArea = suggestedDisplayArea;
+        final DisplayContent display = suggestedDisplayArea.mDisplayContent;
         if (DEBUG) {
-            appendLog("task-display-area=" + outParams.mPreferredTaskDisplayArea
-                    + " display-area-windowing-mode=" + taskDisplayArea.getWindowingMode());
+            appendLog("display-id=" + display.getDisplayId()
+                    + " display-windowing-mode=" + display.getWindowingMode()
+                    + " suggested-display-area=" + suggestedDisplayArea);
         }
 
         if (phase == PHASE_DISPLAY) {
@@ -204,9 +206,11 @@
         // We inherit launch params from previous modifiers or LaunchParamsController if options,
         // layout and display conditions are not contradictory to their suggestions. It's important
         // to carry over their values because LaunchParamsController doesn't automatically do that.
+        // We only check if display matches because display area can be changed later.
         if (!currentParams.isEmpty() && !hasInitialBounds
                 && (currentParams.mPreferredTaskDisplayArea == null
-                    || currentParams.mPreferredTaskDisplayArea == taskDisplayArea)) {
+                    || currentParams.mPreferredTaskDisplayArea.getDisplayId()
+                        == display.getDisplayId())) {
             // Only set windowing mode if display is in freeform. If the display is in fullscreen
             // mode we should only launch a task in fullscreen mode.
             if (currentParams.hasWindowingMode() && display.inFreeformWindowingMode()) {
@@ -255,14 +259,48 @@
             return RESULT_CONTINUE;
         }
 
-        // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
+        // STEP 3: Finalize the display area. Here we allow WM shell route all launches that match
+        // certain criteria to specific task display areas.
+        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
+                : display.getWindowingMode();
+        TaskDisplayArea taskDisplayArea = suggestedDisplayArea;
+        // If launch task display area is set in options we should just use it. We assume the
+        // suggestedDisplayArea has the right one in this case.
+        if (options == null || options.getLaunchTaskDisplayArea() == null) {
+            final int activityType =
+                    mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task);
+            display.forAllTaskDisplayAreas(displayArea -> {
+                final Task launchRoot = displayArea.getLaunchRootTask(
+                        resolvedMode, activityType, null /* ActivityOptions */);
+                if (launchRoot == null) {
+                    return false;
+                }
+                mTmpDisplayArea = displayArea;
+                return true;
+            });
+            if (mTmpDisplayArea != null) {
+                taskDisplayArea = mTmpDisplayArea;
+                mTmpDisplayArea = null;
+                appendLog("overridden-display-area=["
+                        + WindowConfiguration.activityTypeToString(activityType) + ", "
+                        + WindowConfiguration.windowingModeToString(resolvedMode) + ", "
+                        + taskDisplayArea + "]");
+            }
+        }
+        appendLog("display-area=" + taskDisplayArea);
+        outParams.mPreferredTaskDisplayArea = taskDisplayArea;
+
+        if (phase == PHASE_DISPLAY_AREA) {
+            return RESULT_CONTINUE;
+        }
+        // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
+
+        // STEP 4: Determine final launch bounds based on resolved windowing mode and activity
         // requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
         // for all other windowing modes that's not freeform mode. One can read comments in
         // relevant methods to further understand this step.
         //
         // We skip making adjustments if the params are fully resolved from previous results.
-        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
-                : display.getWindowingMode();
         if (fullyResolvedCurrentParam) {
             if (resolvedMode == WINDOWING_MODE_FREEFORM) {
                 // Make sure bounds are in the display if it's possibly in a different display/area.
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 832f918..90ce6cb 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -34,7 +34,6 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
-import android.util.proto.ProtoOutputStream;
 
 import androidx.annotation.NonNull;
 import androidx.test.InstrumentationRegistry;
@@ -279,7 +278,8 @@
             super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
                     false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
                     TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
-                    0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class));
+                    0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
+                    false /* isKeyguard */);
         }
 
         @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 9c1e8ed..4984799 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -32,6 +33,7 @@
 import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;
 
 import static com.android.server.wm.ActivityStarter.Request;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
@@ -109,9 +111,9 @@
         assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setActivity(null).calculate());
     }
 
-    // =============================
-    // Display ID Related Tests
-    // =============================
+    // =======================
+    // Display Related Tests
+    // =======================
     @Test
     public void testDefaultToPrimaryDisplayArea() {
         createNewDisplayContent(WINDOWING_MODE_FREEFORM);
@@ -287,7 +289,7 @@
         when(mActivity.getProcessName()).thenReturn(processName);
         when(mActivity.getUid()).thenReturn(uid);
         doReturn(controller)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(processName, uid);
 
         assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -308,11 +310,11 @@
         when(mActivity.getProcessName()).thenReturn(processName);
         when(mActivity.getUid()).thenReturn(uid);
         doReturn(null)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(processName, uid);
 
         doReturn(controller)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
         assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -340,10 +342,10 @@
                 .thenReturn(expectedTaskDisplayArea);
 
         doReturn(controllerForApplication)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(processName, uid);
         doReturn(controllerForLaunching)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
         assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -365,15 +367,15 @@
         when(controller.getTopActivityDisplayArea()).thenReturn(expectedTaskDisplayArea);
 
         doReturn(null)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);
 
         doReturn(null)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
         doReturn(controller)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(request.realCallingPid, request.realCallingUid);
 
         assertEquals(RESULT_CONTINUE,
@@ -385,11 +387,11 @@
     @Test
     public void testUsesDefaultDisplayAreaIfWindowProcessControllerIsNotPresent() {
         doReturn(null)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);
 
         doReturn(null)
-                .when(mSupervisor.mService)
+                .when(mAtm)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
         assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -397,6 +399,80 @@
         assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId());
     }
 
+    @Test
+    public void testOverridesDisplayAreaWithStandardTypeAndFullscreenMode() {
+        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+        launchRoot.mCreatedByOrganizer = true;
+
+        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+                new int[] { ACTIVITY_TYPE_STANDARD });
+
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
+    public void testOverridesDisplayAreaWithHomeTypeAndFullscreenMode() {
+        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+        launchRoot.mCreatedByOrganizer = true;
+
+        mActivity.setActivityType(ACTIVITY_TYPE_HOME);
+        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+                new int[] { ACTIVITY_TYPE_HOME });
+
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
+    public void testOverridesDisplayAreaWithStandardTypeAndFreeformMode() {
+        final TestDisplayContent freeformDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FREEFORM);
+        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(freeformDisplay,
+                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+        launchRoot.mCreatedByOrganizer = true;
+
+        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FREEFORM },
+                new int[] { ACTIVITY_TYPE_STANDARD });
+
+        mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
+    public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() {
+        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+        launchRoot.mCreatedByOrganizer = true;
+
+        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+                new int[] { ACTIVITY_TYPE_STANDARD });
+
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchTaskDisplayArea(
+                mDefaultDisplay.getDefaultTaskDisplayArea().mRemoteToken.toWindowContainerToken());
+
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
+
+        assertEquals(
+                mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
+    }
+
     // =====================================
     // Launch Windowing Mode Related Tests
     // =====================================
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 26de11a..b1e6683 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -1170,6 +1170,12 @@
                 return "DEVICE_SHUTDOWN";
             case Event.DEVICE_STARTUP:
                 return "DEVICE_STARTUP";
+            case Event.USER_UNLOCKED:
+                return "USER_UNLOCKED";
+            case Event.USER_STOPPED:
+                return "USER_STOPPED";
+            case Event.LOCUS_ID_SET:
+                return "LOCUS_ID_SET";
             default:
                 return "UNKNOWN_TYPE_" + eventType;
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 9f203e1..a5fea34 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -238,7 +238,6 @@
 
         private boolean mSafeMode;
         private int mCurUser;
-        private boolean mCurUserUnlocked;
         private boolean mCurUserSupported;
 
         @GuardedBy("this")
@@ -494,7 +493,6 @@
             FgThread.getHandler().post(() -> {
                 synchronized (this) {
                     setCurrentUserLocked(userHandle);
-                    mCurUserUnlocked = false;
                     switchImplementationIfNeededLocked(false);
                 }
             });
@@ -585,53 +583,43 @@
         VoiceInteractionServiceInfo findAvailInteractor(int userHandle, String packageName) {
             List<ResolveInfo> available =
                     mContext.getPackageManager().queryIntentServicesAsUser(
-                            new Intent(VoiceInteractionService.SERVICE_INTERFACE),
-                            PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                                    | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userHandle);
+                            new Intent(VoiceInteractionService.SERVICE_INTERFACE)
+                                    .setPackage(packageName),
+                            PackageManager.GET_META_DATA
+                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
             int numAvailable = available.size();
-
             if (numAvailable == 0) {
                 Slog.w(TAG, "no available voice interaction services found for user " + userHandle);
                 return null;
-            } else {
-                // Find first system package.  We never want to allow third party services to
-                // be automatically selected, because those require approval of the user.
-                VoiceInteractionServiceInfo foundInfo = null;
-                for (int i=0; i<numAvailable; i++) {
-                    ServiceInfo cur = available.get(i).serviceInfo;
-                    if ((cur.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
-                        ComponentName comp = new ComponentName(cur.packageName, cur.name);
-                        try {
-                            VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo(
-                                    mContext.getPackageManager(), comp, userHandle);
-                            if (info.getParseError() == null) {
-                                if (packageName == null || info.getServiceInfo().packageName.equals(
-                                        packageName)) {
-                                    if (foundInfo == null) {
-                                        foundInfo = info;
-                                    } else {
-                                        Slog.w(TAG, "More than one voice interaction service, "
-                                                + "picking first "
-                                                + new ComponentName(
-                                                        foundInfo.getServiceInfo().packageName,
-                                                        foundInfo.getServiceInfo().name)
-                                                + " over "
-                                                + new ComponentName(cur.packageName, cur.name));
-                                    }
-                                }
-                            } else {
-                                Slog.w(TAG, "Bad interaction service " + comp + ": "
-                                        + info.getParseError());
-                            }
-                        } catch (PackageManager.NameNotFoundException e) {
-                            Slog.w(TAG, "Failure looking up interaction service " + comp);
-                        }
-                    }
-                }
-
-                return foundInfo;
             }
+            // Find first system package.  We never want to allow third party services to
+            // be automatically selected, because those require approval of the user.
+            VoiceInteractionServiceInfo foundInfo = null;
+            for (int i = 0; i < numAvailable; i++) {
+                ServiceInfo cur = available.get(i).serviceInfo;
+                if ((cur.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    continue;
+                }
+                VoiceInteractionServiceInfo info =
+                        new VoiceInteractionServiceInfo(mContext.getPackageManager(), cur);
+                if (info.getParseError() != null) {
+                    Slog.w(TAG,
+                            "Bad interaction service " + cur.packageName + "/"
+                                    + cur.name + ": " + info.getParseError());
+                } else if (foundInfo == null) {
+                    foundInfo = info;
+                } else {
+                    Slog.w(TAG, "More than one voice interaction service, "
+                            + "picking first "
+                            + new ComponentName(
+                            foundInfo.getServiceInfo().packageName,
+                            foundInfo.getServiceInfo().name)
+                            + " over "
+                            + new ComponentName(cur.packageName, cur.name));
+                }
+            }
+            return foundInfo;
         }
 
         ComponentName getCurInteractor(int userHandle) {
@@ -661,7 +649,6 @@
                             PackageManager.MATCH_DIRECT_BOOT_AWARE
                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
             int numAvailable = available.size();
-
             if (numAvailable == 0) {
                 Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
                 return null;
@@ -1458,7 +1445,6 @@
                 pw.println("  mEnableService: " + mEnableService);
                 pw.println("  mTemporarilyDisabled: " + mTemporarilyDisabled);
                 pw.println("  mCurUser: " + mCurUser);
-                pw.println("  mCurUserUnlocked: " + mCurUserUnlocked);
                 pw.println("  mCurUserSupported: " + mCurUserSupported);
                 dumpSupportedUsers(pw, "  ");
                 mDbHelper.dump(pw);
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 03c2ef9..484c318 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -283,6 +283,8 @@
          *
          * @param cid The identifier of the data call which is provided in {@link DataCallResponse}
          * @param callback The result callback for this request.
+         *
+         * @hide
          */
         public void startHandover(int cid, @NonNull DataServiceCallback callback) {
             // The default implementation is to return unsupported.
@@ -303,6 +305,8 @@
          *
          * @param cid The identifier of the data call which is provided in {@link DataCallResponse}
          * @param callback The result callback for this request.
+         *
+         * @hide
          */
         public void cancelHandover(int cid, @NonNull DataServiceCallback callback) {
             // The default implementation is to return unsupported.
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index f56c19b..ca1f861 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -191,6 +191,8 @@
      * Called to indicate result for the request {@link DataService#startHandover}.
      *
      * @param result The result code. Must be one of the {@link ResultCode}
+     *
+     * @hide
      */
     public void onHandoverStarted(@ResultCode int result) {
         if (mCallback != null) {
@@ -209,6 +211,8 @@
      * Called to indicate result for the request {@link DataService#cancelHandover}.
      *
      * @param result The result code. Must be one of the {@link ResultCode}
+     *
+     * @hide
      */
     public void onHandoverCancelled(@ResultCode int result) {
         if (mCallback != null) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index a625dfd..1d69fe4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.close
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
@@ -50,6 +51,7 @@
  * Test app closes by pressing back button
  * To run this test: `atest FlickerTests:CloseAppBackButtonTest`
  */
+@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -93,7 +95,7 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
-                            visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173684672)
 
                             launcherReplacesAppWindowAsTopWindow(testApp)
                             wallpaperWindowBecomesVisible()
@@ -110,7 +112,7 @@
                                 enabled = !configuration.startRotation.isRotated())
                             navBarLayerIsAlwaysVisible()
                             statusBarLayerIsAlwaysVisible()
-                            visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173684672)
 
                             wallpaperLayerReplacesAppLayer(testApp)
                         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index e88b10b..f1d08c2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.close
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
@@ -49,6 +50,7 @@
  * Test app closes by pressing home button.
  * To run this test: `atest FlickerTests:CloseAppHomeButtonTest`
  */
+@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -92,7 +94,7 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
-                            visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173689015)
 
                             launcherReplacesAppWindowAsTopWindow(testApp)
                             wallpaperWindowBecomesVisible()
@@ -108,7 +110,7 @@
                                 Surface.ROTATION_0, enabled = isRotation0)
                             navBarLayerIsAlwaysVisible()
                             statusBarLayerIsAlwaysVisible()
-                            visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173689015)
 
                             wallpaperLayerReplacesAppLayer(testApp)
                         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index e47e757..7911119 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
@@ -38,6 +39,7 @@
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -51,6 +53,7 @@
  * Test IME window opening transitions.
  * To run this test: `atest FlickerTests:ReOpenImeWindowTest`
  */
+@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -109,9 +112,11 @@
                             layersTrace {
                                 noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation)
                                 navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
+                                        configuration.endRotation,
+                                        enabled = !configuration.startRotation.isRotated())
                                 statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
+                                        configuration.endRotation,
+                                        enabled = !configuration.startRotation.isRotated())
                                 statusBarLayerIsAlwaysVisible()
                                 navBarLayerIsAlwaysVisible()
                                 visibleLayersShownMoreThanOneConsecutiveEntry()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 3c8f469..c957b3f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
@@ -52,6 +53,7 @@
  * Launch an app from the recents app view (the overview)
  * To run this test: `atest FlickerTests:OpenAppFromOverviewTest`
  */
+@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)