Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/Android.bp b/Android.bp
index aae78a0..b620634 100644
--- a/Android.bp
+++ b/Android.bp
@@ -568,6 +568,7 @@
         "libcore-platform-compat-config",
         "services-platform-compat-config",
         "documents-ui-compat-config",
+        "calendar-provider-compat-config",
     ],
     libs: ["framework-updatable-stubs-module_libs_api"],
     static_libs: [
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d642f21..3ca5f0d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -732,6 +732,10 @@
     public static final int SAMPLING_STRATEGY_BOOT_TIME_SAMPLING =
             FrameworkStatsLog.RUNTIME_APP_OP_ACCESS__SAMPLING_STRATEGY__BOOT_TIME_SAMPLING;
 
+    /** @hide */
+    public static final int SAMPLING_STRATEGY_UNIFORM_OPS =
+            FrameworkStatsLog.RUNTIME_APP_OP_ACCESS__SAMPLING_STRATEGY__UNIFORM_OPS;
+
     /**
      * Strategies used for message sampling
      * @hide
@@ -741,7 +745,8 @@
             SAMPLING_STRATEGY_DEFAULT,
             SAMPLING_STRATEGY_UNIFORM,
             SAMPLING_STRATEGY_RARELY_USED,
-            SAMPLING_STRATEGY_BOOT_TIME_SAMPLING
+            SAMPLING_STRATEGY_BOOT_TIME_SAMPLING,
+            SAMPLING_STRATEGY_UNIFORM_OPS
     })
     public @interface SamplingStrategy {}
 
@@ -8350,7 +8355,7 @@
      * @hide
      */
     private static boolean isCollectingStackTraces() {
-        if (sConfig.getSampledOpCode() == OP_NONE &&
+        if (sConfig.getSampledOpCode() == OP_NONE && sConfig.getAcceptableLeftDistance() == 0 &&
                 sConfig.getExpirationTimeSinceBootMillis() >= SystemClock.elapsedRealtime()) {
             return false;
         }
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 4b0d2f8..bca6f39 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -175,14 +175,33 @@
  *
  * Caching can be disabled completely by initializing {@code sEnabled} to false and rebuilding.
  *
+ * To test a binder cache, create one or more tests that exercise the binder method.  This
+ * should be done twice: once with production code and once with a special image that sets
+ * {@code DEBUG} and {@code VERIFY} true.  In the latter case, verify that no cache
+ * inconsistencies are reported.  If a cache inconsistency is reported, however, it might be a
+ * false positive.  This happens if the server side data can be read and written non-atomically
+ * with respect to cache invalidation.
+ *
  * @param <Query> The class used to index cache entries: must be hashable and comparable
  * @param <Result> The class holding cache entries; use a boxed primitive if possible
  *
  * {@hide}
  */
 public abstract class PropertyInvalidatedCache<Query, Result> {
-    private static final long NONCE_UNSET = 0;
-    private static final long NONCE_DISABLED = -1;
+    /**
+     * Reserved nonce values.  The code is written assuming that these
+     * values are contiguous.
+     */
+    private static final int NONCE_UNSET = 0;
+    private static final int NONCE_DISABLED = 1;
+    private static final int NONCE_CORKED = 2;
+    private static final int NONCE_RESERVED = NONCE_CORKED + 1;
+
+    /**
+     * The names of the nonces
+     */
+    private static final String[] sNonceName =
+            new String[]{ "unset", "disabled", "corked" };
 
     private static final String TAG = "PropertyInvalidatedCache";
     private static final boolean DEBUG = false;
@@ -195,11 +214,28 @@
     @GuardedBy("mLock")
     private long mMisses = 0;
 
+    @GuardedBy("mLock")
+    private long mMissDisabled[] = new long[]{ 0, 0, 0 };
+
+    @GuardedBy("mLock")
+    private long mMissOverflow = 0;
+
+    @GuardedBy("mLock")
+    private long mHighWaterMark = 0;
+
     // Most invalidation is done in a static context, so the counters need to be accessible.
     @GuardedBy("sCorkLock")
     private static final HashMap<String, Long> sInvalidates = new HashMap<>();
 
     /**
+     * Record the number of invalidate or cork calls that were nops because
+     * the cache was already corked.  This is static because invalidation is
+     * done in a static context.
+     */
+    @GuardedBy("sCorkLock")
+    private static final HashMap<String, Long> sCorkedInvalidates = new HashMap<>();
+
+    /**
      * If sEnabled is false then all cache operations are stubbed out.  Set
      * it to false inside test processes.
      */
@@ -271,7 +307,15 @@
             true /* LRU access order */) {
                 @Override
                 protected boolean removeEldestEntry(Map.Entry eldest) {
-                    return size() > maxEntries;
+                    final int size = size();
+                    if (size > mHighWaterMark) {
+                        mHighWaterMark = size;
+                    }
+                    if (size > maxEntries) {
+                        mMissOverflow++;
+                        return true;
+                    }
+                    return false;
                 }
             };
         synchronized (sCorkLock) {
@@ -363,14 +407,21 @@
         // Let access to mDisabled race: it's atomic anyway.
         long currentNonce = (!isDisabledLocal()) ? getCurrentNonce() : NONCE_DISABLED;
         for (;;) {
-            if (currentNonce == NONCE_DISABLED || currentNonce == NONCE_UNSET) {
+            if (currentNonce == NONCE_DISABLED || currentNonce == NONCE_UNSET ||
+                currentNonce == NONCE_CORKED) {
+                if (!mDisabled) {
+                    // Do not bother collecting statistics if the cache is
+                    // locally disabled.
+                    synchronized (mLock) {
+                        mMissDisabled[(int) currentNonce]++;
+                    }
+                }
+
                 if (DEBUG) {
                     if (!mDisabled) {
                         Log.d(TAG, String.format(
                             "cache %s %s for %s",
-                            cacheName(),
-                            currentNonce == NONCE_DISABLED ? "disabled" : "unset",
-                            queryToString(query)));
+                            cacheName(), sNonceName[(int) currentNonce], queryToString(query)));
                     }
                 }
                 return recompute(query);
@@ -383,10 +434,10 @@
                     if (cachedResult != null) mHits++;
                 } else {
                     if (DEBUG) {
-                        Log.d(TAG,
-                                String.format("clearing cache %s because nonce changed [%s] -> [%s]",
-                                        cacheName(),
-                                        mLastSeenNonce, currentNonce));
+                        Log.d(TAG, String.format(
+                            "clearing cache %s of %d entries because nonce changed [%s] -> [%s]",
+                            cacheName(), mCache.size(),
+                            mLastSeenNonce, currentNonce));
                     }
                     mCache.clear();
                     mLastSeenNonce = currentNonce;
@@ -517,6 +568,8 @@
                 if (DEBUG) {
                     Log.d(TAG, "ignoring invalidation due to cork: " + name);
                 }
+                final long count = sCorkedInvalidates.getOrDefault(name, (long) 0);
+                sCorkedInvalidates.put(name, count + 1);
                 return;
             }
             invalidateCacheLocked(name);
@@ -538,7 +591,7 @@
         long newValue;
         do {
             newValue = NoPreloadHolder.next();
-        } while (newValue == NONCE_UNSET || newValue == NONCE_DISABLED);
+        } while (newValue >= 0 && newValue < NONCE_RESERVED);
         final String newValueString = Long.toString(newValue);
         if (DEBUG) {
             Log.d(TAG,
@@ -567,13 +620,21 @@
      * @param name Name of the cache-key property to cork
      */
     public static void corkInvalidations(@NonNull String name) {
+        if (!sEnabled) {
+            if (DEBUG) {
+                Log.w(TAG, String.format(
+                    "cache cork %s suppressed", name));
+            }
+            return;
+        }
+
         synchronized (sCorkLock) {
             int numberCorks = sCorks.getOrDefault(name, 0);
             if (DEBUG) {
                 Log.d(TAG, String.format("corking %s: numberCorks=%s", name, numberCorks));
             }
 
-            // If we're the first ones to cork this cache, set the cache to the unset state so
+            // If we're the first ones to cork this cache, set the cache to the corked state so
             // existing caches talk directly to their services while we've corked updates.
             // Make sure we don't clobber a disabled cache value.
 
@@ -584,8 +645,11 @@
             if (numberCorks == 0) {
                 final long nonce = SystemProperties.getLong(name, NONCE_UNSET);
                 if (nonce != NONCE_UNSET && nonce != NONCE_DISABLED) {
-                    SystemProperties.set(name, Long.toString(NONCE_UNSET));
+                    SystemProperties.set(name, Long.toString(NONCE_CORKED));
                 }
+            } else {
+                final long count = sCorkedInvalidates.getOrDefault(name, (long) 0);
+                sCorkedInvalidates.put(name, count + 1);
             }
             sCorks.put(name, numberCorks + 1);
             if (DEBUG) {
@@ -602,6 +666,14 @@
      * @param name Name of the cache-key property to uncork
      */
     public static void uncorkInvalidations(@NonNull String name) {
+        if (!sEnabled) {
+            if (DEBUG) {
+                Log.w(TAG, String.format(
+                    "cache uncork %s suppressed", name));
+            }
+            return;
+        }
+
         synchronized (sCorkLock) {
             int numberCorks = sCorks.getOrDefault(name, 0);
             if (DEBUG) {
@@ -729,8 +801,9 @@
             boolean nonceChanged = (getCurrentNonce() != mLastSeenNonce);
             if (!nonceChanged && !debugCompareQueryResults(proposedResult, resultToCompare)) {
                 Log.e(TAG, String.format(
-                    "cache %s inconsistent for %s",
-                    cacheName(), queryToString(query)));
+                    "cache %s inconsistent for %s is %s should be %s",
+                    cacheName(), queryToString(query),
+                    proposedResult, resultToCompare));
             }
             // Always return the "true" result in verification mode.
             return resultToCompare;
@@ -784,18 +857,23 @@
 
     private void dumpContents(PrintWriter pw, String[] args) {
         long invalidateCount;
-
+        long corkedInvalidates;
         synchronized (sCorkLock) {
             invalidateCount = sInvalidates.getOrDefault(mPropertyName, (long) 0);
+            corkedInvalidates = sCorkedInvalidates.getOrDefault(mPropertyName, (long) 0);
         }
 
         synchronized (mLock) {
             pw.println(String.format("  Cache Property Name: %s", cacheName()));
-            pw.println(String.format("    Hits: %d, Misses: %d, Invalidates: %d",
-                    mHits, mMisses, invalidateCount));
+            pw.println(String.format("    Hits: %d, Misses: %d, Invalidates: %d, Overflows: %d",
+                    mHits, mMisses, invalidateCount, mMissOverflow));
+            pw.println(String.format("    Miss-corked: %d, Miss-unset: %d, Miss-other: %d," +
+                    " CorkedInvalidates: %d",
+                    mMissDisabled[NONCE_CORKED], mMissDisabled[NONCE_UNSET],
+                    mMissDisabled[NONCE_DISABLED], corkedInvalidates));
             pw.println(String.format("    Last Observed Nonce: %d", mLastSeenNonce));
-            pw.println(String.format("    Current Size: %d, Max Size: %d",
-                    mCache.entrySet().size(), mMaxEntries));
+            pw.println(String.format("    Current Size: %d, Max Size: %d, HW Mark: %d",
+                    mCache.size(), mMaxEntries, mHighWaterMark));
             pw.println(String.format("    Enabled: %s", mDisabled ? "false" : "true"));
 
             Set<Map.Entry<Query, Result>> cacheEntries = mCache.entrySet();
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 31da83a..6922072 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -308,7 +308,7 @@
                 false /* isScreenRound */,
                 false /* alwaysConsumeSystemBars */, null /* displayCutout */,
                 LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
-                0 /* legacySystemUiFlags */, typeSideMap)
+                0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, typeSideMap)
                .getInsets(mTypes);
     }
 
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index a679b37..c383bc7 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -501,6 +501,7 @@
     private PendingControlRequest mPendingImeControlRequest;
 
     private int mLastLegacySoftInputMode;
+    private int mLastLegacyWindowFlags;
     private int mLastLegacySystemUiFlags;
     private DisplayCutout mLastDisplayCutout;
     private boolean mStartingAnimation;
@@ -569,8 +570,8 @@
 
             WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
                     mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
-                    mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags,
-                    null /* typeSideMap */);
+                    mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacyWindowFlags,
+                    mLastLegacySystemUiFlags, null /* typeSideMap */);
             mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims);
             if (DEBUG) {
                 for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) {
@@ -706,13 +707,14 @@
     @VisibleForTesting
     public WindowInsets calculateInsets(boolean isScreenRound,
             boolean alwaysConsumeSystemBars, DisplayCutout cutout,
-            int legacySoftInputMode, int legacySystemUiFlags) {
+            int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags) {
         mLastLegacySoftInputMode = legacySoftInputMode;
+        mLastLegacyWindowFlags = legacyWindowFlags;
         mLastLegacySystemUiFlags = legacySystemUiFlags;
         mLastDisplayCutout = cutout;
         mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
                 isScreenRound, alwaysConsumeSystemBars, cutout,
-                legacySoftInputMode, legacySystemUiFlags,
+                legacySoftInputMode, legacyWindowFlags, legacySystemUiFlags,
                 null /* typeSideMap */);
         return mLastInsets;
     }
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 91e75911..6b0b509 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -22,13 +22,14 @@
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.ViewRootImpl.sNewInsetsMode;
 import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
-import static android.view.WindowInsets.Type.SIZE;
 import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
 import static android.view.WindowInsets.Type.displayCutout;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.indexOf;
 import static android.view.WindowInsets.Type.isVisibleInsetsType;
+import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 
@@ -38,7 +39,6 @@
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseIntArray;
 import android.view.WindowInsets.Type;
@@ -171,7 +171,7 @@
      */
     public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState,
             boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout,
-            int legacySoftInputMode, int legacySystemUiFlags,
+            int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags,
             @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
         Insets[] typeInsetsMap = new Insets[Type.SIZE];
         Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
@@ -218,10 +218,17 @@
             }
         }
         final int softInputAdjustMode = legacySoftInputMode & SOFT_INPUT_MASK_ADJUST;
+
+        @InsetsType int compatInsetsTypes = systemBars() | displayCutout();
+        if (softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE) {
+            compatInsetsTypes |= ime();
+        }
+        if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
+            compatInsetsTypes &= ~statusBars();
+        }
+
         return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
-                alwaysConsumeSystemBars, cutout, softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE
-                        ? systemBars() | displayCutout() | ime()
-                        : systemBars() | displayCutout(),
+                alwaysConsumeSystemBars, cutout, compatInsetsTypes,
                 sNewInsetsMode == NEW_INSETS_MODE_FULL
                         && (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0);
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f2cec25..fe6f33d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2257,7 +2257,8 @@
             mLastWindowInsets = mInsetsController.calculateInsets(
                     mContext.getResources().getConfiguration().isScreenRound(),
                     mAttachInfo.mAlwaysConsumeSystemBars, mPendingDisplayCutout.get(),
-                    mWindowAttributes.softInputMode, (mWindowAttributes.systemUiVisibility
+                    mWindowAttributes.softInputMode, mWindowAttributes.flags,
+                    (mWindowAttributes.systemUiVisibility
                             | mWindowAttributes.subtreeSystemUiVisibility));
 
             Rect visibleInsets = mInsetsController.calculateVisibleInsets(
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 4d6b72f..5e94758 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,7 +17,6 @@
 
 package android.view;
 
-import static android.view.WindowInsets.Type.CAPTION_BAR;
 import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
 import static android.view.WindowInsets.Type.FIRST;
 import static android.view.WindowInsets.Type.IME;
@@ -95,7 +94,7 @@
     private final boolean mStableInsetsConsumed;
     private final boolean mDisplayCutoutConsumed;
 
-    private final int mCompatInsetTypes;
+    private final int mCompatInsetsTypes;
     private final boolean mCompatIgnoreVisibility;
 
     /**
@@ -150,8 +149,8 @@
             @Nullable Insets[] typeMaxInsetsMap,
             boolean[] typeVisibilityMap,
             boolean isRound,
-            boolean alwaysConsumeSystemBars, DisplayCutout displayCutout, int compatInsetTypes,
-            boolean compatIgnoreVisibility) {
+            boolean alwaysConsumeSystemBars, DisplayCutout displayCutout,
+            @InsetsType int compatInsetsTypes, boolean compatIgnoreVisibility) {
         mSystemWindowInsetsConsumed = typeInsetsMap == null;
         mTypeInsetsMap = mSystemWindowInsetsConsumed
                 ? new Insets[SIZE]
@@ -165,7 +164,7 @@
         mTypeVisibilityMap = typeVisibilityMap;
         mIsRound = isRound;
         mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
-        mCompatInsetTypes = compatInsetTypes;
+        mCompatInsetsTypes = compatInsetsTypes;
         mCompatIgnoreVisibility = compatIgnoreVisibility;
 
         mDisplayCutoutConsumed = displayCutout == null;
@@ -183,7 +182,7 @@
                 src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
                 src.mTypeVisibilityMap, src.mIsRound,
                 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src),
-                src.mCompatInsetTypes,
+                src.mCompatInsetsTypes,
                 src.mCompatIgnoreVisibility);
     }
 
@@ -310,11 +309,11 @@
     @NonNull
     public Insets getSystemWindowInsets() {
         Insets result = mCompatIgnoreVisibility
-                ? getInsetsIgnoringVisibility(mCompatInsetTypes & ~ime())
-                : getInsets(mCompatInsetTypes);
+                ? getInsetsIgnoringVisibility(mCompatInsetsTypes & ~ime())
+                : getInsets(mCompatInsetsTypes);
 
         // We can't query max insets for IME, so we need to add it manually after.
-        if ((mCompatInsetTypes & ime()) != 0 && mCompatIgnoreVisibility) {
+        if ((mCompatInsetsTypes & ime()) != 0 && mCompatIgnoreVisibility) {
             result = Insets.max(result, getInsets(ime()));
         }
         return result;
@@ -503,7 +502,7 @@
                 mTypeVisibilityMap,
                 mIsRound, mAlwaysConsumeSystemBars,
                 null /* displayCutout */,
-                mCompatInsetTypes, mCompatIgnoreVisibility);
+                mCompatInsetsTypes, mCompatIgnoreVisibility);
     }
 
 
@@ -554,7 +553,7 @@
                 mTypeVisibilityMap,
                 mIsRound, mAlwaysConsumeSystemBars,
                 displayCutoutCopyConstructorArgument(this),
-                mCompatInsetTypes, mCompatIgnoreVisibility);
+                mCompatInsetsTypes, mCompatIgnoreVisibility);
     }
 
     // TODO(b/119190588): replace @code with @link below
