Merge "Adds the old timezone to dumpsys logs after a timezone update." into main
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f58baff..4fc894c 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -789,6 +789,12 @@
             in @nullable ImeTracker.Token statsToken);
 
     /**
+     * Updates the currently animating insets types of a remote process.
+     */
+    @EnforcePermission("MANAGE_APP_TOKENS")
+    void updateDisplayWindowAnimatingTypes(int displayId, int animatingTypes);
+
+    /**
      * Called to get the expected window insets.
      *
      * @return {@code true} if system bars are always consumed.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1f8f0820..7d6d5a2 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -272,6 +272,15 @@
             in @nullable ImeTracker.Token imeStatsToken);
 
     /**
+     * Notifies WindowState what insets types are currently running within the Window.
+     * see {@link com.android.server.wm.WindowState#mInsetsAnimationRunning).
+     *
+     * @param window The window that is insets animaiton is running.
+     * @param animatingTypes Indicates the currently animating insets types.
+     */
+    oneway void updateAnimatingTypes(IWindow window, int animatingTypes);
+
+    /**
      * Called when the system gesture exclusion has changed.
      */
     oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
@@ -372,14 +381,4 @@
      */
     oneway void notifyImeWindowVisibilityChangedFromClient(IWindow window, boolean visible,
             in ImeTracker.Token statsToken);
-
-    /**
-     * Notifies WindowState whether inset animations are currently running within the Window.
-     * This value is used by the server to vote for refresh rate.
-     * see {@link com.android.server.wm.WindowState#mInsetsAnimationRunning).
-     *
-     * @param window The window that is insets animaiton is running.
-     * @param running Indicates the insets animation state.
-     */
-    oneway void notifyInsetsAnimationRunningStateChanged(IWindow window, boolean running);
 }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 0d82acd..462c5c6 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -211,12 +211,12 @@
         }
 
         /**
-         * Notifies when the state of running animation is changed. The state is either "running" or
-         * "idle".
+         * Notifies when the insets types of running animation have changed. The animatingTypes
+         * contain all types, which have an ongoing animation.
          *
-         * @param running {@code true} if there is any animation running; {@code false} otherwise.
+         * @param animatingTypes the {@link InsetsType}s that are currently animating
          */
-        default void notifyAnimationRunningStateChanged(boolean running) {}
+        default void updateAnimatingTypes(@InsetsType int animatingTypes) {}
 
         /** @see ViewRootImpl#isHandlingPointerEvent */
         default boolean isHandlingPointerEvent() {
@@ -665,6 +665,9 @@
     /** Set of inset types which are requested visible which are reported to the host */
     private @InsetsType int mReportedRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
 
+    /** Set of insets types which are currently animating */
+    private @InsetsType int mAnimatingTypes = 0;
+
     /** Set of inset types that we have controls of */
     private @InsetsType int mControllableTypes;
 
@@ -745,9 +748,10 @@
                             mFrame, mFromState, mToState, RESIZE_INTERPOLATOR,
                             ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this);
                     if (mRunningAnimations.isEmpty()) {
-                        mHost.notifyAnimationRunningStateChanged(true);
+                        mHost.updateAnimatingTypes(runner.getTypes());
                     }
                     mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
+                    mAnimatingTypes |= runner.getTypes();
                 }
             };
 
@@ -1564,9 +1568,8 @@
             }
         }
         ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
-        if (mRunningAnimations.isEmpty()) {
-            mHost.notifyAnimationRunningStateChanged(true);
-        }
+        mAnimatingTypes |= runner.getTypes();
+        mHost.updateAnimatingTypes(mAnimatingTypes);
         mRunningAnimations.add(new RunningAnimation(runner, animationType));
         if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
                 + useInsetsAnimationThread);
@@ -1827,7 +1830,7 @@
                     dispatchAnimationEnd(runningAnimation.runner.getAnimation());
                 } else {
                     if (Flags.refactorInsetsController()) {
-                        if (removedTypes == ime()
+                        if ((removedTypes & ime()) != 0
                                 && control.getAnimationType() == ANIMATION_TYPE_HIDE) {
                             if (mHost != null) {
                                 // if the (hide) animation is cancelled, the
@@ -1842,9 +1845,11 @@
                 break;
             }
         }
-        if (mRunningAnimations.isEmpty()) {
-            mHost.notifyAnimationRunningStateChanged(false);
+        if (removedTypes > 0) {
+            mAnimatingTypes &= ~removedTypes;
+            mHost.updateAnimatingTypes(mAnimatingTypes);
         }
+
         onAnimationStateChanged(removedTypes, false /* running */);
     }
 
@@ -1969,14 +1974,6 @@
         return animatingTypes;
     }
 
-    private @InsetsType int computeAnimatingTypes() {
-        int animatingTypes = 0;
-        for (int i = 0; i < mRunningAnimations.size(); i++) {
-            animatingTypes |= mRunningAnimations.get(i).runner.getTypes();
-        }
-        return animatingTypes;
-    }
-
     /**
      * Called when finishing setting requested visible types or finishing setting controls.
      *
@@ -1989,7 +1986,7 @@
             // report its requested visibility at the end of the animation, otherwise we would
             // lose the leash, and it would disappear during the animation
             // TODO(b/326377046) revisit this part and see if we can make it more general
-            typesToReport = mRequestedVisibleTypes | (computeAnimatingTypes() & ime());
+            typesToReport = mRequestedVisibleTypes | (mAnimatingTypes & ime());
         } else {
             typesToReport = mRequestedVisibleTypes;
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9498407..7fd7be8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2540,11 +2540,12 @@
     }
 
     /**
-     * Notify the when the running state of a insets animation changed.
+     * Notify the when the animating insets types have changed.
      */
     @VisibleForTesting
-    public void notifyInsetsAnimationRunningStateChanged(boolean running) {
+    public void updateAnimatingTypes(@InsetsType int animatingTypes) {
         if (sToolkitSetFrameRateReadOnlyFlagValue) {
+            boolean running = animatingTypes != 0;
             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                 Trace.instant(Trace.TRACE_TAG_VIEW,
                         TextUtils.formatSimple("notifyInsetsAnimationRunningStateChanged(%s)",
@@ -2552,7 +2553,7 @@
             }
             mInsetsAnimationRunning = running;
             try {
-                mWindowSession.notifyInsetsAnimationRunningStateChanged(mWindow, running);
+                mWindowSession.updateAnimatingTypes(mWindow, animatingTypes);
             } catch (RemoteException e) {
             }
         }
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 889acca4..8954df6 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -171,6 +171,13 @@
     }
 
     @Override
+    public void updateAnimatingTypes(@WindowInsets.Type.InsetsType int animatingTypes) {
+        if (mViewRoot != null) {
+            mViewRoot.updateAnimatingTypes(animatingTypes);
+        }
+    }
+
+    @Override
     public boolean hasAnimationCallbacks() {
         if (mViewRoot.mView == null) {
             return false;
@@ -275,13 +282,6 @@
     }
 
     @Override
-    public void notifyAnimationRunningStateChanged(boolean running) {
-        if (mViewRoot != null) {
-            mViewRoot.notifyInsetsAnimationRunningStateChanged(running);
-        }
-    }
-
-    @Override
     public boolean isHandlingPointerEvent() {
         return mViewRoot != null && mViewRoot.isHandlingPointerEvent();
     }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 72a595d..0a86ff8 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -597,6 +597,11 @@
     }
 
     @Override
+    public void updateAnimatingTypes(IWindow window, @InsetsType int animatingTypes) {
+        // NO-OP
+    }
+
+    @Override
     public void reportSystemGestureExclusionChanged(android.view.IWindow window,
             List<Rect> exclusionRects) {
     }
@@ -679,11 +684,6 @@
             @NonNull ImeTracker.Token statsToken) {
     }
 
-    @Override
-    public void notifyInsetsAnimationRunningStateChanged(IWindow window, boolean running) {
-        // NO-OP
-    }
-
     void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
         IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder();
         IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder();
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index 16f4114..c81c2bb 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -196,3 +196,10 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "report_animating_insets_types"
+  namespace: "input_method"
+  description: "Adding animating insets types and report IME visibility at the beginning of hiding"
+  bug: "393049691"
+}
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9acb242..a1961ae 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -268,6 +268,9 @@
      72dp (content margin) - 12dp (action padding) - 4dp (button inset) -->
     <dimen name="notification_2025_actions_margin_start">56dp</dimen>
 
+    <!-- Notification action button text size -->
+    <dimen name="notification_2025_action_text_size">16sp</dimen>
+
     <!-- The margin on the end of most content views (ignores the expander) -->
     <dimen name="notification_content_margin_end">16dp</dimen>
 
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4516e9c..af87af0 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -1195,6 +1195,23 @@
         });
     }
 
