Merge "Remove UPDATED_SYSTEM_APP from updated system apps no longer exist" into udc-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f803739..63da0a2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7016,6 +7016,22 @@
     }
 
     /**
+     * @return true for custom notifications, including notifications
+     * with DecoratedCustomViewStyle or DecoratedMediaCustomViewStyle,
+     * and other notifications with user-provided custom views.
+     *
+     * @hide
+     */
+    public Boolean isCustomNotification() {
+        if (contentView == null
+                && bigContentView == null
+                && headsUpContentView == null) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * @return true if this notification is showing as a bubble
      *
      * @hide
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 4d858bd..0eb4caa 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -475,6 +475,18 @@
       "group": "WM_DEBUG_TASKS",
       "at": "com\/android\/server\/wm\/RecentTasks.java"
     },
+    "-1643780158": {
+      "message": "Saving original orientation before camera compat, last orientation is %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
+    },
+    "-1639406696": {
+      "message": "NOSENSOR override detected",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
+    },
     "-1638958146": {
       "message": "Removing activity %s from task=%s adding to task=%s Callers=%s",
       "level": "INFO",
@@ -751,6 +763,12 @@
       "group": "WM_DEBUG_IME",
       "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
     },
+    "-1397175017": {
+      "message": "Other orientation overrides are in place: not reverting",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
+    },
     "-1394745488": {
       "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
       "level": "INFO",
@@ -1711,6 +1729,12 @@
       "group": "WM_DEBUG_WINDOW_TRANSITIONS",
       "at": "com\/android\/server\/wm\/Transition.java"
     },
+    "-529187878": {
+      "message": "Reverting orientation after camera compat force rotation",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
+    },
     "-521613870": {
       "message": "App died during pause, not stopping: %s",
       "level": "VERBOSE",
@@ -2383,6 +2407,12 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "138097009": {
+      "message": "NOSENSOR override is absent: reverting",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
+    },
     "140319294": {
       "message": "IME target changed within ActivityRecord",
       "level": "DEBUG",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 8dd23b7..25b074d 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1921,6 +1921,7 @@
      */
     public void setGainmap(@Nullable Gainmap gainmap) {
         checkRecycled("Bitmap is recycled");
+        mGainmap = null;
         nativeSetGainmap(mNativePtr, gainmap == null ? 0 : gainmap.mNativePtr);
     }
 
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 701e20c..1da8e18 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -482,7 +482,9 @@
             if (opts == null || opts.inBitmap == null) {
                 return 0;
             }
-
+            // Clear out the gainmap since we don't attempt to reuse it and don't want to
+            // accidentally keep it on the re-used bitmap
+            opts.inBitmap.setGainmap(null);
             return opts.inBitmap.getNativeInstance();
         }
 
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index d08bc5c5..8049dc9 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -29,9 +29,10 @@
 
 namespace android {
 
-AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
-        : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
-    mTimeToShowNextSnapshot = ms2ns(mSkAnimatedImage->currentFrameDuration());
+AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed,
+                                             SkEncodedImageFormat format)
+        : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed), mFormat(format) {
+    mTimeToShowNextSnapshot = ms2ns(currentFrameDuration());
     setStagingBounds(mSkAnimatedImage->getBounds());
 }
 
@@ -92,7 +93,7 @@
         // directly from mSkAnimatedImage.
         lock.unlock();
         std::unique_lock imageLock{mImageLock};
-        *outDelay = ms2ns(mSkAnimatedImage->currentFrameDuration());
+        *outDelay = ms2ns(currentFrameDuration());
         return true;
     } else {
         // The next snapshot has not yet been decoded, but we've already passed
@@ -109,7 +110,7 @@
     Snapshot snap;
     {
         std::unique_lock lock{mImageLock};
-        snap.mDurationMS = mSkAnimatedImage->decodeNextFrame();
+        snap.mDurationMS = adjustFrameDuration(mSkAnimatedImage->decodeNextFrame());
         snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
     }
 
@@ -123,7 +124,7 @@
         std::unique_lock lock{mImageLock};
         mSkAnimatedImage->reset();
         snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
-        snap.mDurationMS = mSkAnimatedImage->currentFrameDuration();
+        snap.mDurationMS = currentFrameDuration();
     }
 
     return snap;
@@ -274,7 +275,7 @@
         {
             std::unique_lock lock{mImageLock};
             mSkAnimatedImage->reset();
-            durationMS = mSkAnimatedImage->currentFrameDuration();
+            durationMS = currentFrameDuration();
         }
         {
             std::unique_lock lock{mSwapLock};
@@ -306,7 +307,7 @@
     {
         std::unique_lock lock{mImageLock};
         if (update) {
-            durationMS = mSkAnimatedImage->decodeNextFrame();
+            durationMS = adjustFrameDuration(mSkAnimatedImage->decodeNextFrame());
         }
 
         canvas->drawDrawable(mSkAnimatedImage.get());
@@ -336,4 +337,20 @@
     return SkRectMakeLargest();
 }
 
+int AnimatedImageDrawable::adjustFrameDuration(int durationMs) {
+    if (durationMs == SkAnimatedImage::kFinished) {
+        return SkAnimatedImage::kFinished;
+    }
+
+    if (mFormat == SkEncodedImageFormat::kGIF) {
+        // Match Chrome & Firefox behavior that gifs with a duration <= 10ms is bumped to 100ms
+        return durationMs <= 10 ? 100 : durationMs;
+    }
+    return durationMs;
+}
+
+int AnimatedImageDrawable::currentFrameDuration() {
+    return adjustFrameDuration(mSkAnimatedImage->currentFrameDuration());
+}
+
 }  // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index 8ca3c7e..1e965ab 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -16,16 +16,16 @@
 
 #pragma once
 
-#include <cutils/compiler.h>
-#include <utils/Macros.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-
 #include <SkAnimatedImage.h>
 #include <SkCanvas.h>
 #include <SkColorFilter.h>
 #include <SkDrawable.h>
+#include <SkEncodedImageFormat.h>
 #include <SkPicture.h>
+#include <cutils/compiler.h>
+#include <utils/Macros.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
 
 #include <future>
 #include <mutex>
@@ -48,7 +48,8 @@
 public:
     // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the
     // Snapshots.