@@ -627,7 +626,7 @@
     @Deprecated
     @NonNull
     public Insets getStableInsets() {
-        return getInsets(mTypeMaxInsetsMap, mCompatInsetTypes);
+        return getInsets(mTypeMaxInsetsMap, mCompatInsetsTypes);
     }
 
     /**
@@ -939,7 +938,7 @@
                         : mDisplayCutout == null
                                 ? DisplayCutout.NO_CUTOUT
                                 : mDisplayCutout.inset(left, top, right, bottom),
-                mCompatInsetTypes, mCompatIgnoreVisibility);
+                mCompatInsetsTypes, mCompatIgnoreVisibility);
     }
 
     @Override
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 28a18da..2fe7c02 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -276,7 +276,7 @@
             if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
                 return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
                         isScreenRound, alwaysConsumeSystemBars, displayCutout.get(),
-                        SOFT_INPUT_ADJUST_NOTHING,
+                        SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
                         SYSTEM_UI_FLAG_VISIBLE, null /* typeSideMap */);
             } else {
                 return new WindowInsets.Builder()
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index bfcf52a..eb69525 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -86,7 +86,7 @@
                     false,
                     new DisplayCutout(
                             Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
-                    SOFT_INPUT_ADJUST_RESIZE, 0);
+                    SOFT_INPUT_ADJUST_RESIZE, 0, 0);
             mImeConsumer = (ImeInsetsSourceConsumer) mController.getSourceConsumer(ITYPE_IME);
         });
     }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index c36f106..801cd4d 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -165,7 +165,7 @@
                     false,
                     new DisplayCutout(
                             Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
-                    SOFT_INPUT_ADJUST_RESIZE, 0);
+                    SOFT_INPUT_ADJUST_RESIZE, 0, 0);
             mController.onFrameChanged(new Rect(0, 0, 100, 100));
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 5260ef8..c7d835c 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -29,6 +29,7 @@
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -77,7 +78,7 @@
             mState.getSource(ITYPE_IME).setVisible(true);
             SparseIntArray typeSideMap = new SparseIntArray();
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap);
+                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, typeSideMap);
             assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
             assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
             assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