+    @Test
+    public void testAnimatingTypes() throws Exception {
+        prepareControls();
+
+        final int types = navigationBars() | statusBars();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            clearInvocations(mTestHost);
+            mController.hide(types);
+            // quickly jump to final state by cancelling it.
+            mController.cancelExistingAnimations();
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(mTestHost, times(1)).updateAnimatingTypes(eq(types));
+        verify(mTestHost, times(1)).updateAnimatingTypes(eq(0) /* animatingTypes */);
+    }
+
     private void waitUntilNextFrame() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index c40137f..f5d1e7a 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -1054,7 +1054,7 @@
         ViewRootImpl viewRootImpl = mView.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
             mView.invalidate();
-            viewRootImpl.notifyInsetsAnimationRunningStateChanged(true);
+            viewRootImpl.updateAnimatingTypes(Type.systemBars());
             mView.invalidate();
         });
         sInstrumentation.waitForIdleSync();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index df82091..dd2050a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -461,6 +461,14 @@
             }
         }
 
+        private void setAnimating(boolean imeAnimationOngoing) {
+            int animatingTypes = imeAnimationOngoing ? WindowInsets.Type.ime() : 0;
+            try {
+                mWmService.updateDisplayWindowAnimatingTypes(mDisplayId, animatingTypes);
+            } catch (RemoteException e) {
+            }
+        }
+
         private int imeTop(float surfaceOffset, float surfacePositionY) {
             // surfaceOffset is already offset by the surface's top inset, so we need to subtract
             // the top inset so that the return value is in screen coordinates.
@@ -619,6 +627,9 @@
                                 + imeTop(hiddenY, defaultY) + "->" + imeTop(shownY, defaultY)
                                 + " showing:" + (mAnimationDirection == DIRECTION_SHOW));
                     }
+                    if (android.view.inputmethod.Flags.reportAnimatingInsetsTypes()) {
+                        setAnimating(true);
+                    }
                     int flags = dispatchStartPositioning(mDisplayId, imeTop(hiddenY, defaultY),
                             imeTop(shownY, defaultY), mAnimationDirection == DIRECTION_SHOW,
                             isFloating, t);
@@ -666,6 +677,8 @@
                     }
                     if (!android.view.inputmethod.Flags.refactorInsetsController()) {
                         dispatchEndPositioning(mDisplayId, mCancelled, t);
+                    } else if (android.view.inputmethod.Flags.reportAnimatingInsetsTypes()) {
+                        setAnimating(false);
                     }
                     if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
                         ImeTracker.forLogging().onProgress(mStatsToken,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
index fba6151..da3cebd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.qs.FakeTileDetailsViewModel
 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
 import com.android.systemui.qs.tiles.base.interactor.FakeDisabledByPolicyInteractor
 import com.android.systemui.qs.tiles.base.interactor.FakeQSTileDataInteractor
@@ -97,6 +98,7 @@
                 testCoroutineDispatcher,
                 testCoroutineDispatcher,
                 testScope.backgroundScope,
+                FakeTileDetailsViewModel("QSTileViewModelImplTest"),
             )
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
index 3db5efc..261e3de 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
@@ -26,8 +26,6 @@
 import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
 import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
 import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
-import com.android.systemui.qs.tiles.dialog.InternetDetailsContentManager
-import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
 import com.android.systemui.qs.tiles.dialog.InternetDialogManager
 import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
 import com.android.systemui.statusbar.connectivity.AccessPointController
@@ -39,11 +37,8 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.eq
-import org.mockito.kotlin.any
 import org.mockito.kotlin.mock
-import org.mockito.kotlin.times
 import org.mockito.kotlin.verify
-import org.mockito.kotlin.whenever
 
 @SmallTest
 @EnabledOnRavenwood
@@ -56,31 +51,17 @@
 
     private lateinit var internetDialogManager: InternetDialogManager
     private lateinit var controller: AccessPointController
-    private lateinit var internetDetailsViewModelFactory: InternetDetailsViewModel.Factory
-    private lateinit var internetDetailsContentManagerFactory: InternetDetailsContentManager.Factory
-    private lateinit var internetDetailsViewModel: InternetDetailsViewModel
 
     @Before
     fun setup() {
         internetDialogManager = mock<InternetDialogManager>()
         controller = mock<AccessPointController>()
-        internetDetailsViewModelFactory = mock<InternetDetailsViewModel.Factory>()
-        internetDetailsContentManagerFactory = mock<InternetDetailsContentManager.Factory>()
-        internetDetailsViewModel =
-            InternetDetailsViewModel(
-                onLongClick = {},
-                accessPointController = mock<AccessPointController>(),
-                contentManagerFactory = internetDetailsContentManagerFactory,
-            )
-        whenever(internetDetailsViewModelFactory.create(any())).thenReturn(internetDetailsViewModel)
-
         underTest =
             InternetTileUserActionInteractor(
                 kosmos.testScope.coroutineContext,
                 internetDialogManager,
                 controller,
                 inputHandler,
-                internetDetailsViewModelFactory,
             )
     }
 
@@ -127,12 +108,4 @@
                 assertThat(it.intent.action).isEqualTo(Settings.ACTION_WIFI_SETTINGS)
             }
         }
-
-    @Test
-    fun detailsViewModel() =
-        kosmos.testScope.runTest {
-            assertThat(underTest.detailsViewModel.getTitle()).isEqualTo("Internet")
-            assertThat(underTest.detailsViewModel.getSubTitle())
-                .isEqualTo("Tab a network to connect")
-        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt
index 0598a8b..4e9b635 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.coroutines.collectValues
+import com.android.systemui.qs.FakeTileDetailsViewModel
 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.base.interactor.FakeDisabledByPolicyInteractor
@@ -171,21 +172,6 @@
                 .isEqualTo(FakeQSTileDataInteractor.AvailabilityRequest(USER))
         }
 