-    AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed);
+    AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed,
+                          SkEncodedImageFormat format);
 
     /**
      * This updates the internal time and returns true if the image needs
@@ -115,6 +116,7 @@
 private:
     sk_sp<SkAnimatedImage> mSkAnimatedImage;
     const size_t mBytesUsed;
+    const SkEncodedImageFormat mFormat;
 
     bool mRunning = false;
     bool mStarting = false;
@@ -157,6 +159,9 @@
     Properties mProperties;
 
     std::unique_ptr<OnAnimationEndListener> mEndListener;
+
+    int adjustFrameDuration(int);
+    int currentFrameDuration();
 };
 
 }  // namespace android
diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp
index 373e893..a7f5aa83 100644
--- a/libs/hwui/jni/AnimatedImageDrawable.cpp
+++ b/libs/hwui/jni/AnimatedImageDrawable.cpp
@@ -97,7 +97,7 @@
         bytesUsed += picture->approximateBytesUsed();
     }
 
-
+    SkEncodedImageFormat format = imageDecoder->mCodec->getEncodedFormat();
     sk_sp<SkAnimatedImage> animatedImg = SkAnimatedImage::Make(std::move(imageDecoder->mCodec),
                                                                info, subset,
                                                                std::move(picture));
@@ -108,8 +108,8 @@
 
     bytesUsed += sizeof(animatedImg.get());
 
-    sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(std::move(animatedImg),
-                                                                    bytesUsed));
+    sk_sp<AnimatedImageDrawable> drawable(
+            new AnimatedImageDrawable(std::move(animatedImg), bytesUsed, format));
     return reinterpret_cast<jlong>(drawable.release());
 }
 
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index c753020..060abfd 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -44,12 +44,19 @@
 
     std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const {
         if (mBuffer) {
+            // TODO: if returned C2Buffer is different from mBuffer, we should
+            // find a way to connect the life cycle between this C2Buffer and
+            // mBuffer.
             if (mBuffer->data().type() != C2BufferData::LINEAR) {
                 return nullptr;
             }
             C2ConstLinearBlock block = mBuffer->data().linearBlocks().front();
             if (offset == 0 && size == block.capacity()) {
-                return mBuffer;
+                // Let C2Buffer be new one to queue to MediaCodec. It will allow
+                // the related input slot to be released by onWorkDone from C2
+                // Component. Currently, the life cycle of mBuffer should be
+                // protected by different flows.
+                return std::make_shared<C2Buffer>(*mBuffer);
             }
 
             std::shared_ptr<C2Buffer> buffer =
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java
new file mode 100644
index 0000000..5326e73
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.fuelgauge;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Utilities related to battery saver logging.
+ */
+public final class BatterySaverLogging {
+    /**
+     * Record the reason while enabling power save mode manually.
+     * See {@link SaverManualEnabledReason} for all available states.
+     */
+    public static final String EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON =
+            "extra_power_save_mode_manual_enabled_reason";
+
+    /** Broadcast action to record battery saver manual enabled reason. */
+    public static final String ACTION_SAVER_MANUAL_ENABLED_REASON =
+            "com.android.settingslib.fuelgauge.ACTION_SAVER_MANUAL_ENABLED_REASON";
+
+    /** An interface for the battery saver manual enable reason. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({SAVER_ENABLED_UNKNOWN, SAVER_ENABLED_CONFIRMATION, SAVER_ENABLED_VOICE,
+            SAVER_ENABLED_SETTINGS, SAVER_ENABLED_QS, SAVER_ENABLED_LOW_WARNING,
+            SAVER_ENABLED_SEVERE_WARNING})
+    public @interface SaverManualEnabledReason {}
+
+    public static final int SAVER_ENABLED_UNKNOWN = 0;
+    public static final int SAVER_ENABLED_CONFIRMATION = 1;
+    public static final int SAVER_ENABLED_VOICE = 2;
+    public static final int SAVER_ENABLED_SETTINGS = 3;
+    public static final int SAVER_ENABLED_QS = 4;
+    public static final int SAVER_ENABLED_LOW_WARNING = 5;
+    public static final int SAVER_ENABLED_SEVERE_WARNING = 6;
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 52f3111..a3db6d7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -16,6 +16,10 @@
 
 package com.android.settingslib.fuelgauge;
 
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.ACTION_SAVER_MANUAL_ENABLED_REASON;
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON;
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.SaverManualEnabledReason;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -145,7 +149,8 @@
                         && Global.getInt(cr, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) == 0
                         && Secure.getInt(cr,
                         Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, 0) == 0) {
-                    showAutoBatterySaverSuggestion(context, confirmationExtras);
+                    sendSystemUiBroadcast(context, ACTION_SHOW_AUTO_SAVER_SUGGESTION,
+                            confirmationExtras);
                 }
             }
 
@@ -175,21 +180,23 @@
             // Already shown.
             return false;
         }
-        context.sendBroadcast(
-                getSystemUiBroadcast(ACTION_SHOW_START_SAVER_CONFIRMATION, extras));
+        sendSystemUiBroadcast(context, ACTION_SHOW_START_SAVER_CONFIRMATION, extras);
         return true;
     }
 
-    private static void showAutoBatterySaverSuggestion(Context context, Bundle extras) {
-        context.sendBroadcast(getSystemUiBroadcast(ACTION_SHOW_AUTO_SAVER_SUGGESTION, extras));
+    private static void recordBatterySaverEnabledReason(Context context,
+            @SaverManualEnabledReason int reason) {
+        final Bundle enabledReasonExtras = new Bundle(1);
+        enabledReasonExtras.putInt(EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON, reason);
+        sendSystemUiBroadcast(context, ACTION_SAVER_MANUAL_ENABLED_REASON, enabledReasonExtras);
     }
 
-    private static Intent getSystemUiBroadcast(String action, Bundle extras) {
-        final Intent i = new Intent(action);
-        i.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        i.setPackage(SYSUI_PACKAGE);
-        i.putExtras(extras);
-        return i;
+    private static void sendSystemUiBroadcast(Context context, String action, Bundle extras) {
+        final Intent intent = new Intent(action);
+        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.setPackage(SYSUI_PACKAGE);
+        intent.putExtras(extras);
+        context.sendBroadcast(intent);
     }
 
     private static void setBatterySaverConfirmationAcknowledged(Context context) {
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 3007d4a..7a1d9a3 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -156,9 +156,10 @@
         "WifiTrackerLib",
         "WindowManager-Shell",
         "SystemUIAnimationLib",
+        "SystemUICommon",
+        "SystemUICustomizationLib",
         "SystemUIPluginLib",
         "SystemUISharedLib",
-        "SystemUICustomizationLib",
         "SystemUI-statsd",
         "SettingsLib",
         "androidx.core_core-ktx",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/preferences_action_bar.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/preferences_action_bar.xml
new file mode 100644
index 0000000..1d670660
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/preferences_action_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/action_bar_title"
+        style="@style/TextAppearance.AppCompat.Title"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:maxLines="5"/>
+</LinearLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java
index 02d279f..5ed450a 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.accessibility.accessibilitymenu.activity;
 
+import android.app.ActionBar;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -24,6 +25,7 @@
 import android.os.Bundle;
 import android.provider.Browser;
 import android.provider.Settings;
+import android.widget.TextView;
 import android.view.View;
 
 import androidx.annotation.Nullable;
@@ -46,6 +48,13 @@
                 .beginTransaction()
                 .replace(android.R.id.content, new A11yMenuPreferenceFragment())
                 .commit();
+
+        ActionBar actionBar = getActionBar();
+        actionBar.setDisplayShowCustomEnabled(true);
+        actionBar.setCustomView(R.layout.preferences_action_bar);
+        ((TextView) findViewById(R.id.action_bar_title)).setText(
+                getResources().getString(R.string.accessibility_menu_settings_name)
+        );
     }
 
     /**
diff --git a/packages/SystemUI/common/.gitignore b/packages/SystemUI/common/.gitignore
new file mode 100644
index 0000000..f9a33db
--- /dev/null
+++ b/packages/SystemUI/common/.gitignore
@@ -0,0 +1,9 @@
+.idea/
+.gradle/
+gradle/
+build/
+gradlew*
+local.properties
+*.iml
+android.properties
+buildSrc
\ No newline at end of file
diff --git a/packages/SystemUI/common/Android.bp b/packages/SystemUI/common/Android.bp
new file mode 100644
index 0000000..e36ada8
--- /dev/null
+++ b/packages/SystemUI/common/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_library {
+
+    name: "SystemUICommon",
+
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+
+    static_libs: [
+        "androidx.core_core-ktx",
+    ],
+
+    manifest: "AndroidManifest.xml",
+    kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SystemUI/common/AndroidManifest.xml b/packages/SystemUI/common/AndroidManifest.xml
new file mode 100644
index 0000000..6f757eb
--- /dev/null
+++ b/packages/SystemUI/common/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.systemui.common">
+
+</manifest>
diff --git a/packages/SystemUI/common/OWNERS b/packages/SystemUI/common/OWNERS
new file mode 100644
index 0000000..9b8a79e
--- /dev/null
+++ b/packages/SystemUI/common/OWNERS
@@ -0,0 +1,2 @@
+darrellshi@google.com
+evanlaird@google.com
diff --git a/packages/SystemUI/common/README.md b/packages/SystemUI/common/README.md
new file mode 100644
index 0000000..1cc5277
--- /dev/null
+++ b/packages/SystemUI/common/README.md
@@ -0,0 +1,5 @@
+# SystemUICommon
+
+`SystemUICommon` is a module within SystemUI that hosts standalone helper libraries. It is intended to be used by other modules, and therefore should not have other SystemUI dependencies to avoid circular dependencies.
+
+To maintain the structure of this module, please refrain from adding components at the top level. Instead, add them to specific sub-packages, such as `systemui/common/buffer/`. This will help to keep the module organized and easy to navigate.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/common/src/com/android/systemui/common/buffer/RingBuffer.kt
similarity index 98%
rename from packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
rename to packages/SystemUI/common/src/com/android/systemui/common/buffer/RingBuffer.kt
index 4773f54..de49d1c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/common/src/com/android/systemui/common/buffer/RingBuffer.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.plugins.util
+package com.android.systemui.common.buffer
 
 import kotlin.math.max
 
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index fb1c454..e306d4a 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -37,6 +37,7 @@
         "error_prone_annotations",
         "PluginCoreLib",
         "SystemUIAnimationLib",
+        "SystemUICommon",
     ],
 
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index 3e34885..4a6e0b6 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -18,7 +18,7 @@
 
 import android.os.Trace
 import android.util.Log
-import com.android.systemui.plugins.util.RingBuffer
+import com.android.systemui.common.buffer.RingBuffer
 import com.google.errorprone.annotations.CompileTimeConstant
 import java.io.PrintWriter
 import java.util.concurrent.ArrayBlockingQueue
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardActiveUnlockModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardActiveUnlockModel.kt
index 3a89c13..40f6f48 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardActiveUnlockModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardActiveUnlockModel.kt
@@ -17,9 +17,9 @@
 package com.android.keyguard
 
 import android.annotation.CurrentTimeMillisLong
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.dump.DumpsysTableLogger
 import com.android.systemui.dump.Row
-import com.android.systemui.plugins.util.RingBuffer
 
 /** Verbose debug information. */
 data class KeyguardActiveUnlockModel(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index c98e9b4..5b0e290 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -17,9 +17,9 @@
 package com.android.keyguard
 
 import android.annotation.CurrentTimeMillisLong
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.dump.DumpsysTableLogger
 import com.android.systemui.dump.Row
-import com.android.systemui.plugins.util.RingBuffer
 
 /** Verbose debug information associated. */
 data class KeyguardFaceListenModel(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
index 57130ed..b8c0ccb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
@@ -17,9 +17,9 @@
 package com.android.keyguard
 
 import android.annotation.CurrentTimeMillisLong
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.dump.DumpsysTableLogger
 import com.android.systemui.dump.Row
-import com.android.systemui.plugins.util.RingBuffer
 
 /** Verbose debug information. */
 data class KeyguardFingerprintListenModel(
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index f6b7133..691017b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -324,10 +324,6 @@
 
     @Override
     public boolean isFalseLongTap(@Penalty int penalty) {
-        if (!mFeatureFlags.isEnabled(Flags.FALSING_FOR_LONG_TAPS)) {
-            return false;
-        }
-
         checkDestroyed();
 
         if (skipFalsing(GENERIC)) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 6bb0f2e..b44499f 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -648,9 +648,6 @@
     val APP_PANELS_REMOVE_APPS_ALLOWED =
         unreleasedFlag(2003, "app_panels_remove_apps_allowed", teamfood = true)
 
-    // 2100 - Falsing Manager
-    @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps")
-
     // 2200 - udfps
     // TODO(b/259264861): Tracking Bug
     @JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection")
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 9d2d355..faaa205 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -18,7 +18,7 @@
 
 import android.os.Trace
 import com.android.systemui.Dumpable
-import com.android.systemui.plugins.util.RingBuffer
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.util.time.SystemClock
 import java.io.PrintWriter
 import java.text.SimpleDateFormat
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 72286f1..3711a2f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -162,7 +162,7 @@
     private fun registerUserSwitchObserver() {
         iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() {
             override fun onBeforeUserSwitching(newUserId: Int) {
-                setUserIdInternal(newUserId)
+                handleBeforeUserSwitching(newUserId)
             }
 
             override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
@@ -180,6 +180,10 @@
         }, TAG)
     }
 
+    protected open fun handleBeforeUserSwitching(newUserId: Int) {
+        setUserIdInternal(newUserId)
+    }
+
     @WorkerThread
     protected open fun handleUserSwitching(newUserId: Int) {
         Assert.isNotMainThread()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt b/packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
index 754036d..b8bd95c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
@@ -14,9 +14,9 @@
 package com.android.systemui.shade
 
 import android.view.MotionEvent
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.dump.DumpsysTableLogger
 import com.android.systemui.dump.Row
-import com.android.systemui.plugins.util.RingBuffer
 import java.text.SimpleDateFormat
 import java.util.Locale
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
index fed9b84..7812f07 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -16,9 +16,9 @@
 
 package com.android.systemui.shade
 
+import com.android.systemui.common.buffer.RingBuffer
 import com.android.systemui.dump.DumpsysTableLogger
 import com.android.systemui.dump.Row
-import com.android.systemui.plugins.util.RingBuffer
 import com.android.systemui.shade.NotificationShadeWindowState.Buffer
 import com.android.systemui.statusbar.StatusBarState
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index 15ad312..1631ae2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
 import com.android.systemui.statusbar.notification.collection.render.NodeController
 import com.android.systemui.statusbar.notification.dagger.PeopleHeader
 import com.android.systemui.statusbar.notification.icon.ConversationIconManager
@@ -40,27 +41,28 @@
  */
 @CoordinatorScope
 class ConversationCoordinator @Inject constructor(
-    private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
-    private val conversationIconManager: ConversationIconManager,
-    @PeopleHeader peopleHeaderController: NodeController
+        private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
+        private val conversationIconManager: ConversationIconManager,
+        private val highPriorityProvider: HighPriorityProvider,
+        @PeopleHeader private val peopleHeaderController: NodeController,
 ) : Coordinator {
 
     private val promotedEntriesToSummaryOfSameChannel =
-        mutableMapOf<NotificationEntry, NotificationEntry>()
+            mutableMapOf<NotificationEntry, NotificationEntry>()
 
     private val onBeforeRenderListListener = OnBeforeRenderListListener { _ ->
         val unimportantSummaries = promotedEntriesToSummaryOfSameChannel
-            .mapNotNull { (promoted, summary) ->
-                val originalGroup = summary.parent
-                when {
-                    originalGroup == null -> null
-                    originalGroup == promoted.parent -> null
-                    originalGroup.parent == null -> null
-                    originalGroup.summary != summary -> null
-                    originalGroup.children.any { it.channel == summary.channel } -> null
-                    else -> summary.key
+                .mapNotNull { (promoted, summary) ->
+                    val originalGroup = summary.parent
+                    when {
+                        originalGroup == null -> null
+                        originalGroup == promoted.parent -> null
+                        originalGroup.parent == null -> null
+                        originalGroup.summary != summary -> null
+                        originalGroup.children.any { it.channel == summary.channel } -> null
+                        else -> summary.key
+                    }
                 }
-            }
         conversationIconManager.setUnimportantConversations(unimportantSummaries)
         promotedEntriesToSummaryOfSameChannel.clear()
     }
@@ -78,21 +80,23 @@
         }
     }
 
-    val sectioner = object : NotifSectioner("People", BUCKET_PEOPLE) {
+    val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
         override fun isInSection(entry: ListEntry): Boolean =
-                isConversation(entry)
+               highPriorityProvider.isHighPriorityConversation(entry)
 
-        override fun getComparator() = object : NotifComparator("People") {
-            override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
-                val type1 = getPeopleType(entry1)
-                val type2 = getPeopleType(entry2)
-                return type2.compareTo(type1)
-            }
-        }
+        override fun getComparator(): NotifComparator = notifComparator
 
-        override fun getHeaderNodeController() =
-                // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
-                if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
+        override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController
+    }
+
+    val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) {
+        // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting.
+        // All remaining conversations must be silent.
+        override fun isInSection(entry: ListEntry): Boolean = isConversation(entry)
+
+        override fun getComparator(): NotifComparator = notifComparator
+
+        override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController
     }
 
     override fun attach(pipeline: NotifPipeline) {
@@ -101,15 +105,27 @@
     }
 
     private fun isConversation(entry: ListEntry): Boolean =
-        getPeopleType(entry) != TYPE_NON_PERSON
+            getPeopleType(entry) != TYPE_NON_PERSON
 
     @PeopleNotificationType
     private fun getPeopleType(entry: ListEntry): Int =
-        entry.representativeEntry?.let {
-            peopleNotificationIdentifier.getPeopleNotificationType(it)
-        } ?: TYPE_NON_PERSON
+            entry.representativeEntry?.let {
+                peopleNotificationIdentifier.getPeopleNotificationType(it)
+            } ?: TYPE_NON_PERSON
 
-    companion object {
+    private val notifComparator: NotifComparator = object : NotifComparator("People") {
+        override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
+            val type1 = getPeopleType(entry1)
+            val type2 = getPeopleType(entry2)
+            return type2.compareTo(type1)
+        }
+    }
+
+    // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
+    private val conversationHeaderNodeController: NodeController? =
+            if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
+
+    private companion object {
         private const val TAG = "ConversationCoordinator"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 6bb5b92..02ce0d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
 import javax.inject.Inject
 
 /**
@@ -32,6 +33,7 @@
 @CoordinatorScope
 class NotifCoordinatorsImpl @Inject constructor(
         notifPipelineFlags: NotifPipelineFlags,
+        sectionStyleProvider: SectionStyleProvider,
         dataStoreCoordinator: DataStoreCoordinator,
         hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
         hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
@@ -56,7 +58,7 @@
         viewConfigCoordinator: ViewConfigCoordinator,
         visualStabilityCoordinator: VisualStabilityCoordinator,
         sensitiveContentCoordinator: SensitiveContentCoordinator,
-        dismissibilityCoordinator: DismissibilityCoordinator
+        dismissibilityCoordinator: DismissibilityCoordinator,
 ) : NotifCoordinators {
 
     private val mCoordinators: MutableList<Coordinator> = ArrayList()
@@ -99,13 +101,20 @@
         mCoordinators.add(dismissibilityCoordinator)
 
         // Manually add Ordered Sections
-        // HeadsUp > FGS > People > Alerting > Silent > Minimized > Unknown/Default
-        mOrderedSections.add(headsUpCoordinator.sectioner)
+        mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
         mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService
-        mOrderedSections.add(conversationCoordinator.sectioner) // People
+        mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting
+        mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent
         mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting
         mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent
         mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized
+
+        sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner))
+        sectionStyleProvider.setSilentSections(listOf(
+                conversationCoordinator.peopleSilentSectioner,
+                rankingCoordinator.silentSectioner,
+                rankingCoordinator.minimizedSectioner,
+        ))
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index ea5cb30..1d37dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -27,15 +27,12 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
-import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
 import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
 
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -52,7 +49,6 @@
     public static final boolean SHOW_ALL_SECTIONS = false;
     private final StatusBarStateController mStatusBarStateController;
     private final HighPriorityProvider mHighPriorityProvider;
-    private final SectionStyleProvider mSectionStyleProvider;
     private final NodeController mSilentNodeController;
     private final SectionHeaderController mSilentHeaderController;
     private final NodeController mAlertingHeaderController;
@@ -63,13 +59,11 @@
     public RankingCoordinator(
             StatusBarStateController statusBarStateController,
             HighPriorityProvider highPriorityProvider,
-            SectionStyleProvider sectionStyleProvider,
             @AlertingHeader NodeController alertingHeaderController,
             @SilentHeader SectionHeaderController silentHeaderController,
             @SilentHeader NodeController silentNodeController) {
         mStatusBarStateController = statusBarStateController;
         mHighPriorityProvider = highPriorityProvider;
-        mSectionStyleProvider = sectionStyleProvider;
         mAlertingHeaderController = alertingHeaderController;
         mSilentNodeController = silentNodeController;
         mSilentHeaderController = silentHeaderController;
@@ -78,9 +72,6 @@
     @Override
     public void attach(NotifPipeline pipeline) {
         mStatusBarStateController.addCallback(mStatusBarStateCallback);
-        mSectionStyleProvider.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner));
-        mSectionStyleProvider.setSilentSections(
-                Arrays.asList(mSilentNotifSectioner, mMinimizedNotifSectioner));
 
         pipeline.addPreGroupFilter(mSuspendedFilter);
         pipeline.addPreGroupFilter(mDndVisualEffectsFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index e7ef2ec..731ec80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -16,10 +16,13 @@
 
 package com.android.systemui.statusbar.notification.collection.provider;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.NotificationManager;
 
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -63,7 +66,7 @@
      * A GroupEntry is considered high priority if its representativeEntry (summary) or children are
      * high priority
      */
-    public boolean isHighPriority(ListEntry entry) {
+    public boolean isHighPriority(@Nullable ListEntry entry) {
         if (entry == null) {
             return false;
         }
@@ -78,6 +81,36 @@
                 || hasHighPriorityChild(entry);
     }
 
+    /**
+     * @return true if the ListEntry is high priority conversation, else false
+     */
+    public boolean isHighPriorityConversation(@NonNull ListEntry entry) {
+        final NotificationEntry notifEntry = entry.getRepresentativeEntry();
+        if (notifEntry == null) {
+            return  false;
+        }
+
+        if (!isPeopleNotification(notifEntry)) {
+            return false;
+        }
+
+        if (notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
+            return true;
+        }
+
+        return isNotificationEntryWithAtLeastOneImportantChild(entry);
+    }
+
+    private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull ListEntry entry) {
+        if (!(entry instanceof GroupEntry)) {
+            return false;
+        }
+        final GroupEntry groupEntry = (GroupEntry) entry;
+        return groupEntry.getChildren().stream().anyMatch(
+                childEntry ->
+                        childEntry.getRanking().getImportance()
+                                >= NotificationManager.IMPORTANCE_DEFAULT);
+    }
 
     private boolean hasHighPriorityChild(ListEntry entry) {
         if (entry instanceof NotificationEntry
@@ -93,7 +126,6 @@
                 }
             }
         }
-
         return false;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index dce7bf2..bfd133e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -37,7 +37,6 @@
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.stateIn
 
 /** Common interface for all of the location-based mobile icon view models. */
@@ -80,7 +79,12 @@
 ) : MobileIconViewModelCommon {
     /** Whether or not to show the error state of [SignalDrawable] */
     private val showExclamationMark: Flow<Boolean> =
-        iconInteractor.isDefaultDataEnabled.mapLatest { !it }
+        combine(
+            iconInteractor.isDefaultDataEnabled,
+            iconInteractor.isDefaultConnectionFailed,
+        ) { isDefaultDataEnabled, isDefaultConnectionFailed ->
+            !isDefaultDataEnabled || isDefaultConnectionFailed
+        }
 
     override val isVisible: StateFlow<Boolean> =
         if (!constants.hasDataCapabilities) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 8cb9130..4cb99a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -120,7 +120,6 @@
                 gestureCompleteListenerCaptor.capture());
 
         mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
-        mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true);
         mFakeFeatureFlags.set(Flags.MEDIA_FALSING_PENALTY, true);
         mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
     }