@@ -96,7 +97,7 @@
             mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
             mState.getSource(ITYPE_IME).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, null);
+                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null);
             assertEquals(100, insets.getStableInsetBottom());
             assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars()));
             assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
@@ -115,7 +116,7 @@
             mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
             mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+                    false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
             assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
             assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
             assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -131,7 +132,7 @@
             mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
             mState.getSource(ITYPE_IME).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, null);
+                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0, null);
             assertEquals(0, insets.getSystemWindowInsetBottom());
             assertEquals(100, insets.getInsets(ime()).bottom);
             assertTrue(insets.isVisible(ime()));
@@ -147,11 +148,28 @@
             mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
             mState.getSource(ITYPE_IME).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING,
+                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
                     SYSTEM_UI_FLAG_LAYOUT_STABLE, null);
             assertEquals(100, insets.getSystemWindowInsetTop());
             insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
-                    DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING,
+                    DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
+                    0 /* legacySystemUiFlags */, null);
+            assertEquals(0, insets.getSystemWindowInsetTop());
+        }
+    }
+
+    @Test
+    public void testCalculateInsets_systemUiFlagLayoutStable_windowFlagFullscreen() {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+            mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+                    false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN,
+                    SYSTEM_UI_FLAG_LAYOUT_STABLE, null);
+            assertEquals(0, insets.getSystemWindowInsetTop());
+            insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+                    DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
                     0 /* legacySystemUiFlags */, null);
             assertEquals(0, insets.getSystemWindowInsetTop());
         }