-    @Test
-    fun tileDetails() =
-        testScope.runTest {
-            assertThat(tileUserActionInteractor.detailsViewModel).isNotNull()
-            assertThat(tileUserActionInteractor.detailsViewModel?.getTitle())
-                .isEqualTo("FakeQSTileUserActionInteractor")
-            assertThat(underTest.detailsViewModel).isNotNull()
-            assertThat(underTest.detailsViewModel?.getTitle())
-                .isEqualTo("FakeQSTileUserActionInteractor")
-
-            tileUserActionInteractor.detailsViewModel = null
-            assertThat(tileUserActionInteractor.detailsViewModel).isNull()
-            assertThat(underTest.detailsViewModel).isNull()
-        }
-
     private fun createViewModel(
         scope: TestScope,
         config: QSTileConfig = tileConfig,
@@ -209,6 +195,7 @@
             testCoroutineDispatcher,
             testCoroutineDispatcher,
             scope.backgroundScope,
+            FakeTileDetailsViewModel("QSTileViewModelTest"),
         )
 
     private companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt
index ece21e1..166e950 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.qs.FakeTileDetailsViewModel
 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.base.interactor.FakeDisabledByPolicyInteractor
@@ -253,5 +254,6 @@
             testCoroutineDispatcher,
             testCoroutineDispatcher,
             scope.backgroundScope,
+            FakeTileDetailsViewModel("QSTileViewModelUserInputTest"),
         )
 }
diff --git a/packages/SystemUI/res/drawable/notification_2025_guts_priority_button_bg.xml b/packages/SystemUI/res/drawable/notification_2025_guts_priority_button_bg.xml
new file mode 100644
index 0000000..1de8c2b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_2025_guts_priority_button_bg.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2025 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
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle" >
+    <solid
+        android:color="@color/notification_guts_priority_button_bg_fill" />
+
+    <stroke
+        android:width="1.5dp"
+        android:color="@color/notification_guts_priority_button_bg_stroke" />
+
+    <corners android:radius="16dp" />
+</shape>
diff --git a/packages/SystemUI/res/layout/notification_2025_info.xml b/packages/SystemUI/res/layout/notification_2025_info.xml
new file mode 100644
index 0000000..7b69166
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_2025_info.xml
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2025, 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.
+-->
+
+<!-- extends LinearLayout -->
+<com.android.systemui.statusbar.notification.row.NotificationInfo
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/notification_guts"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:focusable="true"
+    android:clipChildren="false"
+    android:clipToPadding="true"
+    android:orientation="vertical"
+    android:paddingStart="@*android:dimen/notification_2025_margin">
+
+    <!-- Package Info -->
+    <LinearLayout
+        android:id="@+id/header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:clipChildren="false"
+        android:clipToPadding="true">
+        <ImageView
+            android:id="@+id/pkg_icon"
+            android:layout_width="@*android:dimen/notification_2025_icon_circle_size"
+            android:layout_height="@*android:dimen/notification_2025_icon_circle_size"
+            android:layout_marginTop="@*android:dimen/notification_2025_margin"
+            android:layout_marginEnd="@*android:dimen/notification_2025_margin" />
+        <LinearLayout
+            android:id="@+id/names"
+            android:layout_weight="1"
+            android:layout_width="0dp"
+            android:orientation="vertical"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@*android:dimen/notification_2025_margin"
+            android:minHeight="@*android:dimen/notification_2025_icon_circle_size">
+            <TextView
+                android:id="@+id/channel_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textDirection="locale"
+                style="@style/TextAppearance.NotificationImportanceChannel"/>
+            <TextView
+                android:id="@+id/group_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textDirection="locale"
+                android:ellipsize="end"
+                style="@style/TextAppearance.NotificationImportanceChannelGroup"/>
+            <TextView
+                android:id="@+id/pkg_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="@style/TextAppearance.NotificationImportanceApp"
+                android:ellipsize="end"
+                android:textDirection="locale"
+                android:maxLines="1"/>
+            <TextView
+                android:id="@+id/delegate_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="@style/TextAppearance.NotificationImportanceHeader"
+                android:ellipsize="end"
+                android:textDirection="locale"
+                android:text="@string/notification_delegate_header"
+                android:maxLines="1" />
+
+        </LinearLayout>
+
+        <!-- feedback for notificationassistantservice -->
+        <ImageButton
+            android:id="@+id/feedback"
+            android:layout_width="@dimen/notification_2025_guts_button_size"
+            android:layout_height="@dimen/notification_2025_guts_button_size"
+            android:visibility="gone"
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/notification_guts_bundle_feedback"
+            android:src="@*android:drawable/ic_feedback"
+            android:paddingTop="@*android:dimen/notification_2025_margin"
+            android:tint="@androidprv:color/materialColorPrimary"/>
+
+        <!-- Optional link to app. Only appears if the channel is not disabled and the app
+        asked for it -->
+        <ImageButton
+            android:id="@+id/app_settings"
+            android:layout_width="@dimen/notification_2025_guts_button_size"
+            android:layout_height="@dimen/notification_2025_guts_button_size"
+            android:visibility="gone"
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/notification_app_settings"
+            android:src="@drawable/ic_info"
+            android:paddingTop="@*android:dimen/notification_2025_margin"
+            android:tint="@androidprv:color/materialColorPrimary"/>
+
+        <!-- System notification settings -->
+        <ImageButton
+            android:id="@+id/info"
+            android:layout_width="@dimen/notification_2025_guts_button_size"
+            android:layout_height="@dimen/notification_2025_guts_button_size"
+            android:contentDescription="@string/notification_more_settings"
+            android:background="@drawable/ripple_drawable"
+            android:src="@drawable/ic_settings"
+            android:padding="@*android:dimen/notification_2025_margin"
+            android:tint="@androidprv:color/materialColorPrimary" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/inline_controls"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@*android:dimen/notification_2025_margin"
+        android:layout_marginTop="@*android:dimen/notification_2025_margin"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:orientation="vertical">
+
+        <!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings-->
+        <TextView
+            android:id="@+id/non_configurable_text"
+            android:text="@string/notification_unblockable_desc"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+
+        <!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings-->
+        <TextView
+            android:id="@+id/non_configurable_call_text"
+            android:text="@string/notification_unblockable_call_desc"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+
+        <!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings-->
+        <TextView
+            android:id="@+id/non_configurable_multichannel_text"
+            android:text="@string/notification_multichannel_desc"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+
+        <LinearLayout
+            android:id="@+id/interruptiveness_settings"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:orientation="vertical">
+            <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+                android:id="@+id/automatic"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingVertical="@dimen/notification_2025_importance_button_padding_vertical"
+                android:paddingHorizontal="@dimen/notification_2025_importance_button_padding_horizontal"
+                android:gravity="center_vertical"
+                android:clickable="true"
+                android:focusable="true"
+                android:background="@drawable/notification_2025_guts_priority_button_bg"
+                android:orientation="horizontal"
+                android:visibility="gone">
+                <ImageView
+                    android:id="@+id/automatic_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:paddingEnd="@*android:dimen/notification_2025_margin"
+                    android:src="@drawable/ic_notifications_automatic"
+                    android:background="@android:color/transparent"
+                    android:tint="@color/notification_guts_priority_contents"
+                    android:clickable="false"
+                    android:focusable="false"/>
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    android:gravity="center"
+                >
+                    <TextView
+                        android:id="@+id/automatic_label"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:maxLines="1"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+                        android:text="@string/notification_automatic_title"/>
+                    <TextView
+                        android:id="@+id/automatic_summary"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
+                        android:visibility="gone"
+                        android:text="@string/notification_channel_summary_automatic"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:ellipsize="end"
+                        android:maxLines="2"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+                </LinearLayout>
+            </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
+
+            <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+                android:id="@+id/alert"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingVertical="@dimen/notification_2025_importance_button_padding_vertical"
+                android:paddingHorizontal="@dimen/notification_2025_importance_button_padding_horizontal"
+                android:gravity="center_vertical"
+                android:clickable="true"
+                android:focusable="true"
+                android:background="@drawable/notification_2025_guts_priority_button_bg"
+                android:orientation="horizontal">
+                <ImageView
+                    android:id="@+id/alert_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:paddingEnd="@*android:dimen/notification_2025_margin"
+                    android:src="@drawable/ic_notifications_alert"
+                    android:background="@android:color/transparent"
+                    android:tint="@color/notification_guts_priority_contents"
+                    android:clickable="false"
+                    android:focusable="false"/>
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    android:gravity="center"
+                    >
+                    <TextView
+                        android:id="@+id/alert_label"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:maxLines="1"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+                        android:text="@string/notification_alert_title"/>
+                    <TextView
+                        android:id="@+id/alert_summary"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:visibility="gone"
+                        android:text="@string/notification_channel_summary_default"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:ellipsize="end"
+                        android:maxLines="2"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+                </LinearLayout>
+            </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
+
+            <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+                android:id="@+id/silence"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/notification_importance_button_separation"
+                android:paddingVertical="@dimen/notification_2025_importance_button_padding_vertical"
+                android:paddingHorizontal="@dimen/notification_2025_importance_button_padding_horizontal"
+                android:gravity="center_vertical"
+                android:clickable="true"
+                android:focusable="true"
+                android:background="@drawable/notification_2025_guts_priority_button_bg"
+                android:orientation="horizontal">
+                <ImageView
+                    android:id="@+id/silence_icon"
+                    android:src="@drawable/ic_notifications_silence"
+                    android:background="@android:color/transparent"
+                    android:tint="@color/notification_guts_priority_contents"
+                    android:layout_gravity="center"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:paddingEnd="@*android:dimen/notification_2025_margin"
+                    android:clickable="false"
+                    android:focusable="false"/>
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    android:gravity="center"
+                    >
+                    <TextView
+                        android:id="@+id/silence_label"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ellipsize="end"
+                        android:maxLines="1"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:layout_toEndOf="@id/silence_icon"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+                        android:text="@string/notification_silence_title"/>
+                    <TextView
+                        android:id="@+id/silence_summary"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:visibility="gone"
+                        android:text="@string/notification_channel_summary_low"
+                        android:clickable="false"
+                        android:focusable="false"
+                        android:ellipsize="end"
+                        android:maxLines="2"
+                        android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+                </LinearLayout>
+            </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/bottom_buttons"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@*android:dimen/notification_2025_margin"
+            android:minHeight="@dimen/notification_2025_guts_button_size"
+            android:gravity="center_vertical"
+            >
+            <TextView
+                android:id="@+id/turn_off_notifications"
+                android:text="@string/inline_turn_off_notifications"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="32dp"
+                android:paddingTop="8dp"
+                android:paddingBottom="@*android:dimen/notification_2025_margin"
+                android:gravity="center"
+                android:minWidth="@dimen/notification_2025_min_tap_target_size"
+                android:minHeight="@dimen/notification_2025_min_tap_target_size"
+                android:maxWidth="200dp"
+                style="@style/TextAppearance.NotificationInfo.Button"
+                android:textSize="@*android:dimen/notification_2025_action_text_size"/>
+            <TextView
+                android:id="@+id/done"
+                android:text="@string/inline_ok_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:paddingBottom="@*android:dimen/notification_2025_margin"
+                android:gravity="center"
+                android:minWidth="@dimen/notification_2025_min_tap_target_size"
+                android:minHeight="@dimen/notification_2025_min_tap_target_size"
+                android:maxWidth="125dp"
+                style="@style/TextAppearance.NotificationInfo.Button"
+                android:textSize="@*android:dimen/notification_2025_action_text_size"/>
+        </LinearLayout>
+    </LinearLayout>
+</com.android.systemui.statusbar.notification.row.NotificationInfo>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 640e1fa..7c370d3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -390,6 +390,12 @@
     <!-- Extra space for guts bundle feedback button -->
     <dimen name="notification_guts_bundle_feedback_size">48dp</dimen>
 