@@ -260,13 +259,6 @@
     }
 
     @Test
-    public void testIsFalseLongTap_FalseLongTap_NotFlagged() {
-        mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, false);
-        when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult);
-        assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isFalse();
-    }
-
-    @Test
     public void testIsFalseLongTap_FalseLongTap() {
         when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult);
         assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isTrue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index 315774a..292fdff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -94,7 +94,6 @@
                 mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
                 mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
                 mAccessibilityManager, false, mFakeFeatureFlags);
-        mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true);
         mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index 30708a7..ac66ad9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -97,6 +97,59 @@
     }
 
     @Test
+    public void highImportanceConversation() {
+        // GIVEN notification is high importance and is a people notification
+        final Notification notification = new Notification.Builder(mContext, "test")
+                .build();
+        final NotificationEntry entry = new NotificationEntryBuilder()
+                .setNotification(notification)
+                .setImportance(IMPORTANCE_HIGH)
+                .build();
+        when(mPeopleNotificationIdentifier
+                .getPeopleNotificationType(entry))
+                .thenReturn(TYPE_PERSON);
+
+        // THEN it is high priority conversation
+        assertTrue(mHighPriorityProvider.isHighPriorityConversation(entry));
+    }
+
+    @Test
+    public void lowImportanceConversation() {
+        // GIVEN notification is high importance and is a people notification
+        final Notification notification = new Notification.Builder(mContext, "test")
+                .build();
+        final NotificationEntry entry = new NotificationEntryBuilder()
+                .setNotification(notification)
+                .setImportance(IMPORTANCE_LOW)
+                .build();
+        when(mPeopleNotificationIdentifier
+                .getPeopleNotificationType(entry))
+                .thenReturn(TYPE_PERSON);
+
+        // THEN it is low priority conversation
+        assertFalse(mHighPriorityProvider.isHighPriorityConversation(entry));
+    }
+
+    @Test
+    public void highImportanceConversationWhenAnyOfChildIsHighPriority() {
+        // GIVEN notification is high importance and is a people notification
+        final NotificationEntry summary = createNotifEntry(false);
+        final NotificationEntry lowPriorityChild = createNotifEntry(false);
+        final NotificationEntry highPriorityChild = createNotifEntry(true);
+        when(mPeopleNotificationIdentifier
+                .getPeopleNotificationType(summary))
+                .thenReturn(TYPE_PERSON);
+        final GroupEntry groupEntry = new GroupEntryBuilder()
+                .setParent(GroupEntry.ROOT_ENTRY)
+                .setSummary(summary)
+                .setChildren(List.of(lowPriorityChild, highPriorityChild))
+                .build();
+
+        // THEN the groupEntry is high priority conversation since it has a high priority child
+        assertTrue(mHighPriorityProvider.isHighPriorityConversation(groupEntry));
+    }
+
+    @Test
     public void messagingStyle() {
         // GIVEN notification is low importance but has messaging style
         final Notification notification = new Notification.Builder(mContext, "test")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index 742fcf5..55ea3157 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -17,6 +17,9 @@
 package com.android.systemui.statusbar.notification.collection.coordinator
 
 import android.app.NotificationChannel
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.app.NotificationManager.IMPORTANCE_LOW
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import androidx.test.filters.SmallTest
@@ -31,10 +34,13 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl
 import com.android.systemui.statusbar.notification.collection.render.NodeController
 import com.android.systemui.statusbar.notification.icon.ConversationIconManager
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.withArgCaptor
@@ -55,7 +61,8 @@
 class ConversationCoordinatorTest : SysuiTestCase() {
     // captured listeners and pluggables:
     private lateinit var promoter: NotifPromoter
-    private lateinit var peopleSectioner: NotifSectioner
+    private lateinit var peopleAlertingSectioner: NotifSectioner
+    private lateinit var peopleSilentSectioner: NotifSectioner
     private lateinit var peopleComparator: NotifComparator
     private lateinit var beforeRenderListListener: OnBeforeRenderListListener
 
@@ -76,6 +83,7 @@
         coordinator = ConversationCoordinator(
             peopleNotificationIdentifier,
             conversationIconManager,
+            HighPriorityProvider(peopleNotificationIdentifier, GroupMembershipManagerImpl()),
             headerController
         )
         whenever(channel.isImportantConversation).thenReturn(true)
@@ -90,12 +98,13 @@
             verify(pipeline).addOnBeforeRenderListListener(capture())
         }
 
-        peopleSectioner = coordinator.sectioner
-        peopleComparator = peopleSectioner.comparator!!
+        peopleAlertingSectioner = coordinator.peopleAlertingSectioner
+        peopleSilentSectioner = coordinator.peopleSilentSectioner
+        peopleComparator = peopleAlertingSectioner.comparator!!
 
         entry = NotificationEntryBuilder().setChannel(channel).build()
 
-        val section = NotifSection(peopleSectioner, 0)
+        val section = NotifSection(peopleAlertingSectioner, 0)
         entryA = NotificationEntryBuilder().setChannel(channel)
             .setSection(section).setTag("A").build()
         entryB = NotificationEntryBuilder().setChannel(channel)
@@ -129,13 +138,67 @@
     }
 
     @Test