@@ -195,7 +213,7 @@
             mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
             mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+                    false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
             assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
             assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
             assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -211,7 +229,7 @@
             mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
             mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
-                    false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+                    false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
             assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
             assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
             assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -226,7 +244,7 @@
         mState.getSource(ITYPE_IME).setVisible(true);
         mState.removeSource(ITYPE_IME);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
-                DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, null);
+                DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null);
         assertEquals(0, insets.getSystemWindowInsetBottom());
     }
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c710bed..0679142 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -198,6 +198,8 @@
         <permission name="android.permission.MANAGE_USERS" />
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
+        <permission name="android.permission.LOG_COMPAT_CHANGE" />
+        <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.providers.contacts">
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
index de5ed54..5c87d30 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
@@ -283,5 +283,50 @@
         String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
 
         transcode(testVideoName, transcodedVideoName);
-    }*/
+    } */
+
+    @Test
+    public void testBenchmarkingHEVCToAVCWith107FramesWithoutAudio() throws Exception {
+        String videoNameWithoutExtension = "video_1920x1080_107frame_hevc_4Mbps_30fps";
+        String testVideoName = videoNameWithoutExtension + ".mp4";
+        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+        transcode(testVideoName, transcodedVideoName);
+    }
+
+    @Test
+    public void testBenchmarkingHEVCToAVCWith928FramesWithoutAudio() throws Exception {
+        String videoNameWithoutExtension = "video_1920x1080_928frame_hevc_4Mbps_30fps";
+        String testVideoName = videoNameWithoutExtension + ".mp4";
+        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+        transcode(testVideoName, transcodedVideoName);
+    }
+
+    @Test
+    public void testBenchmarkingHEVCToAVCWith1863FramesWithoutAudio() throws Exception {
+        String videoNameWithoutExtension = "video_1920x1080_1863frame_hevc_4Mbps_30fps";
+        String testVideoName = videoNameWithoutExtension + ".mp4";
+        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+        transcode(testVideoName, transcodedVideoName);
+    }
+
+    @Test
+    public void testBenchmarkingHEVCToAVCWith3863FramesWithoutAudio() throws Exception {
+        String videoNameWithoutExtension = "video_1920x1080_3863frame_hevc_4Mbps_30fps";
+        String testVideoName = videoNameWithoutExtension + ".mp4";
+        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+        transcode(testVideoName, transcodedVideoName);
+    }
+
+    @Test
+    public void testBenchmarkingHEVCToAVCWith9374FramesWithoutAudio() throws Exception {
+        String videoNameWithoutExtension = "video_1920x1080_9374frame_hevc_4Mbps_30fps";
+        String testVideoName = videoNameWithoutExtension + ".mp4";
+        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+        transcode(testVideoName, transcodedVideoName);
+    }
 }
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 6ecf303..dfc4758 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -140,7 +140,8 @@
         "testables",
         "truth-prebuilt",
         "dagger2",