+    <!-- Size of icon buttons in notification info. -->
+    <!-- 24dp for the icon itself + 16dp * 2 for top and bottom padding -->
+    <dimen name="notification_2025_guts_button_size">56dp</dimen>
+
+    <dimen name="notification_2025_min_tap_target_size">48dp</dimen>
+
     <dimen name="notification_importance_toggle_size">48dp</dimen>
     <dimen name="notification_importance_button_separation">8dp</dimen>
     <dimen name="notification_importance_drawable_padding">8dp</dimen>
@@ -402,6 +408,10 @@
     <dimen name="notification_importance_button_description_top_margin">12dp</dimen>
     <dimen name="rect_button_radius">8dp</dimen>
 
+    <!-- Padding for importance selection buttons in notification info, 2025 redesign version -->
+    <dimen name="notification_2025_importance_button_padding_vertical">12dp</dimen>
+    <dimen name="notification_2025_importance_button_padding_horizontal">16dp</dimen>
+
     <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
     <dimen name="snooze_snackbar_min_height">56dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
index f80b8fb..e48e943 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
@@ -99,7 +99,7 @@
     }
 
     override fun getDetailsViewModel(): TileDetailsViewModel {
-        return internetDetailsViewModelFactory.create { longClick(null) }
+        return internetDetailsViewModelFactory.create()
     }
 
     override fun handleUpdateState(state: QSTile.BooleanState, arg: Any?) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
index e8c4274..8ad4e16 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
@@ -28,17 +28,4 @@
      * It's safe to run long running computations inside this function.
      */
     @WorkerThread suspend fun handleInput(input: QSTileInput<DATA_TYPE>)
-
-    /**
-     * Provides the [TileDetailsViewModel] for constructing the corresponding details view.
-     *
-     * This property is defined here to reuse the business logic. For example, reusing the user
-     * long-click as the go-to-settings callback in the details view.
-     * Subclasses can override this property to provide a specific [TileDetailsViewModel]
-     * implementation.
-     *
-     * @return The [TileDetailsViewModel] instance, or null if not implemented.
-     */
-    val detailsViewModel: TileDetailsViewModel?
-        get() = null
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
index 8c75cf0..7f475f3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.UiBackground
 import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.TileDetailsViewModel
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
 import com.android.systemui.qs.tiles.base.interactor.DisabledByPolicyInteractor
@@ -70,9 +71,7 @@
          * Creates [QSTileViewModelImpl] based on the interactors obtained from [QSTileComponent].
          * Reference of that [QSTileComponent] is then stored along the view model.
          */
-        fun create(
-            tileSpec: TileSpec,
-        ): QSTileViewModel {
+        fun create(tileSpec: TileSpec): QSTileViewModel {
             val config = qsTileConfigProvider.getConfig(tileSpec.spec)
             val component =
                 customTileComponentBuilder.qsTileConfigModule(QSTileConfigModule(config)).build()
@@ -90,6 +89,7 @@
                 backgroundDispatcher,
                 uiBackgroundDispatcher,
                 component.coroutineScope(),
+                /* tileDetailsViewModel= */ null,
             )
         }
     }