-    fun testInPeopleSection() {
-        whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry))
-            .thenReturn(TYPE_PERSON)
+    fun testInAlertingPeopleSectionWhenTheImportanceIsAtLeastDefault() {
+        // GIVEN
+        val alertingEntry = NotificationEntryBuilder().setChannel(channel)
+                .setImportance(IMPORTANCE_DEFAULT).build()
+        whenever(peopleNotificationIdentifier.getPeopleNotificationType(alertingEntry))
+                .thenReturn(TYPE_PERSON)
 
-        // only put people notifications in this section
-        assertTrue(peopleSectioner.isInSection(entry))
-        assertFalse(peopleSectioner.isInSection(NotificationEntryBuilder().build()))
+        // put alerting people notifications in this section
+        assertThat(peopleAlertingSectioner.isInSection(alertingEntry)).isTrue()
+       }
+
+    @Test
+    fun testInSilentPeopleSectionWhenTheImportanceIsLowerThanDefault() {
+        // GIVEN
+        val silentEntry = NotificationEntryBuilder().setChannel(channel)
+                .setImportance(IMPORTANCE_LOW).build()
+        whenever(peopleNotificationIdentifier.getPeopleNotificationType(silentEntry))
+                .thenReturn(TYPE_PERSON)
+
+        // THEN put silent people notifications in this section
+        assertThat(peopleSilentSectioner.isInSection(silentEntry)).isTrue()
+        // People Alerting sectioning happens before the silent one.
+        // It claims high important conversations and rest of conversations will be considered as silent.
+        assertThat(peopleAlertingSectioner.isInSection(silentEntry)).isFalse()
+    }
+
+    @Test
+    fun testNotInPeopleSection() {
+        // GIVEN
+        val entry = NotificationEntryBuilder().setChannel(channel)
+                .setImportance(IMPORTANCE_LOW).build()
+        val importantEntry = NotificationEntryBuilder().setChannel(channel)
+                .setImportance(IMPORTANCE_HIGH).build()
+        whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry))
+                .thenReturn(TYPE_NON_PERSON)
+        whenever(peopleNotificationIdentifier.getPeopleNotificationType(importantEntry))
+                .thenReturn(TYPE_NON_PERSON)
+
+        // THEN - only put people notification either silent or alerting
+        assertThat(peopleSilentSectioner.isInSection(entry)).isFalse()
+        assertThat(peopleAlertingSectioner.isInSection(importantEntry)).isFalse()
+    }
+
+    @Test
+    fun testInAlertingPeopleSectionWhenThereIsAnImportantChild(){
+        // GIVEN
+        val altChildA = NotificationEntryBuilder().setTag("A")
+                .setImportance(IMPORTANCE_DEFAULT).build()
+        val altChildB = NotificationEntryBuilder().setTag("B")
+                .setImportance(IMPORTANCE_LOW).build()
+        val summary = NotificationEntryBuilder().setId(2)
+                .setImportance(IMPORTANCE_LOW).setChannel(channel).build()
+        val groupEntry = GroupEntryBuilder()
+                .setParent(GroupEntry.ROOT_ENTRY)
+                .setSummary(summary)
+                .setChildren(listOf(altChildA, altChildB))
+                .build()
+        whenever(peopleNotificationIdentifier.getPeopleNotificationType(summary))
+                .thenReturn(TYPE_PERSON)
+        // THEN
+        assertThat(peopleAlertingSectioner.isInSection(groupEntry)).isTrue()
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index d5c0c55..3d1253e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -52,7 +52,6 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
-import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 
@@ -73,7 +72,6 @@
 
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private HighPriorityProvider mHighPriorityProvider;
-    @Mock private SectionStyleProvider mSectionStyleProvider;
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private NodeController mAlertingHeaderController;
     @Mock private NodeController mSilentNodeController;
@@ -100,7 +98,6 @@
         mRankingCoordinator = new RankingCoordinator(
                 mStatusBarStateController,
                 mHighPriorityProvider,
-                mSectionStyleProvider,
                 mAlertingHeaderController,
                 mSilentHeaderController,
                 mSilentNodeController);
@@ -108,7 +105,6 @@
         mEntry.setRanking(getRankingForUnfilteredNotif().build());
 
         mRankingCoordinator.attach(mNotifPipeline);
-        verify(mSectionStyleProvider).setMinimizedSections(any());
         verify(mNotifPipeline, times(2)).addPreGroupFilter(mNotifFilterCaptor.capture());
         mCapturedSuspendedFilter = mNotifFilterCaptor.getAllValues().get(0);
         mCapturedDozingFilter = mNotifFilterCaptor.getAllValues().get(1);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index 1b6ab4d..297cb9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -179,15 +179,71 @@
         }
 
     @Test