-        "jsr330"
+        "jsr330",
+        "WindowManager-Shell",
     ],
     libs: [
         "android.test.runner",
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 2a2ba1b..14097b1 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -39,4 +39,6 @@
 
 -keep public class * extends com.android.systemui.SystemUI {
     public <init>(android.content.Context);
-}
\ No newline at end of file
+}
+
+-keep class com.android.wm.shell.*
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config_tv.xml b/packages/SystemUI/res/values/config_tv.xml
index ffd58dc..d8c9428 100644
--- a/packages/SystemUI/res/values/config_tv.xml
+++ b/packages/SystemUI/res/values/config_tv.xml
@@ -22,4 +22,13 @@
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
          when the PIP menu is shown in center. -->
     <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
+
+    <!-- Whether to enable microphone disclosure indicator
+         (com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar). -->
+    <bool name="audio_recording_disclosure_enabled">true</bool>
+
+    <!-- Whether the indicator should expand and show the recording application's label.
+         When disabled (false) the "minimized" indicator would appear on the screen whenever an
+         application is recording, but will not reveal to the user what application this is.  -->
+    <bool name="audio_recording_disclosure_reveal_packages">false</bool>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 1354585..434bf49 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -207,12 +207,6 @@
     /** Whether or not the BubbleStackView has been added to the WindowManager. */
     private boolean mAddedToWindowManager = false;
 
-    /**
-     * Value from {@link NotificationShadeWindowController#getForceHasTopUi()} when we forced top UI
-     * due to expansion. We'll restore this value when the stack collapses.
-     */
-    private boolean mHadTopUi = false;
-
     // Listens to user switch so bubbles can be saved and restored.
     private final NotificationLockscreenUserManager mNotifUserManager;
 
@@ -1304,7 +1298,7 @@
             // Collapsing? Do this first before remaining steps.
             if (update.expandedChanged && !update.expanded) {
                 mStackView.setExpanded(false);
-                mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
+                mNotificationShadeWindowController.setRequestTopUi(false, TAG);
             }
 
             // Do removals, if any.
@@ -1394,8 +1388,7 @@
             if (update.expandedChanged && update.expanded) {
                 if (mStackView != null) {
                     mStackView.setExpanded(true);
-                    mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
-                    mNotificationShadeWindowController.setForceHasTopUi(true);
+                    mNotificationShadeWindowController.setRequestTopUi(true, TAG);
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index b2e9164..ef51abb 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -2129,7 +2129,6 @@
         private boolean mShowing;
         private float mScrimAlpha;
         private ResetOrientationData mResetOrientationData;
-        private boolean mHadTopUi;
         private final NotificationShadeWindowController mNotificationShadeWindowController;
         private final NotificationShadeDepthController mDepthController;
         private final SysUiState mSysUiState;
@@ -2397,8 +2396,7 @@
         public void show() {
             super.show();
             mShowing = true;
-            mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
-            mNotificationShadeWindowController.setForceHasTopUi(true);
+            mNotificationShadeWindowController.setRequestTopUi(true, TAG);
             mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true)
                     .commitUpdate(mContext.getDisplayId());
 
@@ -2499,7 +2497,7 @@
             dismissOverflow(true);
             dismissPowerOptions(true);
             if (mControlsUiController != null) mControlsUiController.hide();
-            mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
+            mNotificationShadeWindowController.setRequestTopUi(false, TAG);
             mDepthController.updateGlobalDialogVisibility(0, null /* view */);
             mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false)
                     .commitUpdate(mContext.getDisplayId());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index cdcfac8..d264af9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -84,7 +84,6 @@
     private final Map<View, MenuItem> mMenuItemsByView = new ArrayMap<>();
     private OnMenuEventListener mMenuListener;
     private boolean mDismissRtl;
-    private boolean mIsForeground;
 
     private ValueAnimator mFadeAnimator;
     private boolean mAnimating;
@@ -191,9 +190,7 @@
     @Override
     public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
         mParent = (ExpandableNotificationRow) parent;
-        createMenuViews(true /* resetState */,
-                sbn != null && (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
-                        != 0);
+        createMenuViews(true /* resetState */);
     }
 
     @Override
@@ -237,8 +234,7 @@
             // Menu hasn't been created yet, no need to do anything.
             return;
         }
-        createMenuViews(!isMenuVisible() /* resetState */,
-                (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
+        createMenuViews(!isMenuVisible() /* resetState */);
     }
 
     @Override
@@ -253,9 +249,7 @@
         mParent.removeListener();
     }
 