@@ -127,6 +127,7 @@
             userActionInteractor: QSTileUserActionInteractor<T>,
             tileDataInteractor: QSTileDataInteractor<T>,
             mapper: QSTileDataToStateMapper<T>,
+            tileDetailsViewModel: TileDetailsViewModel? = null,
         ): QSTileViewModelImpl<T> =
             QSTileViewModelImpl(
                 qsTileConfigProvider.getConfig(tileSpec.spec),
@@ -142,6 +143,7 @@
                 backgroundDispatcher,
                 uiBackgroundDispatcher,
                 coroutineScopeFactory.create(),
+                tileDetailsViewModel,
             )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
index 30bf5b3..9bdec43 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
@@ -83,6 +83,7 @@
     private val backgroundDispatcher: CoroutineDispatcher,
     uiBackgroundDispatcher: CoroutineDispatcher,
     private val tileScope: CoroutineScope,
+    override val tileDetailsViewModel: TileDetailsViewModel? = null,
 ) : QSTileViewModel, Dumpable {
 
     private val users: MutableStateFlow<UserHandle> =
@@ -114,9 +115,6 @@
             .flowOn(backgroundDispatcher)
             .stateIn(tileScope, SharingStarted.WhileSubscribed(), true)
 
-    override val detailsViewModel: TileDetailsViewModel?
-        get() = userActionInteractor().detailsViewModel
-
     override fun forceUpdate() {
         tileScope.launch(context = backgroundDispatcher) { forceUpdates.emit(Unit) }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
index 0ed56f6..6709fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
@@ -16,9 +16,11 @@
 
 package com.android.systemui.qs.tiles.dialog
 
+import android.content.Intent
+import android.provider.Settings
 import com.android.systemui.plugins.qs.TileDetailsViewModel
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
 import com.android.systemui.statusbar.connectivity.AccessPointController
-import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 
@@ -27,10 +29,13 @@
 constructor(
     private val accessPointController: AccessPointController,
     val contentManagerFactory: InternetDetailsContentManager.Factory,
-    @Assisted private val onLongClick: () -> Unit,
+    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
 ) : TileDetailsViewModel() {
     override fun clickOnSettingsButton() {
-        onLongClick()
+        qsTileIntentUserActionHandler.handle(
+            /* expandable= */ null,
+            Intent(Settings.ACTION_WIFI_SETTINGS),
+        )
     }
 
     override fun getTitle(): String {
@@ -58,7 +63,7 @@
     }
 
     @AssistedFactory
-    interface Factory {
-        fun create(onLongClick: () -> Unit): InternetDetailsViewModel
+    fun interface Factory {
+        fun create(): InternetDetailsViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
index 0ed46e7..5f692f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.impl.di
 
+import com.android.systemui.plugins.qs.TileDetailsViewModel
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
index 8e48fe4..0431e36 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
@@ -18,13 +18,10 @@
 
 import android.content.Intent
 import android.provider.Settings
-import com.android.systemui.animation.Expandable
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.plugins.qs.TileDetailsViewModel
 import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
 import com.android.systemui.qs.tiles.base.interactor.QSTileInput
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
-import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
 import com.android.systemui.qs.tiles.dialog.InternetDialogManager
 import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
@@ -41,7 +38,6 @@
     private val internetDialogManager: InternetDialogManager,
     private val accessPointController: AccessPointController,
     private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
-    private val internetDetailsViewModelFactory: InternetDetailsViewModel.Factory,
 ) : QSTileUserActionInteractor<InternetTileModel> {
 
     override suspend fun handleInput(input: QSTileInput<InternetTileModel>): Unit =
@@ -58,16 +54,12 @@
                     }
                 }
                 is QSTileUserAction.LongClick -> {
-                    handleLongClick(action.expandable)
+                    qsTileIntentUserActionHandler.handle(
+                        action.expandable,
+                        Intent(Settings.ACTION_WIFI_SETTINGS),
+                    )
                 }
                 else -> {}
             }
         }
-
-    override val detailsViewModel: TileDetailsViewModel =
-        internetDetailsViewModelFactory.create { handleLongClick(null) }
-
-    private fun handleLongClick(expandable: Expandable?) {
-        qsTileIntentUserActionHandler.handle(expandable, Intent(Settings.ACTION_WIFI_SETTINGS))
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModel.kt
index e8b9926..eeb8c85 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModel.kt
@@ -39,7 +39,7 @@
     val isAvailable: StateFlow<Boolean>
 
     /** Specifies the [TileDetailsViewModel] for constructing the corresponding details view. */
-    val detailsViewModel: TileDetailsViewModel?
+    val tileDetailsViewModel: TileDetailsViewModel?
         get() = null
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index 30d1f05..527c542 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -157,7 +157,7 @@
     }
 
     override fun getDetailsViewModel(): TileDetailsViewModel? {
-        return qsTileViewModel.detailsViewModel
+        return qsTileViewModel.tileDetailsViewModel
     }
 
     @Deprecated(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
index 10090283..48f0245 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.qs.tiles.NfcTile
 import com.android.systemui.qs.tiles.base.interactor.QSTileAvailabilityInteractor
 import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
+import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
 import com.android.systemui.qs.tiles.impl.airplane.domain.AirplaneModeMapper
 import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileDataInteractor
 import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileUserActionInteractor
@@ -162,13 +163,15 @@
             factory: QSTileViewModelFactory.Static<AirplaneModeTileModel>,
             mapper: AirplaneModeMapper,
             stateInteractor: AirplaneModeTileDataInteractor,
-            userActionInteractor: AirplaneModeTileUserActionInteractor
+            userActionInteractor: AirplaneModeTileUserActionInteractor,
+            internetDetailsViewModelFactory: InternetDetailsViewModel.Factory
         ): QSTileViewModel =
             factory.create(
                 TileSpec.create(AIRPLANE_MODE_TILE_SPEC),
                 userActionInteractor,
                 stateInteractor,
                 mapper,
+                internetDetailsViewModelFactory.create(),
             )
 
         @Provides
@@ -226,13 +229,15 @@
             factory: QSTileViewModelFactory.Static<InternetTileModel>,
             mapper: InternetTileMapper,
             stateInteractor: InternetTileDataInteractor,
-            userActionInteractor: InternetTileUserActionInteractor
+            userActionInteractor: InternetTileUserActionInteractor,
+            internetDetailsViewModelFactory: InternetDetailsViewModel.Factory
         ): QSTileViewModel =
             factory.create(
                 TileSpec.create(INTERNET_TILE_SPEC),
                 userActionInteractor,
                 stateInteractor,
                 mapper,
+                internetDetailsViewModelFactory.create(),
             )
 
         @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index ab382df..e89a76f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static android.app.NotificationChannel.SYSTEM_RESERVED_IDS;
+import static android.app.Flags.notificationsRedesignTemplates;
 import static android.view.HapticFeedbackConstants.CLOCK_TICK;
 
 import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
@@ -706,8 +706,11 @@
     static NotificationMenuItem createInfoItem(Context context) {
         Resources res = context.getResources();
         String infoDescription = res.getString(R.string.notification_menu_gear_description);
+        int layoutId = notificationsRedesignTemplates()
+                ? R.layout.notification_2025_info
+                : R.layout.notification_info;
         NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
-                R.layout.notification_info, null, false);
+                layoutId, null, false);
         return new NotificationMenuItem(context, infoDescription, infoContent,
                 R.drawable.ic_settings);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