-    fun iconId_cutout_whenDefaultDataDisabled() =
+    fun icon_usesLevelFromInteractor() =
+        testScope.runTest {
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
+
+            interactor.level.value = 3
+            assertThat(latest!!.level).isEqualTo(3)
+
+            interactor.level.value = 1
+            assertThat(latest!!.level).isEqualTo(1)
+
+            job.cancel()
+        }
+
+    @Test
+    fun icon_usesNumberOfLevelsFromInteractor() =
+        testScope.runTest {
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
+
+            interactor.numberOfLevels.value = 5
+            assertThat(latest!!.numberOfLevels).isEqualTo(5)
+
+            interactor.numberOfLevels.value = 2
+            assertThat(latest!!.numberOfLevels).isEqualTo(2)
+
+            job.cancel()
+        }
+
+    @Test
+    fun icon_defaultDataDisabled_showExclamationTrue() =
         testScope.runTest {
             interactor.setIsDefaultDataEnabled(false)
 
             var latest: SignalIconModel? = null
             val job = underTest.icon.onEach { latest = it }.launchIn(this)
-            val expected = defaultSignal(level = 1, connected = false)
 
-            assertThat(latest).isEqualTo(expected)
+            assertThat(latest!!.showExclamationMark).isTrue()
+
+            job.cancel()
+        }
+
+    @Test
+    fun icon_defaultConnectionFailed_showExclamationTrue() =
+        testScope.runTest {
+            interactor.isDefaultConnectionFailed.value = true
+
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest!!.showExclamationMark).isTrue()
+
+            job.cancel()
+        }
+
+    @Test
+    fun icon_enabledAndNotFailed_showExclamationFalse() =
+        testScope.runTest {
+            interactor.setIsDefaultDataEnabled(true)
+            interactor.isDefaultConnectionFailed.value = false
+
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest!!.showExclamationMark).isFalse()
 
             job.cancel()
         }
@@ -572,16 +628,14 @@
 
     companion object {
         private const val SUB_1_ID = 1
+        private const val NUM_LEVELS = 4
 
         /** Convenience constructor for these tests */
-        fun defaultSignal(
-            level: Int = 1,
-            connected: Boolean = true,
-        ): SignalIconModel {
-            return SignalIconModel(level, numberOfLevels = 4, showExclamationMark = !connected)
+        fun defaultSignal(level: Int = 1): SignalIconModel {
+            return SignalIconModel(level, NUM_LEVELS, showExclamationMark = false)
         }
 
         fun emptySignal(): SignalIconModel =
-            SignalIconModel(level = 0, numberOfLevels = 4, showExclamationMark = true)
+            SignalIconModel(level = 0, numberOfLevels = NUM_LEVELS, showExclamationMark = true)
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b25206d..7e48f68 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -3391,6 +3391,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onDefaultNetworkChanged(@NonNull Network network) {
+            mEventChanges.log("[UnderlyingNW] Default network changed to " + network);
             Log.d(TAG, "onDefaultNetworkChanged: " + network);
 
             // If there is a new default network brought up, cancel the retry task to prevent
@@ -3628,6 +3629,7 @@
                 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
                         .setTransportInfo(info)
                         .build();
+                mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities);
                 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities);
             }
         }
@@ -3664,6 +3666,7 @@
 
         private void startIkeSession(@NonNull Network underlyingNetwork) {
             Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
+            mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork);
 
             try {
                 // Clear mInterface to prevent Ikev2VpnRunner being cleared when
@@ -3778,6 +3781,7 @@
         }
 
         public void onValidationStatus(int status) {
+            mEventChanges.log("[Validation] validation status " + status);
             if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
                 // No data stall now. Reset it.
                 mExecutor.execute(() -> {
@@ -3818,6 +3822,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onDefaultNetworkLost(@NonNull Network network) {
+            mEventChanges.log("[UnderlyingNW] Network lost " + network);
             // If the default network is torn down, there is no need to call
             // startOrMigrateIkeSession() since it will always check if there is an active network
             // can be used or not.
@@ -3936,6 +3941,8 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onSessionLost(int token, @Nullable Exception exception) {
+            mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork
+                    + (null == exception ? "" : " reason " + exception.getMessage()));
             Log.d(TAG, "onSessionLost() called for token " + token);
 
             if (!isActiveToken(token)) {
@@ -4092,6 +4099,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         private void disconnectVpnRunner() {
+            mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork);
             mActiveNetwork = null;
             mUnderlyingNetworkCapabilities = null;
             mUnderlyingLinkProperties = null;
diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java
index c05a03e..c76ca2b 100644
--- a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java
+++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java
@@ -286,7 +286,6 @@
                     final InputMethodSubtype.InputMethodSubtypeBuilder
                             builder = new InputMethodSubtype.InputMethodSubtypeBuilder()
                             .setSubtypeNameResId(label)
-                            .setSubtypeNameOverride(untranslatableName)
                             .setPhysicalKeyboardHint(
                                     pkLanguageTag == null ? null : new ULocale(pkLanguageTag),
                                     pkLayoutType == null ? "" : pkLayoutType)
@@ -302,6 +301,9 @@
                     if (subtypeId != InputMethodSubtype.SUBTYPE_ID_NONE) {
                         builder.setSubtypeId(subtypeId);
                     }
+                    if (untranslatableName != null) {
+                        builder.setSubtypeNameOverride(untranslatableName);
+                    }
                     tempSubtypesArray.add(builder.build());
                 }
             }
diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java
index c29e4d7..52fdbda 100644
--- a/services/core/java/com/android/server/pm/IPackageManagerBase.java
+++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java
@@ -606,6 +606,7 @@
         final Computer snapshot = snapshot();
         // Return null for InstantApps.
         if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            Log.w(PackageManagerService.TAG, "Returning null PackageInstaller for InstantApps");
             return null;
         }
         return mInstallerService;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b5fde9e..fb1f899 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3522,7 +3522,8 @@
 
             final boolean endTask = task.getTopNonFinishingActivity() == null
                     && !task.isClearingToReuseTask();
-            mTransitionController.requestCloseTransitionIfNeeded(endTask ? task : this);
+            final Transition newTransition =
+                    mTransitionController.requestCloseTransitionIfNeeded(endTask ? task : this);
             if (isState(RESUMED)) {
                 if (endTask) {
                     mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
@@ -3576,7 +3577,16 @@
             } else if (!isState(PAUSING)) {
                 if (mVisibleRequested) {
                     // Prepare and execute close transition.
-                    prepareActivityHideTransitionAnimation();
+                    if (mTransitionController.isShellTransitionsEnabled()) {
+                        setVisibility(false);
+                        if (newTransition != null) {
+                            // This is a transition specifically for this close operation, so set
+                            // ready now.
+                            newTransition.setReady(mDisplayContent, true);
+                        }
+                    } else {
+                        prepareActivityHideTransitionAnimation();
+                    }
                 }
 
                 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
@@ -9762,6 +9772,7 @@
      * directly with keeping its record.
      */
     void restartProcessIfVisible() {
+        if (finishing) return;
         Slog.i(TAG, "Request to restart process of " + this);
 
         // Reset the existing override configuration so it can be updated according to the latest
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 85974c7..a49ecce 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -305,8 +305,8 @@
         if (mActiveSyncs.size() != 0) {
             // We currently only support one sync at a time, so start a new SyncGroup when there is
             // another may cause issue.
-            ProtoLog.w(WM_DEBUG_SYNC_ENGINE,
-                    "SyncGroup %d: Started when there is other active SyncGroup", s.mSyncId);
+            Slog.e(TAG, "SyncGroup " + s.mSyncId
+                    + ": Started when there is other active SyncGroup");
         }
         mActiveSyncs.put(s.mSyncId, s);
         ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s",
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index be80b01..7b562b0 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -286,8 +286,8 @@
                                 currentActivity.getCustomAnimation(false/* open */);
                         if (customAppTransition != null) {
                             infoBuilder.setCustomAnimation(currentActivity.packageName,
-                                    customAppTransition.mExitAnim,
                                     customAppTransition.mEnterAnim,
+                                    customAppTransition.mExitAnim,
                                     customAppTransition.mBackgroundColor);
                         }
                     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index bec58b8..c2bc459 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -775,6 +775,8 @@
      */
     DisplayWindowPolicyControllerHelper mDwpcHelper;
 
+    private final DisplayRotationReversionController mRotationReversionController;
+
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final ActivityRecord activity = w.mActivityRecord;
@@ -1204,6 +1206,7 @@
                 mWmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
                             /* checkDeviceConfig */ false)
                         ? new DisplayRotationCompatPolicy(this) : null;
+        mRotationReversionController = new DisplayRotationReversionController(this);
 
         mInputMonitor = new InputMonitor(mWmService, this);
         mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this);
@@ -1333,6 +1336,10 @@
                 .show(mA11yOverlayLayer);
     }
 
+    DisplayRotationReversionController getRotationReversionController() {
+        return mRotationReversionController;
+    }
+
     boolean isReady() {
         // The display is ready when the system and the individual display are both ready.
         return mWmService.mDisplayReady && mDisplayReady;
@@ -1711,9 +1718,14 @@
     }
 
     private boolean updateOrientation(boolean forceUpdate) {
+        final WindowContainer prevOrientationSource = mLastOrientationSource;
         final int orientation = getOrientation();
         // The last orientation source is valid only after getOrientation.
         final WindowContainer orientationSource = getLastOrientationSource();
+        if (orientationSource != prevOrientationSource
+                && mRotationReversionController.isRotationReversionEnabled()) {
+            mRotationReversionController.updateForNoSensorOverride();
+        }
         final ActivityRecord r =
                 orientationSource != null ? orientationSource.asActivityRecord() : null;
         if (r != null) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index c8fde6b..20048ce 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -33,6 +33,9 @@
 import static com.android.server.wm.DisplayRotationProto.LAST_ORIENTATION;
 import static com.android.server.wm.DisplayRotationProto.ROTATION;
 import static com.android.server.wm.DisplayRotationProto.USER_ROTATION;
+import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_CAMERA_COMPAT;
+import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_HALF_FOLD;
+import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_NOSENSOR;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
@@ -106,6 +109,9 @@
         int mExit;
     }
 
+    @Nullable
+    final FoldController mFoldController;
+
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
     private final DisplayPolicy mDisplayPolicy;
@@ -127,8 +133,6 @@
     private OrientationListener mOrientationListener;
     private StatusBarManagerInternal mStatusBarManagerInternal;
     private SettingsObserver mSettingsObserver;
-    @Nullable
-    private FoldController mFoldController;
     @NonNull
     private final DeviceStateController mDeviceStateController;
     @NonNull
@@ -299,7 +303,11 @@
             if (mSupportAutoRotation && mContext.getResources().getBoolean(
                     R.bool.config_windowManagerHalfFoldAutoRotateOverride)) {
                 mFoldController = new FoldController();
+            } else {
+                mFoldController = null;
             }
+        } else {
+            mFoldController = null;
         }
     }
 