-    private void createMenuViews(boolean resetState, final boolean isForeground) {
-        mIsForeground = isForeground;
-
+    private void createMenuViews(boolean resetState) {
         final Resources res = mContext.getResources();
         mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
         mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -266,7 +260,7 @@
                 SHOW_NOTIFICATION_SNOOZE, 0) == 1;
 
         // Construct the menu items based on the notification
-        if (!isForeground && showSnooze) {
+        if (showSnooze) {
             // Only show snooze for non-foreground notifications, and if the setting is on
             mSnoozeItem = createSnoozeItem(mContext);
         }
@@ -283,7 +277,7 @@
             mInfoItem = createInfoItem(mContext);
         }
 
-        if (!isForeground && showSnooze) {
+        if (showSnooze) {
             mRightMenuItems.add(mSnoozeItem);
         }
         mRightMenuItems.add(mInfoItem);
@@ -789,7 +783,7 @@
     public void setDismissRtl(boolean dismissRtl) {
         mDismissRtl = dismissRtl;
         if (mMenuContainer != null) {
-            createMenuViews(true, mIsForeground);
+            createMenuViews(true);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 07eaaa1..bf85852 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -19,8 +19,6 @@
 import static com.android.systemui.statusbar.phone.HeadsUpAppearanceController.CONTENT_FADE_DELAY;
 import static com.android.systemui.statusbar.phone.HeadsUpAppearanceController.CONTENT_FADE_DURATION;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
@@ -807,6 +805,7 @@
                 } else {
                     super.applyToView(view);
                 }
+                sTempProperties.setAnimationEndAction(null);
                 boolean inShelf = iconAppearAmount == 1.0f;
                 icon.setIsInShelf(inShelf);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index 5164440..bc73be1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -61,6 +61,8 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -432,7 +434,7 @@
     }
 
     private void applyHasTopUi(State state) {
-        mHasTopUiChanged = state.mForceHasTopUi || isExpanded(state);
+        mHasTopUiChanged = !state.mComponentsForcingTopUi.isEmpty() || isExpanded(state);
     }
 
     private void applyNotTouchable(State state) {
@@ -635,12 +637,17 @@
         apply(mCurrentState);
     }
 
-    public boolean getForceHasTopUi() {
-        return mCurrentState.mForceHasTopUi;
-    }
-
-    public void setForceHasTopUi(boolean forceHasTopUi) {
-        mCurrentState.mForceHasTopUi = forceHasTopUi;
+    /**
+     * SystemUI may need top-ui to avoid jank when performing animations.  After the
+     * animation is performed, the component should remove itself from the list of features that
+     * are forcing SystemUI to be top-ui.
+     */
+    public void setRequestTopUi(boolean requestTopUi, String componentTag) {
+        if (requestTopUi) {
+            mCurrentState.mComponentsForcingTopUi.add(componentTag);
+        } else {
+            mCurrentState.mComponentsForcingTopUi.remove(componentTag);
+        }
         apply(mCurrentState);
     }
 
@@ -663,7 +670,7 @@
         boolean mBackdropShowing;
         boolean mWallpaperSupportsAmbientMode;
         boolean mNotTouchable;
-        boolean mForceHasTopUi;
+        Set<String> mComponentsForcingTopUi = new HashSet<>();
 
         /**
          * The {@link StatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c14a5ef..b65bd45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -213,7 +213,6 @@
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
 import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -2397,18 +2396,31 @@
                     new WirelessChargingAnimation.Callback() {
                         @Override
                         public void onAnimationStarting() {
+                            mNotificationShadeWindowController.setRequestTopUi(true, TAG);
                             CrossFadeHelper.fadeOut(mNotificationPanelViewController.getView(), 1);
                         }
 
                         @Override
                         public void onAnimationEnded() {
                             CrossFadeHelper.fadeIn(mNotificationPanelViewController.getView());
+                            mNotificationShadeWindowController.setRequestTopUi(false, TAG);
                         }
                     }, mDozing).show(animationDelay);
         } else {
             // workspace
             WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
-                    transmittingBatteryLevel, batteryLevel, null, false).show(animationDelay);
+                    transmittingBatteryLevel, batteryLevel,
+                    new WirelessChargingAnimation.Callback() {
+                        @Override
+                        public void onAnimationStarting() {
+                            mNotificationShadeWindowController.setRequestTopUi(true, TAG);
+                        }
+
+                        @Override
+                        public void onAnimationEnded() {
+                            mNotificationShadeWindowController.setRequestTopUi(false, TAG);
+                        }
+                    }, false).show(animationDelay);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 53ac657..9c3395f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -79,7 +79,7 @@
 /**
  * Host for the remote input.
  */
-public class RemoteInputView extends LinearLayout implements View.OnClickListener, TextWatcher {
+public class RemoteInputView extends LinearLayout implements View.OnClickListener {
 
     private static final String TAG = "RemoteInput";
 
@@ -88,6 +88,8 @@
 
     public final Object mToken = new Object();
 
+    private final SendButtonTextWatcher mTextWatcher;
+    private final TextView.OnEditorActionListener mEditorActionHandler;
     private RemoteEditText mEditText;
     private ImageButton mSendButton;
     private ProgressBar mProgressBar;
@@ -113,6 +115,8 @@
 
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mTextWatcher = new SendButtonTextWatcher();
+        mEditorActionHandler = new EditorActionHandler();
         mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class);
         mStatusBarManagerService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -128,30 +132,7 @@
         mSendButton.setOnClickListener(this);
 
         mEditText = (RemoteEditText) getChildAt(0);
-        mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
-            @Override
-            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-                final boolean isSoftImeEvent = event == null
-                        && (actionId == EditorInfo.IME_ACTION_DONE
-                        || actionId == EditorInfo.IME_ACTION_NEXT
-                        || actionId == EditorInfo.IME_ACTION_SEND);
-                final boolean isKeyboardEnterKey = event != null
-                        && KeyEvent.isConfirmKey(event.getKeyCode())
-                        && event.getAction() == KeyEvent.ACTION_DOWN;
-
-                if (isSoftImeEvent || isKeyboardEnterKey) {
-                    if (mEditText.length() > 0) {
-                        sendRemoteInput(prepareRemoteInputFromText());
-                    }
-                    // Consume action to prevent IME from closing.
-                    return true;
-                }
-                return false;
-            }
-        });
-        mEditText.addTextChangedListener(this);
         mEditText.setInnerFocusable(false);
-        mEditText.mRemoteInputView = this;
     }
 
     protected Intent prepareRemoteInputFromText() {
@@ -292,6 +273,9 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mEditText.mRemoteInputView = this;
+        mEditText.setOnEditorActionListener(mEditorActionHandler);
+        mEditText.addTextChangedListener(mTextWatcher);
         if (mEntry.getRow().isChangingPosition()) {
             if (getVisibility() == VISIBLE && mEditText.isFocusable()) {
                 mEditText.requestFocus();
@@ -302,6 +286,9 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        mEditText.removeTextChangedListener(mTextWatcher);
+        mEditText.setOnEditorActionListener(null);
+        mEditText.mRemoteInputView = null;
         if (mEntry.getRow().isChangingPosition() || isTemporarilyDetached()) {
             return;
         }
@@ -412,17 +399,6 @@
         mSendButton.setEnabled(mEditText.getText().length() != 0);
     }
 
-    @Override
-    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
-
-    @Override
-    public void onTextChanged(CharSequence s, int start, int before, int count) {}
-
-    @Override
-    public void afterTextChanged(Editable s) {
-        updateSendButton();
-    }
-
     public void close() {
         mEditText.defocusIfNeeded(false /* animated */);
     }
@@ -545,6 +521,45 @@
         return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
     }
 
+    /** Handler for button click on send action in IME. */
+    private class EditorActionHandler implements TextView.OnEditorActionListener {
+
+        @Override
+        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+            final boolean isSoftImeEvent = event == null
+                    && (actionId == EditorInfo.IME_ACTION_DONE
+                    || actionId == EditorInfo.IME_ACTION_NEXT
+                    || actionId == EditorInfo.IME_ACTION_SEND);
+            final boolean isKeyboardEnterKey = event != null
+                    && KeyEvent.isConfirmKey(event.getKeyCode())
+                    && event.getAction() == KeyEvent.ACTION_DOWN;
+
+            if (isSoftImeEvent || isKeyboardEnterKey) {
+                if (mEditText.length() > 0) {
+                    sendRemoteInput(prepareRemoteInputFromText());
+                }
+                // Consume action to prevent IME from closing.
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /** Observes text change events and updates the visibility of the send button accordingly. */
+    private class SendButtonTextWatcher implements TextWatcher {
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            updateSendButton();
+        }
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -599,7 +614,7 @@
             if (!focused) {
                 defocusIfNeeded(true /* animate */);
             }
-            if (!mRemoteInputView.mRemoved) {
+            if (mRemoteInputView != null && !mRemoteInputView.mRemoved) {
                 mLightBarController.setDirectReplying(focused);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 6bc0565..c0602762 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -26,6 +26,7 @@
 import android.os.UserHandle;
 
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.statusbar.CommandQueue;
@@ -72,6 +73,11 @@
         } catch (RemoteException ex) {
             // If the system process isn't there we're doomed anyway.
         }
+
+        if  (mContext.getResources().getBoolean(R.bool.audio_recording_disclosure_enabled)) {
+            // Creating AudioRecordingDisclosureBar and just letting it run
+            new AudioRecordingDisclosureBar(mContext);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 36e360d..8e4e123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -112,6 +112,13 @@
      */
     private final AudioActivityObserver[] mAudioActivityObservers;
     /**
+     * Whether the indicator should expand and show the recording application's label.
+     * If disabled ({@code false}) the "minimized" ({@link #STATE_MINIMIZED}) indicator would appear
+     * on the screen whenever an application is recording, but will not reveal to the user what
+     * application this is.
+     */
+    private final boolean mRevealRecordingPackages;
+    /**
      * Set of applications that we've notified the user about since the indicator came up. Meaning
      * that if an application is in this list then at some point since the indicator came up, it
      * was expanded showing this application's title.
@@ -137,6 +144,8 @@
     public AudioRecordingDisclosureBar(Context context) {
         mContext = context;
 
+        mRevealRecordingPackages = mContext.getResources().getBoolean(
+                R.bool.audio_recording_disclosure_reveal_packages);
         mExemptPackages = new ArraySet<>(
                 Arrays.asList(mContext.getResources().getStringArray(
                         R.array.audio_recording_disclosure_exempt_apps)));
@@ -149,11 +158,6 @@
         };
     }
 
-    private String[] getGlobalStringArray(String setting) {
-        String result = Settings.Global.getString(mContext.getContentResolver(), setting);
-        return TextUtils.isEmpty(result) ? new String[0] : result.split(",");
-    }
-
     @UiThread
     @Override
     public void onAudioActivityStateChange(boolean active, String packageName) {
@@ -190,7 +194,9 @@
                 break;
 
             case STATE_MINIMIZED:
-                expand(packageName);
+                if (mRevealRecordingPackages) {
+                    expand(packageName);
+                }
                 break;
 
             case STATE_DISAPPEARING:
@@ -228,9 +234,8 @@
 
     @UiThread
     private void show(String packageName) {
-        final String label = getApplicationLabel(packageName);
         if (DEBUG) {
-            Log.d(TAG, "Showing indicator for " + packageName + " (" + label + ")...");
+            Log.d(TAG, "Showing indicator for " + packageName);
         }
 
         mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
@@ -247,18 +252,30 @@
         mTextView = mTextsContainers.findViewById(R.id.text);
         mBgEnd = mIndicatorView.findViewById(R.id.bg_end);
 
-        // Swap background drawables depending on layout directions (both drawables have rounded
-        // corners only on one side)
-        if (mIsLtr) {
-            mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
-            mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
-        } else {
-            mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
-            mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
-        }
-
         // Set up the notification text
-        mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
+        if (mRevealRecordingPackages) {
+            // Swap background drawables depending on layout directions (both drawables have rounded
+            // corners only on one side)
+            if (mIsLtr) {
+                mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+                mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+            } else {
+                mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+                mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+            }
+
+            final String label = getApplicationLabel(packageName);
+            mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
+        } else {
+            mTextsContainers.setVisibility(View.GONE);
+            mIconContainerBg.setVisibility(View.GONE);
+            mTextView.setVisibility(View.GONE);
+            mBgEnd.setVisibility(View.GONE);
+            mTextsContainers = null;
+            mIconContainerBg = null;
+            mTextView = null;
+            mBgEnd = null;
+        }
 
         // Initially change the visibility to INVISIBLE, wait until and receives the size and
         // then animate it moving from "off" the screen correctly
@@ -296,7 +313,11 @@
                                             @Override
                                             public void onAnimationEnd(Animator animation) {
                                                 startPulsatingAnimation();
-                                                onExpanded();
+                                                if (mRevealRecordingPackages) {
+                                                    onExpanded();
+                                                } else {
+                                                    onMinimized();
+                                                }
                                             }
                                         });
                                 set.start();
@@ -321,6 +342,8 @@
 
     @UiThread
     private void expand(String packageName) {
+        assertRevealingRecordingPackages();
+
         final String label = getApplicationLabel(packageName);
         if (DEBUG) {
             Log.d(TAG, "Expanding for " + packageName + " (" + label + ")...");
@@ -348,6 +371,8 @@
 
     @UiThread
     private void minimize() {
+        assertRevealingRecordingPackages();
+
         if (DEBUG) Log.d(TAG, "Minimizing...");
         final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth();
         final AnimatorSet set = new AnimatorSet();
@@ -393,6 +418,8 @@
 
     @UiThread
     private void onExpanded() {
+        assertRevealingRecordingPackages();
+
         if (DEBUG) Log.d(TAG, "Expanded");
         mState = STATE_SHOWN;
 
@@ -404,11 +431,13 @@
         if (DEBUG) Log.d(TAG, "Minimized");
         mState = STATE_MINIMIZED;
 
-        if (!mPendingNotificationPackages.isEmpty()) {
-            // There is a new application that started recording, tell the user about it.
-            expand(mPendingNotificationPackages.poll());
-        } else {
-            hideIndicatorIfNeeded();
+        if (mRevealRecordingPackages) {
+            if (!mPendingNotificationPackages.isEmpty()) {
+                // There is a new application that started recording, tell the user about it.
+                expand(mPendingNotificationPackages.poll());
+            } else {
+                hideIndicatorIfNeeded();
+            }
         }
     }
 
@@ -451,7 +480,14 @@
         animator.start();
     }
 
+    private String[] getGlobalStringArray(String setting) {
+        String result = Settings.Global.getString(mContext.getContentResolver(), setting);
+        return TextUtils.isEmpty(result) ? new String[0] : result.split(",");
+    }
+
     private String getApplicationLabel(String packageName) {
+        assertRevealingRecordingPackages();
+
         final PackageManager pm = mContext.getPackageManager();
         final ApplicationInfo appInfo;
         try {
@@ -461,4 +497,11 @@
         }
         return pm.getApplicationLabel(appInfo).toString();
     }
+
+    private void assertRevealingRecordingPackages() {
+        if (!mRevealRecordingPackages) {
+            Log.e(TAG, "Not revealing recording packages",
+                    DEBUG ? new RuntimeException("Should not be called") : null);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2eca00e..b323190 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -44,6 +44,7 @@
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_RARELY_USED;
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
+import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
 import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
 import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
 import static android.app.AppOpsManager.UID_STATE_CACHED;
@@ -5936,11 +5937,13 @@
         int newLeftDistance = AppOpsManager.leftCircularDistance(opCode,
                 mSampledAppOpCode, _NUM_OP);
 
-        if (mAcceptableLeftDistance < newLeftDistance) {
+        if (mAcceptableLeftDistance < newLeftDistance
+                && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) {
             return;
         }
 
-        if (mAcceptableLeftDistance > newLeftDistance) {
+        if (mAcceptableLeftDistance > newLeftDistance
+                && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) {
             mAcceptableLeftDistance = newLeftDistance;
             mMessagesCollectedCount = 0.0f;
         }
@@ -5978,13 +5981,13 @@
         if (mSampledPackage == null) {
             if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
                 mSamplingStrategy = SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
-                resampleAppOpForPackageLocked(packageName);
+                resampleAppOpForPackageLocked(packageName, true);
             }
         } else if (mRarelyUsedPackages.contains(packageName)) {
             mRarelyUsedPackages.remove(packageName);
             if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
                 mSamplingStrategy = SAMPLING_STRATEGY_RARELY_USED;
-                resampleAppOpForPackageLocked(packageName);
+                resampleAppOpForPackageLocked(packageName, true);
             }
         }
     }
@@ -6001,16 +6004,22 @@
     /** Resamples package and appop to watch from the list provided. */
     private void resamplePackageAndAppOpLocked(@NonNull List<String> packageNames) {
         if (!packageNames.isEmpty()) {
-            mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM;
-            resampleAppOpForPackageLocked(packageNames.get(
-                    ThreadLocalRandom.current().nextInt(packageNames.size())));
+            if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
+                mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM;
+                resampleAppOpForPackageLocked(packageNames.get(
+                        ThreadLocalRandom.current().nextInt(packageNames.size())), true);
+            } else {
+                mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM_OPS;
+                resampleAppOpForPackageLocked(packageNames.get(
+                        ThreadLocalRandom.current().nextInt(packageNames.size())), false);
+            }
         }
     }
 
     /** Resamples appop for the chosen package and initializes sampling state */
-    private void resampleAppOpForPackageLocked(@NonNull String packageName) {
+    private void resampleAppOpForPackageLocked(@NonNull String packageName, boolean pickOp) {
         mMessagesCollectedCount = 0.0f;
-        mSampledAppOpCode = ThreadLocalRandom.current().nextInt(_NUM_OP);
+        mSampledAppOpCode = pickOp ? ThreadLocalRandom.current().nextInt(_NUM_OP) : OP_NONE;
         mAcceptableLeftDistance = _NUM_OP;
         mSampledPackage = packageName;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 265ef19..17b805f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -25546,7 +25546,8 @@
 
     private void applyMimeGroupChanges(String packageName, String mimeGroup) {
         if (mComponentResolver.updateMimeGroup(packageName, mimeGroup)) {
-            clearPackagePreferredActivities(packageName, UserHandle.USER_ALL);
+            Binder.withCleanCallingIdentity(() ->
+                    clearPackagePreferredActivities(packageName, UserHandle.USER_ALL));
         }
 
         mPmInternal.writeSettings(false);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f13dfdd..68445f6 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -615,8 +615,9 @@
     static Rect getSystemBarInsets(Rect frame, InsetsState state) {
         return state.calculateInsets(frame, null /* ignoringVisibilityState */,
                 false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
-                null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacySystemUiFlags */,
-                null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect();
+                null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacyWindowFlags */,
+                0 /* legacySystemUiFlags */, null /* typeSideMap */).getInsets(
+                        WindowInsets.Type.systemBars()).toRect();
     }
 
     void dump(PrintWriter pw, String prefix) {