index da98858..9bd5a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
@@ -291,7 +291,7 @@
          * currently being swiped. From the center outwards, the multipliers apply to the neighbors
          * of the swiped view.
          */
-        private val MAGNETIC_TRANSLATION_MULTIPLIERS = listOf(0.18f, 0.28f, 0.5f, 0.28f, 0.18f)
+        private val MAGNETIC_TRANSLATION_MULTIPLIERS = listOf(0.04f, 0.12f, 0.5f, 0.12f, 0.04f)
 
         const val MAGNETIC_REDUCTION = 0.65f
 
@@ -299,7 +299,7 @@
         private const val DETACH_STIFFNESS = 800f
         private const val DETACH_DAMPING_RATIO = 0.95f
         private const val SNAP_BACK_STIFFNESS = 550f
-        private const val SNAP_BACK_DAMPING_RATIO = 0.52f
+        private const val SNAP_BACK_DAMPING_RATIO = 0.6f
 
         // Maximum value of corner roundness that gets applied during the pre-detach dragging
         private const val MAX_PRE_DETACH_ROUNDNESS = 0.8f
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
index bc1c60c..c058490 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
@@ -33,7 +33,4 @@
     override suspend fun handleInput(input: QSTileInput<T>) {
         mutex.withLock { mutableInputs.add(input) }
     }
-
-    override var detailsViewModel: TileDetailsViewModel? =
-        FakeTileDetailsViewModel("FakeQSTileUserActionInteractor")
 }
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index bd34f33..c182c26 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -149,7 +149,6 @@
 
     OperationStorage mOperationStorage;
     List<PackageInfo> mPackages;
-    PackageInfo mCurrentPackage;
     boolean mUpdateSchedule;
     CountDownLatch mLatch;
     FullBackupJob mJob;             // if a scheduled job needs to be finished afterwards
@@ -207,10 +206,9 @@
         for (String pkg : whichPackages) {
             try {
                 PackageManager pm = backupManagerService.getPackageManager();
-                PackageInfo info = pm.getPackageInfoAsUser(pkg,
+                PackageInfo packageInfo = pm.getPackageInfoAsUser(pkg,
                         PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
-                mCurrentPackage = info;
-                if (!mBackupEligibilityRules.appIsEligibleForBackup(info.applicationInfo)) {
+                if (!mBackupEligibilityRules.appIsEligibleForBackup(packageInfo.applicationInfo)) {
                     // Cull any packages that have indicated that backups are not permitted,
                     // that run as system-domain uids but do not define their own backup agents,
                     // as well as any explicit mention of the 'special' shared-storage agent
@@ -220,13 +218,13 @@
                     }
                     mBackupManagerMonitorEventSender.monitorEvent(
                             BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE,
-                            mCurrentPackage,
+                            packageInfo,
                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            null);
+                            /* extras= */ null);
                     BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
                             BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                     continue;
-                } else if (!mBackupEligibilityRules.appGetsFullBackup(info)) {
+                } else if (!mBackupEligibilityRules.appGetsFullBackup(packageInfo)) {
                     // Cull any packages that are found in the queue but now aren't supposed
                     // to get full-data backup operations.
                     if (DEBUG) {
@@ -235,13 +233,13 @@
                     }
                     mBackupManagerMonitorEventSender.monitorEvent(
                             BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT,
-                            mCurrentPackage,
+                            packageInfo,
                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            null);
+                            /* extras= */ null);
                     BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
                             BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                     continue;
-                } else if (mBackupEligibilityRules.appIsStopped(info.applicationInfo)) {
+                } else if (mBackupEligibilityRules.appIsStopped(packageInfo.applicationInfo)) {
                     // Cull any packages in the 'stopped' state: they've either just been
                     // installed or have explicitly been force-stopped by the user.  In both
                     // cases we do not want to launch them for backup.
@@ -250,21 +248,21 @@
                     }
                     mBackupManagerMonitorEventSender.monitorEvent(
                             BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED,
-                            mCurrentPackage,
+                            packageInfo,
                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            null);
+                            /* extras= */ null);
                     BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
                             BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                     continue;
                 }
-                mPackages.add(info);
+                mPackages.add(packageInfo);
             } catch (NameNotFoundException e) {
                 Slog.i(TAG, "Requested package " + pkg + " not found; ignoring");
                 mBackupManagerMonitorEventSender.monitorEvent(
                         BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND,
-                        mCurrentPackage,
+                        /* pkg= */ null,
                         BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                        null);
+                        /* extras= */ null);
             }
         }
 
@@ -352,10 +350,11 @@
                 } else {
                     monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
                 }
-                mBackupManagerMonitorEventSender
-                        .monitorEvent(monitoringEvent, null,
-                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                null);
+                mBackupManagerMonitorEventSender.monitorEvent(
+                        monitoringEvent,
+                        /* pkg= */ null,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        /* extras= */ null);
                 mUpdateSchedule = false;
                 backupRunStatus = BackupManager.ERROR_BACKUP_NOT_ALLOWED;
                 return;
@@ -367,8 +366,9 @@
                 backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
                 mBackupManagerMonitorEventSender.monitorEvent(
                         BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT,
-                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
-                        null);
+                        /* pkg= */ null,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+                        /* extras= */ null);
                 return;
             }
 
@@ -461,9 +461,10 @@
                         }
                         mBackupManagerMonitorEventSender.monitorEvent(
                                 BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT,
-                                mCurrentPackage,
+                                currentPackage,
                                 BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                mBackupManagerMonitorEventSender.putMonitoringExtra(null,
+                                BackupManagerMonitorEventSender.putMonitoringExtra(
+                                        /* extras= */ null,
                                         BackupManagerMonitor.EXTRA_LOG_PREFLIGHT_ERROR,
                                         preflightResult));
                         backupPackageStatus = (int) preflightResult;
@@ -496,9 +497,9 @@
                                     + ": " + totalRead + " of " + quota);
                             mBackupManagerMonitorEventSender.monitorEvent(
                                     BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT,
-                                    mCurrentPackage,
+                                    currentPackage,
                                     BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
-                                    null);
+                                    /* extras= */ null);
                             mBackupRunner.sendQuotaExceeded(totalRead, quota);
                         }
                     }
@@ -645,9 +646,9 @@
             Slog.w(TAG, "Exception trying full transport backup", e);
             mBackupManagerMonitorEventSender.monitorEvent(
                     BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP,
-                    mCurrentPackage,
+                    /* pkg= */ null,
                     BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                    mBackupManagerMonitorEventSender.putMonitoringExtra(null,
+                    BackupManagerMonitorEventSender.putMonitoringExtra(/* extras= */ null,
                             BackupManagerMonitor.EXTRA_LOG_EXCEPTION_FULL_BACKUP,
                             Log.getStackTraceString(e)));
 
@@ -966,9 +967,6 @@
             }
         }
 
-
-        // BackupRestoreTask interface: specifically, timeout detection
-
         @Override
         public void execute() { /* intentionally empty */ }
 
@@ -981,7 +979,9 @@
 
             mBackupManagerMonitorEventSender.monitorEvent(
                     BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL,
-                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
+                    mTarget,
+                    BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                    /* extras= */ null);
             mIsCancelled = true;
             // Cancel tasks spun off by this task.
             mUserBackupManagerService.handleCancel(mEphemeralToken, cancelAll);
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorEventSender.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorEventSender.java
index c4519b1..33668a6 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorEventSender.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorEventSender.java
@@ -71,6 +71,7 @@
         mMonitor = monitor;
     }
 