@@ -357,6 +365,11 @@
         return -1;
     }
 
+    @VisibleForTesting
+    boolean useDefaultSettingsProvider() {
+        return isDefaultDisplay;
+    }
+
     /**
      * Updates the configuration which may have different values depending on current user, e.g.
      * runtime resource overlay.
@@ -903,7 +916,7 @@
     @VisibleForTesting
     void setUserRotation(int userRotationMode, int userRotation) {
         mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED;
-        if (isDefaultDisplay) {
+        if (useDefaultSettingsProvider()) {
             // We'll be notified via settings listener, so we don't need to update internal values.
             final ContentResolver res = mContext.getContentResolver();
             final int accelerometerRotation =
@@ -1859,7 +1872,7 @@
                 return false;
             }
             if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
-                return !(isTabletop ^ mTabletopRotations.contains(mRotation));
+                return isTabletop == mTabletopRotations.contains(mRotation);
             }
             return true;
         }
@@ -1883,14 +1896,17 @@
             return mDeviceState == DeviceStateController.DeviceState.OPEN
                     && !mShouldIgnoreSensorRotation // Ignore if the hinge angle still moving
                     && mInHalfFoldTransition
-                    && mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
+                    && mDisplayContent.getRotationReversionController().isOverrideActive(
+                        REVERSION_TYPE_HALF_FOLD)
                     && mUserRotationMode
-                    == WindowManagerPolicy.USER_ROTATION_LOCKED; // Ignore if we're unlocked.
+                        == WindowManagerPolicy.USER_ROTATION_LOCKED; // Ignore if we're unlocked.
         }
 
         int revertOverriddenRotation() {
             int savedRotation = mHalfFoldSavedRotation;
             mHalfFoldSavedRotation = -1;
+            mDisplayContent.getRotationReversionController()
+                    .revertOverride(REVERSION_TYPE_HALF_FOLD);
             mInHalfFoldTransition = false;
             return savedRotation;
         }
@@ -1910,6 +1926,8 @@
                     && mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
                 // The device has transitioned to HALF_FOLDED state: save the current rotation and
                 // update the device rotation.
+                mDisplayContent.getRotationReversionController().beforeOverrideApplied(
+                        REVERSION_TYPE_HALF_FOLD);
                 mHalfFoldSavedRotation = mRotation;
                 mDeviceState = newState;
                 // Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
@@ -2115,6 +2133,8 @@
             final int mHalfFoldSavedRotation;
             final boolean mInHalfFoldTransition;
             final DeviceStateController.DeviceState mDeviceState;
+            @Nullable final boolean[] mRotationReversionSlots;
+
             @Nullable final String mDisplayRotationCompatPolicySummary;
 
             Record(DisplayRotation dr, int fromRotation, int toRotation) {
@@ -2155,6 +2175,8 @@
                         ? null
                         : dc.mDisplayRotationCompatPolicy
                                 .getSummaryForDisplayRotationHistoryRecord();
+                mRotationReversionSlots =
+                        dr.mDisplayContent.getRotationReversionController().getSlotsCopy();
             }
 
             void dump(String prefix, PrintWriter pw) {
@@ -2180,6 +2202,12 @@
                 if (mDisplayRotationCompatPolicySummary != null) {
                     pw.println(prefix + mDisplayRotationCompatPolicySummary);
                 }
+                if (mRotationReversionSlots != null) {
+                    pw.println(prefix + " reversionSlots= NOSENSOR "
+                            + mRotationReversionSlots[REVERSION_TYPE_NOSENSOR] + ", CAMERA "
+                            + mRotationReversionSlots[REVERSION_TYPE_CAMERA_COMPAT] + " HALF_FOLD "
+                            + mRotationReversionSlots[REVERSION_TYPE_HALF_FOLD]);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index fb72d6c..ae93a94 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -33,6 +33,7 @@
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_CAMERA_COMPAT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -156,6 +157,11 @@
     @ScreenOrientation
     int getOrientation() {
         mLastReportedOrientation = getOrientationInternal();
+        if (mLastReportedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+            rememberOverriddenOrientationIfNeeded();
+        } else {
+            restoreOverriddenOrientationIfNeeded();
+        }
         return mLastReportedOrientation;
     }
 
@@ -277,6 +283,34 @@
                 + " }";
     }
 
+    private void restoreOverriddenOrientationIfNeeded() {
+        if (!isOrientationOverridden()) {
+            return;
+        }
+        if (mDisplayContent.getRotationReversionController().revertOverride(
+                REVERSION_TYPE_CAMERA_COMPAT)) {
+            ProtoLog.v(WM_DEBUG_ORIENTATION,
+                    "Reverting orientation after camera compat force rotation");
+            // Reset last orientation source since we have reverted the orientation.
+            mDisplayContent.mLastOrientationSource = null;
+        }
+    }
+
+    private boolean isOrientationOverridden() {
+        return mDisplayContent.getRotationReversionController().isOverrideActive(
+                REVERSION_TYPE_CAMERA_COMPAT);
+    }
+
+    private void rememberOverriddenOrientationIfNeeded() {
+        if (!isOrientationOverridden()) {
+            mDisplayContent.getRotationReversionController().beforeOverrideApplied(
+                    REVERSION_TYPE_CAMERA_COMPAT);
+            ProtoLog.v(WM_DEBUG_ORIENTATION,
+                    "Saving original orientation before camera compat, last orientation is %d",
+                    mDisplayContent.getLastOrientation());
+        }
+    }
+
     // Refreshing only when configuration changes after rotation.
     private boolean shouldRefreshActivity(ActivityRecord activity, Configuration newConfig,
             Configuration lastReportedConfig) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotationReversionController.java b/services/core/java/com/android/server/wm/DisplayRotationReversionController.java
new file mode 100644
index 0000000..d3a8a82
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayRotationReversionController.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+
+import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.content.ActivityInfoProto;
+import android.view.Surface;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.policy.WindowManagerPolicy;
+
+/**
+ * Defines the behavior of reversion from device rotation overrides.
+ *
+ * <p>There are 3 override types:
+ * <ol>
+ *  <li>The top application has {@link SCREEN_ORIENTATION_NOSENSOR} set and is rotated to
+ *  {@link ROTATION_0}.
+ *  <li>Camera compat treatment has rotated the app {@link DisplayRotationCompatPolicy}.
+ *  <li>The device is half-folded and has auto-rotate is temporarily enabled.
+ * </ol>
+ *
+ * <p>Before an override is enabled, a component should call {@code beforeOverrideApplied}. When
+ * it wishes to revert, it should call {@code revertOverride}. The user rotation will be restored
+ * if there are no other overrides present.
+ */
+final class DisplayRotationReversionController {
+
+    static final int REVERSION_TYPE_NOSENSOR = 0;
+    static final int REVERSION_TYPE_CAMERA_COMPAT = 1;
+    static final int REVERSION_TYPE_HALF_FOLD = 2;
+    private static final int NUM_SLOTS = 3;
+
+    @Surface.Rotation
+    private int mUserRotationOverridden = WindowConfiguration.ROTATION_UNDEFINED;
+    @WindowManagerPolicy.UserRotationMode
+    private int mUserRotationModeOverridden;
+
+    private final boolean[] mSlots = new boolean[NUM_SLOTS];
+    private final DisplayContent mDisplayContent;
+
+    DisplayRotationReversionController(DisplayContent content) {
+        mDisplayContent = content;
+    }
+
+    boolean isRotationReversionEnabled() {
+        return mDisplayContent.mDisplayRotationCompatPolicy != null
+                || mDisplayContent.getDisplayRotation().mFoldController != null
+                || mDisplayContent.getIgnoreOrientationRequest();
+    }
+
+    void beforeOverrideApplied(int slotIndex) {
+        if (mSlots[slotIndex]) return;
+        maybeSaveUserRotation();
+        mSlots[slotIndex] = true;
+    }
+
+    boolean isOverrideActive(int slotIndex) {
+        return mSlots[slotIndex];
+    }
+
+    @Nullable
+    boolean[] getSlotsCopy() {
+        return isRotationReversionEnabled() ? mSlots.clone() : null;
+    }
+
+    void updateForNoSensorOverride() {
+        if (!mSlots[REVERSION_TYPE_NOSENSOR]) {
+            if (isTopFullscreenActivityNoSensor()) {
+                ProtoLog.v(WM_DEBUG_ORIENTATION, "NOSENSOR override detected");
+                beforeOverrideApplied(REVERSION_TYPE_NOSENSOR);
+            }
+        } else {
+            if (!isTopFullscreenActivityNoSensor()) {
+                ProtoLog.v(WM_DEBUG_ORIENTATION, "NOSENSOR override is absent: reverting");
+                revertOverride(REVERSION_TYPE_NOSENSOR);
+            }
+        }
+    }
+
+    boolean isAnyOverrideActive() {
+        for (int i = 0; i < NUM_SLOTS; ++i) {
+            if (mSlots[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean revertOverride(int slotIndex) {
+        if (!mSlots[slotIndex]) return false;
+        mSlots[slotIndex] = false;
+        if (isAnyOverrideActive()) {
+            ProtoLog.v(WM_DEBUG_ORIENTATION,
+                    "Other orientation overrides are in place: not reverting");
+            return false;
+        }
+        // Only override if the rotation is frozen and there are no other active slots.
+        if (mDisplayContent.getDisplayRotation().isRotationFrozen()) {
+            mDisplayContent.getDisplayRotation().setUserRotation(
+                    mUserRotationModeOverridden,
+                    mUserRotationOverridden);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private void maybeSaveUserRotation() {
+        if (!isAnyOverrideActive()) {
+            mUserRotationModeOverridden =
+                    mDisplayContent.getDisplayRotation().getUserRotationMode();
+            mUserRotationOverridden = mDisplayContent.getDisplayRotation().getUserRotation();
+        }
+    }
+
+    private boolean isTopFullscreenActivityNoSensor() {
+        final Task topFullscreenTask =
+                mDisplayContent.getTask(
+                        t -> t.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+        if (topFullscreenTask != null) {
+            final ActivityRecord topActivity =
+                    topFullscreenTask.topRunningActivity();
+            return topActivity != null && topActivity.getOrientation()
+                    == ActivityInfoProto.SCREEN_ORIENTATION_NOSENSOR;
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index f8f0211..f5079d3 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1512,7 +1512,7 @@
         // callbacks here.
         final Task removedTask = mTasks.remove(removeIndex);
         if (removedTask != task) {
-            if (removedTask.hasChild()) {
+            if (removedTask.hasChild() && !removedTask.isActivityTypeHome()) {
                 Slog.i(TAG, "Add " + removedTask + " to hidden list because adding " + task);
                 // A non-empty task is replaced by a new task. Because the removed task is no longer
                 // managed by the recent tasks list, add it to the hidden list to prevent the task
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0857898..73f4b5b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4687,7 +4687,7 @@
         if (!isAttached()) {
             return;
         }
-        mTransitionController.collect(this);
+        mTransitionController.recordTaskOrder(this);
 
         final TaskDisplayArea taskDisplayArea = getDisplayArea();
 
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 3cc1548..e209ef9 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -521,10 +521,7 @@
             mChanges.put(wc, info);
         }
         mParticipants.add(wc);
-        if (wc.getDisplayContent() != null && !mTargetDisplays.contains(wc.getDisplayContent())) {
-            mTargetDisplays.add(wc.getDisplayContent());
-            addOnTopTasks(wc.getDisplayContent(), mOnTopTasksStart);
-        }
+        recordDisplay(wc.getDisplayContent());
         if (info.mShowWallpaper) {
             // Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
             final WindowState wallpaper =
@@ -535,6 +532,20 @@
         }
     }
 
+    private void recordDisplay(DisplayContent dc) {
+        if (dc == null || mTargetDisplays.contains(dc)) return;
+        mTargetDisplays.add(dc);
+        addOnTopTasks(dc, mOnTopTasksStart);
+    }
+
+    /**
+     * Records information about the initial task order. This does NOT collect anything. Call this
+     * before any ordering changes *could* occur, but it is not known yet if it will occur.
+     */
+    void recordTaskOrder(WindowContainer from) {
+        recordDisplay(from.getDisplayContent());
+    }
+
     /** Adds the top non-alwaysOnTop tasks within `task` to `out`. */
     private static void addOnTopTasks(Task task, ArrayList<Task> out) {
         for (int i = task.getChildCount() - 1; i >= 0; --i) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index bcb8c46..8d56607 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -577,12 +577,16 @@
         return transition;
     }
 
-    /** Requests transition for a window container which will be removed or invisible. */
-    void requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) {
-        if (mTransitionPlayer == null) return;
+    /**
+     * Requests transition for a window container which will be removed or invisible.
+     * @return the new transition if it was created for this request, `null` otherwise.
+     */
+    Transition requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) {
+        if (mTransitionPlayer == null) return null;
+        Transition out = null;
         if (wc.isVisibleRequested()) {
             if (!isCollecting()) {
-                requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
+                out = requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
                         wc.asTask(), null /* remoteTransition */, null /* displayChange */);
             }
             collectExistenceChange(wc);
@@ -591,6 +595,7 @@
             // collecting, this should be a member just in case.
             collect(wc);
         }
+        return out;
     }
 
     /** @see Transition#collect */
@@ -605,6 +610,12 @@
         mCollectingTransition.collectExistenceChange(wc);
     }
 
+    /** @see Transition#recordTaskOrder */
+    void recordTaskOrder(@NonNull WindowContainer wc) {
+        if (mCollectingTransition == null) return;
+        mCollectingTransition.recordTaskOrder(wc);
+    }
+
     /**
      * Collects the window containers which need to be synced with the changing display area into
      * the current collecting transition.
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index 5c77aa2..19a0c5e 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -27,7 +27,7 @@
 import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
-import android.util.Log;
+import android.util.Slog;
 
 import java.util.ArrayList;
 import java.util.Set;
@@ -67,7 +67,8 @@
                 .createNewSession(mContext, mUserId, providerInfo,
                         this, remoteCredentialService);
         if (providerClearSession != null) {
-            Log.i(TAG, "In startProviderSession - provider session created and being added");
+            Slog.d(TAG, "In startProviderSession - provider session created "
+                    + "and being added for: " + providerInfo.getComponentName());
             mProviders.put(providerClearSession.getComponentName().flattenToString(),
                     providerClearSession);
         }
@@ -77,12 +78,12 @@
     @Override // from provider session
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName, ProviderSession.CredentialsSource source) {
-        Log.i(TAG, "in onStatusChanged with status: " + status);
+        Slog.d(TAG, "in onStatusChanged with status: " + status + ", and source: " + source);
         if (ProviderSession.isTerminatingStatus(status)) {
-            Log.i(TAG, "in onStatusChanged terminating status");
+            Slog.d(TAG, "in onProviderStatusChanged terminating status");
             onProviderTerminated(componentName);
         } else if (ProviderSession.isCompletionStatus(status)) {
-            Log.i(TAG, "in onStatusChanged isCompletionStatus status");
+            Slog.d(TAG, "in onProviderStatusChanged isCompletionStatus status");
             onProviderResponseComplete(componentName);
         }
     }
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 02aaf86..a04143a 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -33,7 +33,7 @@
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.PermissionUtils;
-import android.util.Log;
+import android.util.Slog;
 
 import com.android.server.credentials.metrics.ProviderStatusForMetrics;
 
@@ -77,7 +77,8 @@
                 .createNewSession(mContext, mUserId, providerInfo,
                         this, remoteCredentialService);
         if (providerCreateSession != null) {
-            Log.i(TAG, "In startProviderSession - provider session created and being added");
+            Slog.d(TAG, "In initiateProviderSession - provider session created and "
+                    + "being added for: " + providerInfo.getComponentName());
             mProviders.put(providerCreateSession.getComponentName().flattenToString(),
                     providerCreateSession);
         }
@@ -120,7 +121,7 @@
     @Override
     public void onFinalResponseReceived(ComponentName componentName,
             @Nullable CreateCredentialResponse response) {
-        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
+        Slog.d(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
         mRequestSessionMetric.collectUiResponseData(/*uiReturned=*/ true, System.nanoTime());
         mRequestSessionMetric.collectChosenMetricViaCandidateTransfer(mProviders.get(
                 componentName.flattenToString()).mProviderSessionMetric
@@ -163,13 +164,13 @@
     @Override
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName, ProviderSession.CredentialsSource source) {
-        Log.i(TAG, "in onProviderStatusChanged with status: " + status);
+        Slog.d(TAG, "in onStatusChanged with status: " + status + ", and source: " + source);
         // If all provider responses have been received, we can either need the UI,
         // or we need to respond with error. The only other case is the entry being
         // selected after the UI has been invoked which has a separate code path.
         if (!isAnyProviderPending()) {
             if (isUiInvocationNeeded()) {
-                Log.i(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
+                Slog.d(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
                 getProviderDataAndInitiateUi();
             } else {
                 respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index c44e665..aeb4801 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -30,7 +30,7 @@
 import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
-import android.util.Log;
+import android.util.Slog;
 
 import com.android.server.credentials.metrics.ProviderStatusForMetrics;
 
@@ -77,7 +77,8 @@
                 .createNewSession(mContext, mUserId, providerInfo,
                         this, remoteCredentialService);
         if (providerGetSession != null) {
-            Log.i(TAG, "In startProviderSession - provider session created and being added");
+            Slog.d(TAG, "In startProviderSession - provider session created and "
+                    + "being added for: " + providerInfo.getComponentName());
             mProviders.put(providerGetSession.getComponentName().flattenToString(),
                     providerGetSession);
         }
@@ -116,7 +117,7 @@
     @Override
     public void onFinalResponseReceived(ComponentName componentName,
             @Nullable GetCredentialResponse response) {
-        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
+        Slog.d(TAG, "onFinalResponseReceived from: " + componentName.flattenToString());
         mRequestSessionMetric.collectUiResponseData(/*uiReturned=*/ true, System.nanoTime());
         mRequestSessionMetric.collectChosenMetricViaCandidateTransfer(
                 mProviders.get(componentName.flattenToString())
@@ -160,7 +161,7 @@
     @Override
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName, ProviderSession.CredentialsSource source) {
-        Log.i(TAG, "in onStatusChanged with status: " + status + "and source: " + source);
+        Slog.d(TAG, "in onStatusChanged with status: " + status + ", and source: " + source);
 
         // Auth entry was selected, and it did not have any underlying credentials
         if (status == ProviderSession.Status.NO_CREDENTIALS_FROM_AUTH_ENTRY) {
@@ -173,7 +174,7 @@
             // or we need to respond with error. The only other case is the entry being
             // selected after the UI has been invoked which has a separate code path.
             if (isUiInvocationNeeded()) {
-                Log.i(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
+                Slog.d(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
                 getProviderDataAndInitiateUi();
             } else {
                 respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
diff --git a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
index f274e65..9e7a87e 100644
--- a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
@@ -33,7 +33,6 @@
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.PermissionUtils;
-import android.util.Log;
 import android.util.Slog;
 
 import java.util.ArrayList;
@@ -67,6 +66,9 @@
     @Override
     public void onProviderStatusChanged(ProviderSession.Status status, ComponentName componentName,
             ProviderSession.CredentialsSource source) {
+        Slog.d(TAG, "in onProviderStatusChanged with status: " + status + ", and "
+                + "source: " + source);
+
         switch (source) {
             case REMOTE_PROVIDER:
                 // Remote provider's status changed. We should check if all providers are done, and
@@ -123,7 +125,7 @@
                             hasPermission,
                             credentialTypes, hasAuthenticationResults, hasRemoteResults, uiIntent));
         } catch (RemoteException e) {
-            Log.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e);
+            Slog.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e);
         }
     }
 
@@ -138,7 +140,7 @@
                             /*hasRemoteResults=*/ false,
                             /*pendingIntent=*/ null));
         } catch (RemoteException e) {
-            Log.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e);
+            Slog.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e);
         }
     }
 
@@ -179,10 +181,8 @@
     private PendingIntent getUiIntent() {
         ArrayList<ProviderData> providerDataList = new ArrayList<>();
         for (ProviderSession session : mProviders.values()) {
-            Log.i(TAG, "preparing data for : " + session.getComponentName());
             ProviderData providerData = session.prepareUiData();
             if (providerData != null) {
-                Log.i(TAG, "Provider data is not null");
                 providerDataList.add(providerData);
             }
         }
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index e98c524..8fd0269 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -32,7 +32,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.credentials.CallingAppInfo;
-import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -179,7 +178,7 @@
     @Override // from CredentialManagerUiCallbacks
     public void onUiSelection(UserSelectionDialogResult selection) {
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
-            Log.i(TAG, "Request has already been completed. This is strange.");
+            Slog.w(TAG, "Request has already been completed. This is strange.");
             return;
         }
         if (isSessionCancelled()) {
@@ -187,13 +186,11 @@
             return;
         }
         String providerId = selection.getProviderId();
-        Log.i(TAG, "onUiSelection, providerId: " + providerId);
         ProviderSession providerSession = mProviders.get(providerId);
         if (providerSession == null) {
-            Log.i(TAG, "providerSession not found in onUiSelection");
+            Slog.w(TAG, "providerSession not found in onUiSelection. This is strange.");
             return;
         }
-        Log.i(TAG, "Provider session found");
         mRequestSessionMetric.collectMetricPerBrowsingSelect(selection,
                 providerSession.mProviderSessionMetric.getCandidatePhasePerProviderMetric());
         providerSession.onUiEntrySelected(selection.getEntryKey(),
@@ -247,15 +244,13 @@
     void getProviderDataAndInitiateUi() {
         ArrayList<ProviderData> providerDataList = getProviderDataForUi();
         if (!providerDataList.isEmpty()) {
-            Log.i(TAG, "provider list not empty about to initiate ui");
             launchUiWithProviderData(providerDataList);
         }
     }
 
     @NonNull
     protected ArrayList<ProviderData> getProviderDataForUi() {
-        Log.i(TAG, "In getProviderDataAndInitiateUi");
-        Log.i(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
+        Slog.d(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
         ArrayList<ProviderData> providerDataList = new ArrayList<>();
         mRequestSessionMetric.logCandidatePhaseMetrics(mProviders);
 
@@ -265,10 +260,8 @@
         }
 
         for (ProviderSession session : mProviders.values()) {
-            Log.i(TAG, "preparing data for : " + session.getComponentName());
             ProviderData providerData = session.prepareUiData();
             if (providerData != null) {
-                Log.i(TAG, "Provider data is not null");
                 providerDataList.add(providerData);
             }
         }
@@ -284,7 +277,7 @@
         mRequestSessionMetric.collectFinalPhaseProviderMetricStatus(/*has_exception=*/ false,
                 ProviderStatusForMetrics.FINAL_SUCCESS);
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
-            Log.i(TAG, "Request has already been completed. This is strange.");
+            Slog.w(TAG, "Request has already been completed. This is strange.");
             return;
         }
         if (isSessionCancelled()) {
@@ -300,7 +293,7 @@
         } catch (RemoteException e) {
             mRequestSessionMetric.collectFinalPhaseProviderMetricStatus(
                     /*has_exception=*/ true, ProviderStatusForMetrics.FINAL_FAILURE);
-            Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
+            Slog.e(TAG, "Issue while responding to client with a response : " + e);
             mRequestSessionMetric.logApiCalledAtFinish(
                     /*apiStatus=*/ ApiStatus.FAILURE.getMetricCode());
         }
@@ -317,7 +310,7 @@
         mRequestSessionMetric.collectFinalPhaseProviderMetricStatus(
                 /*has_exception=*/ true, ProviderStatusForMetrics.FINAL_FAILURE);
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
-            Log.i(TAG, "Request has already been completed. This is strange.");
+            Slog.w(TAG, "Request has already been completed. This is strange.");
             return;
         }
         if (isSessionCancelled()) {
@@ -330,7 +323,7 @@
         try {
             invokeClientCallbackError(errorType, errorMsg);
         } catch (RemoteException e) {
-            Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
+            Slog.e(TAG, "Issue while responding to client with error : " + e);
         }
         boolean isUserCanceled = errorType.contains(MetricUtilities.USER_CANCELED_SUBSTRING);
         mRequestSessionMetric.logFailureOrUserCancel(isUserCanceled);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index ba9f809..7330411 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -24,6 +24,7 @@
 import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -1063,6 +1064,51 @@
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
     }
 
+    private void updateAllDisplayContentAndRotation(DisplayContent dc) {
+        // NB updateOrientation will not revert the user orientation until a settings change
+        // takes effect.
+        dc.updateOrientation();
+        dc.onDisplayChanged(dc);
+        dc.mWmService.updateRotation(true /* alwaysSendConfiguration */,
+                false /* forceRelayout */);
+        waitUntilHandlersIdle();
+    }
+
+    @Test
+    public void testNoSensorRevert() {
+        final DisplayContent dc = mDisplayContent;
+        spyOn(dc);
+        doReturn(true).when(dc).getIgnoreOrientationRequest();
+        final DisplayRotation dr = dc.getDisplayRotation();
+        spyOn(dr);
+        doReturn(false).when(dr).useDefaultSettingsProvider();
+        final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        app.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, app);
+
+        assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
+        dc.getDisplayRotation().setUserRotation(WindowManagerPolicy.USER_ROTATION_LOCKED,
+                ROTATION_90);
+        updateAllDisplayContentAndRotation(dc);
+        assertEquals(ROTATION_90, dc.getDisplayRotation()
+                .rotationForOrientation(SCREEN_ORIENTATION_UNSPECIFIED, ROTATION_90));
+
+        app.setOrientation(SCREEN_ORIENTATION_NOSENSOR);
+        updateAllDisplayContentAndRotation(dc);
+        assertTrue(dc.getRotationReversionController().isAnyOverrideActive());
+        assertEquals(ROTATION_0, dc.getRotation());
+
+        app.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
+        updateAllDisplayContentAndRotation(dc);
+        assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED,
+                dc.getDisplayRotation().getUserRotationMode());
+        assertEquals(ROTATION_90, dc.getDisplayRotation().getUserRotation());
+        assertEquals(ROTATION_90, dc.getDisplayRotation()
+                .rotationForOrientation(SCREEN_ORIENTATION_UNSPECIFIED, ROTATION_0));
+        dc.getDisplayRotation().setUserRotation(WindowManagerPolicy.USER_ROTATION_FREE,
+                ROTATION_0);
+    }
+
     @Test
     public void testOnDescendantOrientationRequestChanged() {
         final DisplayContent dc = createNewDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index c2b3783..a311726 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -365,6 +365,23 @@
     }
 
     @Test
+    public void testCameraDisconnected_revertRotationAndRefresh() throws Exception {
+        configureActivityAndDisplay(SCREEN_ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE);
+        // Open camera and test for compat treatment
+        mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+        callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true);
+        assertEquals(mDisplayRotationCompatPolicy.getOrientation(),
+                SCREEN_ORIENTATION_LANDSCAPE);
+        assertActivityRefreshRequested(/* refreshRequested */ true);
+        // Close camera and test for revert
+        mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+        callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true);
+        assertEquals(mDisplayRotationCompatPolicy.getOrientation(),
+                SCREEN_ORIENTATION_UNSPECIFIED);
+        assertActivityRefreshRequested(/* refreshRequested */ true);
+    }
+
+    @Test
     public void testGetOrientation_cameraConnectionClosed_returnUnspecified() {
         configureActivity(SCREEN_ORIENTATION_PORTRAIT);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 19a1edd..4b2d107 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -115,6 +115,7 @@
 
     private static WindowManagerService sMockWm;
     private DisplayContent mMockDisplayContent;
+    private DisplayRotationReversionController mMockDisplayRotationReversionController;
     private DisplayPolicy mMockDisplayPolicy;
     private DisplayAddress mMockDisplayAddress;
     private Context mMockContext;
@@ -1409,6 +1410,10 @@
             when(mMockContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_windowManagerHalfFoldAutoRotateOverride))
                     .thenReturn(mSupportHalfFoldAutoRotateOverride);
+            mMockDisplayRotationReversionController =
+                    mock(DisplayRotationReversionController.class);
+            when(mMockDisplayContent.getRotationReversionController())
+                        .thenReturn(mMockDisplayRotationReversionController);
 
             mMockResolver = mock(ContentResolver.class);
             when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
diff --git a/telecomm/java/android/telecom/CallAttributes.java b/telecomm/java/android/telecom/CallAttributes.java
index f3ef834..52ff90f 100644
--- a/telecomm/java/android/telecom/CallAttributes.java
+++ b/telecomm/java/android/telecom/CallAttributes.java
@@ -59,7 +59,10 @@
     public static final String CALL_CAPABILITIES_KEY = "TelecomCapabilities";
 
     /** @hide **/
-    public static final String CALLER_PID = "CallerPid";
+    public static final String CALLER_PID_KEY = "CallerPid";
+
+    /** @hide **/
+    public static final String CALLER_UID_KEY = "CallerUid";
 
     private CallAttributes(@NonNull PhoneAccountHandle phoneAccountHandle,
             @NonNull CharSequence displayName,