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);