+    @Nullable
     public IBackupManagerMonitor getMonitor() {
         return mMonitor;
     }
@@ -87,9 +88,9 @@
      */
     public void monitorEvent(
             int id,
-            PackageInfo pkg,
+            @Nullable PackageInfo pkg,
             int category,
-            Bundle extras) {
+            @Nullable Bundle extras) {
         try {
             Bundle bundle = new Bundle();
             bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b6fe0ad..e46bbe2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -160,6 +160,7 @@
 import com.android.server.pm.Installer;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.storage.AppFuseBridge;
+import com.android.server.storage.ImmutableVolumeInfo;
 import com.android.server.storage.StorageSessionController;
 import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
 import com.android.server.storage.WatchedVolumeInfo;
@@ -777,7 +778,7 @@
                     break;
                 }
                 case H_VOLUME_UNMOUNT: {
-                    final WatchedVolumeInfo vol = (WatchedVolumeInfo) msg.obj;
+                    final ImmutableVolumeInfo vol = (ImmutableVolumeInfo) msg.obj;
                     unmount(vol);
                     break;
                 }
@@ -898,8 +899,14 @@
                         for (int i = 0; i < size; i++) {
                             final WatchedVolumeInfo vol = mVolumes.valueAt(i);
                             if (vol.getMountUserId() == userId) {
+                                // Capture the volume before we set mount user id to null,
+                                // so that StorageSessionController remove the session from
+                                // the correct user (old mount user id)
+                                final ImmutableVolumeInfo volToUnmount
+                                        = vol.getClonedImmutableVolumeInfo();
                                 vol.setMountUserId(UserHandle.USER_NULL);
-                                mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
+                                mHandler.obtainMessage(H_VOLUME_UNMOUNT, volToUnmount)
+                                        .sendToTarget();
                             }
                         }
                     }
@@ -1295,7 +1302,12 @@
     }
 
     private void maybeRemountVolumes(int userId) {
-        List<WatchedVolumeInfo> volumesToRemount = new ArrayList<>();
+        // We need to keep 2 lists
+        // 1. List of volumes before we set the mount user Id so that
+        // StorageSessionController is able to remove the session from the correct user (old one)
+        // 2. List of volumes to mount which should have the up to date info
+        List<ImmutableVolumeInfo> volumesToUnmount = new ArrayList<>();
+        List<WatchedVolumeInfo> volumesToMount = new ArrayList<>();
         synchronized (mLock) {
             for (int i = 0; i < mVolumes.size(); i++) {
                 final WatchedVolumeInfo vol = mVolumes.valueAt(i);
@@ -1303,16 +1315,19 @@
                         && vol.getMountUserId() != mCurrentUserId) {
                     // If there's a visible secondary volume mounted,
                     // we need to update the currentUserId and remount
+                    // But capture the volume with the old user id first to use it in unmounting
+                    volumesToUnmount.add(vol.getClonedImmutableVolumeInfo());
                     vol.setMountUserId(mCurrentUserId);
-                    volumesToRemount.add(vol);
+                    volumesToMount.add(vol);
                 }
             }
         }
 
-        for (WatchedVolumeInfo vol : volumesToRemount) {
-            Slog.i(TAG, "Remounting volume for user: " + userId + ". Volume: " + vol);
-            mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
-            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
+        for (int i = 0; i < volumesToMount.size(); i++) {
+            Slog.i(TAG, "Remounting volume for user: " + userId + ". Volume: "
+                    + volumesToUnmount.get(i));
+            mHandler.obtainMessage(H_VOLUME_UNMOUNT, volumesToUnmount.get(i)).sendToTarget();
+            mHandler.obtainMessage(H_VOLUME_MOUNT, volumesToMount.get(i)).sendToTarget();
         }
     }
 
@@ -2430,10 +2445,10 @@
         super.unmount_enforcePermission();
 
         final WatchedVolumeInfo vol = findVolumeByIdOrThrow(volId);
-        unmount(vol);
+        unmount(vol.getClonedImmutableVolumeInfo());
     }
 
-    private void unmount(WatchedVolumeInfo vol) {
+    private void unmount(ImmutableVolumeInfo vol) {
         try {
             try {
                 if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
@@ -2444,7 +2459,7 @@
             }
             extendWatchdogTimeout("#unmount might be slow");
             mVold.unmount(vol.getId());
-            mStorageSessionController.onVolumeUnmount(vol.getImmutableVolumeInfo());
+            mStorageSessionController.onVolumeUnmount(vol);
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
index 7a96195..9937049 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabaseCorruptException;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Environment;
@@ -204,6 +205,11 @@
             return false;
         }
         final String clause = WhiteListReportContract.TIMESTAMP + "< " + untilTimestamp;
-        return db.delete(WhiteListReportContract.TABLE, clause, null) != 0;
+        try {
+            return db.delete(WhiteListReportContract.TABLE, clause, null) != 0;
+        } catch (SQLiteDatabaseCorruptException e) {
+            Slog.e(TAG, "Error deleting records", e);
+            return false;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/storage/WatchedVolumeInfo.java b/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
index 94e52cd..d4b20fb 100644
--- a/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
+++ b/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
@@ -68,6 +68,10 @@
         return ImmutableVolumeInfo.fromVolumeInfo(mVolumeInfo);
     }
 
+    public ImmutableVolumeInfo getClonedImmutableVolumeInfo() {
+        return ImmutableVolumeInfo.fromVolumeInfo(mVolumeInfo.clone());
+    }
+
     public StorageVolume buildStorageVolume(Context context, int userId, boolean reportUnmounted) {
         return mVolumeInfo.buildStorageVolume(context, userId, reportUnmounted);
     }
diff --git a/services/core/java/com/android/server/wm/DesktopModeHelper.java b/services/core/java/com/android/server/wm/DesktopModeHelper.java
index c2255d8..dc42b32 100644
--- a/services/core/java/com/android/server/wm/DesktopModeHelper.java
+++ b/services/core/java/com/android/server/wm/DesktopModeHelper.java
@@ -79,7 +79,7 @@
     }
 
     @VisibleForTesting
-    static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
+    public static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
         if (!shouldEnforceDeviceRestrictions()) {
             return true;
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e190a04..50f12c3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6938,6 +6938,8 @@
         /** The actual requested visible inset types for this display */
         private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
 
+        private @InsetsType int mAnimatingTypes = 0;
+
         /** The component name of the top focused window on this display */
         private ComponentName mTopFocusedComponentName = null;
 
@@ -7075,6 +7077,18 @@
             }
             return 0;
         }
+
+        @Override
+        public @InsetsType int getAnimatingTypes() {
+            return mAnimatingTypes;
+        }
+
+        @Override
+        public void setAnimatingTypes(@InsetsType int animatingTypes) {
+            if (mAnimatingTypes != animatingTypes) {
+                mAnimatingTypes = animatingTypes;
+            }
+        }
     }
 
     MagnificationSpec getMagnificationSpec() {
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index cee4967..6462a37 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -97,6 +97,20 @@
             @NonNull ImeTracker.Token statsToken) {
     }
 
+    /**
+     * @return {@link WindowInsets.Type.InsetsType}s which are currently animating (showing or
+     * hiding).
+     */
+    default @InsetsType int getAnimatingTypes() {
+        return 0;
+    }
+
+    /**
+     * @param animatingTypes the {@link InsetsType}s, that are currently animating
+     */
+    default void setAnimatingTypes(@InsetsType int animatingTypes) {
+    }
+
     /** Returns {@code target.getWindow()}, or null if {@code target} is {@code null}. */
     static WindowState asWindowOrNull(InsetsControlTarget target) {
         return target != null ? target.getWindow() : null;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 009d482..2872214 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -790,8 +790,6 @@
         private final Handler mHandler;
         private final String mName;
 
-        private boolean mInsetsAnimationRunning;
-
         Host(Handler handler, String name) {
             mHandler = handler;
             mName = name;
@@ -901,10 +899,5 @@
         public IBinder getWindowToken() {
             return null;
         }
-
-        @Override
-        public void notifyAnimationRunningStateChanged(boolean running) {
-            mInsetsAnimationRunning = running;
-        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 8d198b2..3ed16db 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -737,6 +737,17 @@
         }
     }
 
+    @Override
+    public void updateAnimatingTypes(IWindow window, @InsetsType int animatingTypes) {
+        synchronized (mService.mGlobalLock) {
+            final WindowState win = mService.windowForClientLocked(this, window,
+                    false /* throwOnError */);
+            if (win != null) {
+                win.setAnimatingTypes(animatingTypes);
+            }
+        }
+    }
+
     void onWindowAdded(WindowState w) {
         if (mPackageName == null) {
             mPackageName = mProcess.mInfo.packageName;
@@ -1015,15 +1026,4 @@
             }
         }
     }
-
-    @Override
-    public void notifyInsetsAnimationRunningStateChanged(IWindow window, boolean running) {
-        synchronized (mService.mGlobalLock) {
-            final WindowState win = mService.windowForClientLocked(this, window,
-                    false /* throwOnError */);
-            if (win != null) {
-                win.notifyInsetsAnimationRunningStateChanged(running);
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2e699ca..28f2825 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4773,6 +4773,26 @@
         }
     }
 
+    @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
+    @Override
+    public void updateDisplayWindowAnimatingTypes(int displayId, @InsetsType int animatingTypes) {
+        updateDisplayWindowAnimatingTypes_enforcePermission();
+        if (android.view.inputmethod.Flags.reportAnimatingInsetsTypes()) {
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                synchronized (mGlobalLock) {
+                    final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                    if (dc == null || dc.mRemoteInsetsControlTarget == null) {
+                        return;
+                    }
+                    dc.mRemoteInsetsControlTarget.setAnimatingTypes(animatingTypes);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
     @Override
     public int watchRotation(IRotationWatcher watcher, int displayId) {
         final DisplayContent displayContent;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ce87ca5..3b7d312 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -736,6 +736,8 @@
 
     private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
 
+    private @InsetsType int mAnimatingTypes = 0;
+
     /**
      * Freeze the insets state in some cases that not necessarily keeps up-to-date to the client.
      * (e.g app exiting transition)
@@ -842,6 +844,27 @@
                 mRequestedVisibleTypes & ~mask | requestedVisibleTypes & mask);
     }
 
+    @Override
+    public @InsetsType int getAnimatingTypes() {
+        return mAnimatingTypes;
+    }
+
+    @Override
+    public void setAnimatingTypes(@InsetsType int animatingTypes) {
+        if (mAnimatingTypes != animatingTypes) {
+            if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                Trace.instant(TRACE_TAG_WINDOW_MANAGER,
+                        TextUtils.formatSimple("%s: setAnimatingTypes(%s)",
+                                getName(),
+                                animatingTypes));
+            }
+            mInsetsAnimationRunning = animatingTypes != 0;
+            mWmService.scheduleAnimationLocked();
+
+            mAnimatingTypes = animatingTypes;
+        }
+    }
+
     /**
      * Set a freeze state for the window to ignore dispatching its insets state to the client.
      *
@@ -6078,17 +6101,6 @@
         mWmService.scheduleAnimationLocked();
     }
 
-    void notifyInsetsAnimationRunningStateChanged(boolean running) {
-        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
-            Trace.instant(TRACE_TAG_WINDOW_MANAGER,
-                    TextUtils.formatSimple("%s: notifyInsetsAnimationRunningStateChanged(%s)",
-                    getName(),
-                    Boolean.toString(running)));
-        }
-        mInsetsAnimationRunning = running;
-        mWmService.scheduleAnimationLocked();
-    }
-
     boolean isInsetsAnimationRunning() {
         return mInsetsAnimationRunning;
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index bada337..6b8ef88 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -64,7 +64,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
 import android.graphics.Color;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
@@ -95,6 +94,7 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.LocalServices;
+import com.android.server.wm.DesktopModeHelper;
 import com.android.server.wm.WindowManagerInternal;
 
 import org.hamcrest.CoreMatchers;
@@ -155,8 +155,6 @@
 
     private IPackageManager mIpm = AppGlobals.getPackageManager();
 
-    private Resources mResources = sContext.getResources();
-
     @Mock
     private DisplayManager mDisplayManager;
 
@@ -178,6 +176,7 @@
                 .spyStatic(WallpaperUtils.class)
                 .spyStatic(LocalServices.class)
                 .spyStatic(WallpaperManager.class)
+                .spyStatic(DesktopModeHelper.class)
                 .startMocking();
 
         sWindowManagerInternal = mock(WindowManagerInternal.class);
@@ -246,6 +245,8 @@
             int userId = (invocation.getArgument(0));
             return getWallpaperTestDir(userId);
         }).when(() -> WallpaperUtils.getWallpaperDir(anyInt()));
+        ExtendedMockito.doAnswer(invocation -> true).when(
+                () -> DesktopModeHelper.isDeviceEligibleForDesktopMode(any()));
 
         sContext.addMockSystemService(DisplayManager.class, mDisplayManager);
 
@@ -257,10 +258,6 @@
         doReturn(displays).when(mDisplayManager).getDisplays();
 
         spyOn(mIpm);
-        spyOn(mResources);
-        doReturn(true).when(mResources).getBoolean(eq(R.bool.config_isDesktopModeSupported));
-        doReturn(true).when(mResources).getBoolean(
-                eq(R.bool.config_canInternalDisplayHostDesktops));
         mService = new TestWallpaperManagerService(sContext);
         spyOn(mService);
         mService.systemReady();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index 45436e4..d3f3269 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -33,6 +33,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.Display.Mode;
 import android.view.Surface;
+import android.view.WindowInsets;
 import android.view.WindowManager.LayoutParams;
 
 import androidx.test.filters.SmallTest;
@@ -283,7 +284,7 @@
         assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE);
         assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE);
 
-        overrideWindow.notifyInsetsAnimationRunningStateChanged(true);
+        overrideWindow.setAnimatingTypes(WindowInsets.Type.statusBars());
         assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
         assertTrue(mPolicy.updateFrameRateVote(overrideWindow));
         assertEquals(FRAME_RATE_VOTE_NONE, overrideWindow.mFrameRateVote);
@@ -303,7 +304,7 @@
         assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE);
         assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE);
 
-        overrideWindow.notifyInsetsAnimationRunningStateChanged(true);
+        overrideWindow.setAnimatingTypes(WindowInsets.Type.statusBars());
         assertEquals(0, mPolicy.getPreferredModeId(overrideWindow));
         assertTrue(mPolicy.updateFrameRateVote(overrideWindow));
         assertEquals(FRAME_RATE_VOTE_NONE, overrideWindow.mFrameRateVote);