summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/AutomaticZenRule.java2
-rw-r--r--libs/WindowManager/Shell/res/values/ids.xml1
-rw-r--r--libs/WindowManager/Shell/res/values/strings.xml2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java13
-rw-r--r--media/java/android/media/RoutingSessionInfo.java12
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig7
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/ContentDescription.kt2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/Icon.kt5
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt2
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt189
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt38
-rw-r--r--packages/SystemUI/res/values-xlarge-land/config.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodPromotedNotificationSection.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt21
-rw-r--r--packages/SystemUI/tests/utils/src/android/view/WindowManagerKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarOrchestratorKosmos.kt2
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java4
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java91
-rw-r--r--services/supervision/java/com/android/server/supervision/SupervisionService.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt10
30 files changed, 336 insertions, 160 deletions
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index e0a937156906..9d1d9c7b69de 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -162,7 +162,7 @@ public final class AutomaticZenRule implements Parcelable {
* both to fields in the rule itself (such as its name) and items with sub-fields.
* @hide
*/
- public static final int MAX_STRING_LENGTH = 1000;
+ public static final int MAX_STRING_LENGTH = 500;
/**
* The maximum string length for the trigger description rule, given UI constraints.
diff --git a/libs/WindowManager/Shell/res/values/ids.xml b/libs/WindowManager/Shell/res/values/ids.xml
index 122cde04f8e4..c6082b3bd60f 100644
--- a/libs/WindowManager/Shell/res/values/ids.xml
+++ b/libs/WindowManager/Shell/res/values/ids.xml
@@ -25,6 +25,7 @@
<item type="id" name="action_move_tl_50" />
<item type="id" name="action_move_tl_30" />
<item type="id" name="action_move_rb_full" />
+ <item type="id" name="action_swap_apps" />
<!-- For saving PhysicsAnimationLayout animations/animators as view tags. -->
<item type="id" name="translation_x_dynamicanimation_tag"/>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index c29b927f61c2..a2231dd64112 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -90,6 +90,8 @@
<string name="accessibility_action_divider_left_30">Left 30%</string>
<!-- Accessibility action for moving docked stack divider to make the right screen full screen [CHAR LIMIT=NONE] -->
<string name="accessibility_action_divider_right_full">Right full screen</string>
+ <!-- Accessibility action for swapping the apps around the divider (double tap action) [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_swap">Swap Apps</string>
<!-- Accessibility action for moving docked stack divider to make the top screen full screen [CHAR LIMIT=NONE] -->
<string name="accessibility_action_divider_top_full">Top full screen</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 2c418d34f09a..06044ccc1c61 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -125,11 +125,13 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
}
};
- private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
+ final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
final DividerSnapAlgorithm snapAlgorithm = mSplitLayout.mDividerSnapAlgorithm;
+ info.addAction(new AccessibilityAction(R.id.action_swap_apps,
+ mContext.getString(R.string.accessibility_action_divider_swap)));
if (mSplitLayout.isLeftRightSplit()) {
info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
mContext.getString(R.string.accessibility_action_divider_left_full)));
@@ -172,6 +174,11 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
@Override
public boolean performAccessibilityAction(@NonNull View host, int action,
@Nullable Bundle args) {
+ if (action == R.id.action_swap_apps) {
+ mSplitLayout.onDoubleTappedDivider();
+ return true;
+ }
+
DividerSnapAlgorithm.SnapTarget nextTarget = null;
DividerSnapAlgorithm snapAlgorithm = mSplitLayout.mDividerSnapAlgorithm;
if (action == R.id.action_move_tl_full) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
index fd3d3b5b6e2f..8c34c1946702 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
@@ -36,6 +36,7 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
@@ -66,9 +67,9 @@ public class DividerViewTest extends ShellTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
Configuration configuration = getConfiguration();
- mSplitLayout = new SplitLayout("TestSplitLayout", mContext, configuration,
+ mSplitLayout = spy(new SplitLayout("TestSplitLayout", mContext, configuration,
mSplitLayoutHandler, mCallbacks, mDisplayController, mDisplayImeController,
- mTaskOrganizer, SplitLayout.PARALLAX_NONE, mSplitState, mHandler);
+ mTaskOrganizer, SplitLayout.PARALLAX_NONE, mSplitState, mHandler));
SplitWindowManager splitWindowManager = new SplitWindowManager("TestSplitWindowManager",
mContext,
configuration, mCallbacks);
@@ -98,6 +99,14 @@ public class DividerViewTest extends ShellTestCase {
"false", false);
}
+ @Test
+ public void swapDividerActionForA11y() {
+ mDividerView.setAccessibilityDelegate(mDividerView.mHandleDelegate);
+ mDividerView.getAccessibilityDelegate().performAccessibilityAction(mDividerView,
+ R.id.action_swap_apps, null);
+ verify(mSplitLayout, times(1)).onDoubleTappedDivider();
+ }
+
private static MotionEvent getMotionEvent(long eventTime, int action, float x, float y) {
MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
properties.id = 0;
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index 87bb6eab6c4d..d27d7fc72a38 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -649,9 +649,19 @@ public final class RoutingSessionInfo implements Parcelable {
* @param sessionInfo the existing instance to copy data from.
*/
public Builder(@NonNull RoutingSessionInfo sessionInfo) {
+ this(sessionInfo, sessionInfo.getOriginalId());
+ }
+
+ /**
+ * Builds upon the given {@code sessionInfo}, using the given {@link #getOriginalId()} for
+ * the id.
+ *
+ * @hide
+ */
+ public Builder(@NonNull RoutingSessionInfo sessionInfo, String originalId) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
- mOriginalId = sessionInfo.mOriginalId;
+ mOriginalId = originalId;
mName = sessionInfo.mName;
mClientPackageName = sessionInfo.mClientPackageName;
mProviderId = sessionInfo.mProviderId;
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index bb0d5d7755cf..6c96279711d0 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1697,13 +1697,6 @@ flag {
}
flag {
- name: "magic_portrait_wallpapers"
- namespace: "systemui"
- description: "Magic Portrait related changes in systemui"
- bug: "370863642"
-}
-
-flag {
name: "notes_role_qs_tile"
namespace: "systemui"
description: "Enables notes role qs tile which opens default notes role app in app bubbles"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/ContentDescription.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/ContentDescription.kt
index 4a5ad6554dc6..b254963cc5e9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/ContentDescription.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/ContentDescription.kt
@@ -17,11 +17,13 @@
package com.android.systemui.common.ui.compose
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.res.stringResource
import com.android.systemui.common.shared.model.ContentDescription
/** Returns the loaded [String] or `null` if there isn't one. */
@Composable
+@ReadOnlyComposable
fun ContentDescription.load(): String? {
return when (this) {
is ContentDescription.Loaded -> description
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/Icon.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/Icon.kt
index 82d14369f239..8b0c00535262 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/Icon.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/Icon.kt
@@ -21,9 +21,8 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
-import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.systemui.common.shared.model.Icon
/**
@@ -36,7 +35,7 @@ fun Icon(icon: Icon, modifier: Modifier = Modifier, tint: Color = LocalContentCo
val contentDescription = icon.contentDescription?.load()
when (icon) {
is Icon.Loaded -> {
- Icon(icon.drawable.toBitmap().asImageBitmap(), contentDescription, modifier, tint)
+ Icon(rememberDrawablePainter(icon.drawable), contentDescription, modifier, tint)
}
is Icon.Resource -> Icon(painterResource(icon.res), contentDescription, modifier, tint)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt
index 4e8121f14e4b..19adba0f39de 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt
@@ -19,6 +19,7 @@ package com.android.systemui.common.ui.compose
import android.content.Context
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import com.android.systemui.common.shared.model.Text
@@ -26,6 +27,7 @@ import com.android.systemui.common.shared.model.Text.Companion.loadText
/** Returns the loaded [String] or `null` if there isn't one. */
@Composable
+@ReadOnlyComposable
fun Text.load(): String? {
return when (this) {
is Text.Loaded -> text
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 12b20a53df81..ab31286b78b4 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -299,8 +299,7 @@ open class ClockRegistry(
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
)
}
-
- ClockSettings.fromJson(JSONObject(json))
+ json?.let { ClockSettings.fromJson(JSONObject(it)) }
} catch (ex: Exception) {
logger.e("Failed to parse clock settings", ex)
null
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt
index c06da4bc5080..dc65a9e24407 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.core
import android.platform.test.annotations.EnableFlags
import android.view.Display
+import android.view.mockIWindowManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -31,11 +32,13 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -51,75 +54,110 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() {
private val fakeInitializerStore = kosmos.fakeStatusBarInitializerStore
private val fakePrivacyDotStore = kosmos.fakePrivacyDotWindowControllerStore
private val fakeLightBarStore = kosmos.fakeLightBarControllerStore
+ private val windowManager = kosmos.mockIWindowManager
+
// Lazy, so that @EnableFlags is set before initializer is instantiated.
private val underTest by lazy { kosmos.multiDisplayStatusBarStarter }
+ @Before
+ fun setup() {
+ whenever(windowManager.shouldShowSystemDecors(Display.DEFAULT_DISPLAY)).thenReturn(true)
+ whenever(windowManager.shouldShowSystemDecors(DISPLAY_1)).thenReturn(true)
+ whenever(windowManager.shouldShowSystemDecors(DISPLAY_2)).thenReturn(true)
+ whenever(windowManager.shouldShowSystemDecors(DISPLAY_3)).thenReturn(true)
+ whenever(windowManager.shouldShowSystemDecors(DISPLAY_4_NO_SYSTEM_DECOR)).thenReturn(false)
+ }
+
@Test
fun start_startsInitializersForCurrentDisplays() =
testScope.runTest {
- fakeDisplayRepository.addDisplay(displayId = 1)
- fakeDisplayRepository.addDisplay(displayId = 2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_1)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
underTest.start()
runCurrent()
expect
- .that(fakeInitializerStore.forDisplay(displayId = 1).startedByCoreStartable)
+ .that(fakeInitializerStore.forDisplay(displayId = DISPLAY_1).startedByCoreStartable)
.isTrue()
expect
- .that(fakeInitializerStore.forDisplay(displayId = 2).startedByCoreStartable)
+ .that(fakeInitializerStore.forDisplay(displayId = DISPLAY_2).startedByCoreStartable)
.isTrue()
+ expect
+ .that(
+ fakeInitializerStore
+ .forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
+ .startedByCoreStartable
+ )
+ .isFalse()
}
@Test
fun start_startsOrchestratorForCurrentDisplays() =
testScope.runTest {
- fakeDisplayRepository.addDisplay(displayId = 1)
- fakeDisplayRepository.addDisplay(displayId = 2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_1)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
underTest.start()
runCurrent()
- verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 1)!!).start()
- verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 2)!!).start()
+ verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = DISPLAY_1)!!)
+ .start()
+ verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = DISPLAY_2)!!)
+ .start()
+ assertThat(
+ fakeOrchestratorFactory.createdOrchestratorForDisplay(
+ displayId = DISPLAY_4_NO_SYSTEM_DECOR
+ )
+ )
+ .isNull()
}
@Test
fun start_startsPrivacyDotForCurrentDisplays() =
testScope.runTest {
- fakeDisplayRepository.addDisplay(displayId = 1)
- fakeDisplayRepository.addDisplay(displayId = 2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_1)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
underTest.start()
runCurrent()
- verify(fakePrivacyDotStore.forDisplay(displayId = 1)).start()
- verify(fakePrivacyDotStore.forDisplay(displayId = 2)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_1)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_2)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
@Test
fun start_doesNotStartLightBarControllerForCurrentDisplays() =
testScope.runTest {
- fakeDisplayRepository.addDisplay(displayId = 1)
- fakeDisplayRepository.addDisplay(displayId = 2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_1)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
underTest.start()
runCurrent()
- verify(fakeLightBarStore.forDisplay(displayId = 1), never()).start()
- verify(fakeLightBarStore.forDisplay(displayId = 2), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_1), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_2), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
@Test
fun start_createsLightBarControllerForCurrentDisplays() =
testScope.runTest {
- fakeDisplayRepository.addDisplay(displayId = 1)
- fakeDisplayRepository.addDisplay(displayId = 2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_1)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_2)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
underTest.start()
runCurrent()
- assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(1, 2)
+ assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(1, DISPLAY_2)
}
@Test
@@ -135,121 +173,174 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() {
}
@Test
- fun displayAdded_orchestratorForNewDisplayIsStarted() =
+ fun displayAdded_orchestratorForNewDisplay() =
testScope.runTest {
underTest.start()
runCurrent()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 3)!!).start()
+ verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = DISPLAY_3)!!)
+ .start()
+ assertThat(
+ fakeOrchestratorFactory.createdOrchestratorForDisplay(
+ displayId = DISPLAY_4_NO_SYSTEM_DECOR
+ )
+ )
+ .isNull()
}
@Test
- fun displayAdded_initializerForNewDisplayIsStarted() =
+ fun displayAdded_initializerForNewDisplay() =
testScope.runTest {
underTest.start()
runCurrent()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
expect
- .that(fakeInitializerStore.forDisplay(displayId = 3).startedByCoreStartable)
+ .that(fakeInitializerStore.forDisplay(displayId = DISPLAY_3).startedByCoreStartable)
.isTrue()
+ expect
+ .that(
+ fakeInitializerStore
+ .forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
+ .startedByCoreStartable
+ )
+ .isFalse()
}
@Test
- fun displayAdded_privacyDotForNewDisplayIsStarted() =
+ fun displayAdded_privacyDotForNewDisplay() =
testScope.runTest {
underTest.start()
runCurrent()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_3)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
@Test
- fun displayAdded_lightBarForNewDisplayIsCreated() =
+ fun displayAdded_lightBarForNewDisplayCreate() =
testScope.runTest {
underTest.start()
runCurrent()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(3)
+ assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(DISPLAY_3)
}
@Test
- fun displayAdded_lightBarForNewDisplayIsNotStarted() =
+ fun displayAdded_lightBarForNewDisplayStart() =
testScope.runTest {
underTest.start()
runCurrent()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakeLightBarStore.forDisplay(displayId = 3), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_3), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
@Test
- fun displayAddedDuringStart_initializerForNewDisplayIsStarted() =
+ fun displayAddedDuringStart_initializerForNewDisplay() =
testScope.runTest {
underTest.start()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
expect
- .that(fakeInitializerStore.forDisplay(displayId = 3).startedByCoreStartable)
+ .that(fakeInitializerStore.forDisplay(displayId = DISPLAY_3).startedByCoreStartable)
.isTrue()
+ expect
+ .that(
+ fakeInitializerStore
+ .forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
+ .startedByCoreStartable
+ )
+ .isFalse()
}
@Test
- fun displayAddedDuringStart_orchestratorForNewDisplayIsStarted() =
+ fun displayAddedDuringStart_orchestratorForNewDisplay() =
testScope.runTest {
underTest.start()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 3)!!).start()
+ verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = DISPLAY_3)!!)
+ .start()
+ assertThat(
+ fakeOrchestratorFactory.createdOrchestratorForDisplay(
+ displayId = DISPLAY_4_NO_SYSTEM_DECOR
+ )
+ )
+ .isNull()
}
@Test
- fun displayAddedDuringStart_privacyDotForNewDisplayIsStarted() =
+ fun displayAddedDuringStart_privacyDotForNewDisplay() =
testScope.runTest {
underTest.start()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_3)).start()
+ verify(fakePrivacyDotStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
@Test
- fun displayAddedDuringStart_lightBarForNewDisplayIsCreated() =
+ fun displayAddedDuringStart_lightBarForNewDisplayCreate() =
testScope.runTest {
underTest.start()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(3)
+ assertThat(fakeLightBarStore.perDisplayMocks.keys).containsExactly(DISPLAY_3)
}
@Test
- fun displayAddedDuringStart_lightBarForNewDisplayIsNotStarted() =
+ fun displayAddedDuringStart_lightBarForNewDisplayStart() =
testScope.runTest {
underTest.start()
- fakeDisplayRepository.addDisplay(displayId = 3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_3)
+ fakeDisplayRepository.addDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR)
runCurrent()
- verify(fakeLightBarStore.forDisplay(displayId = 3), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_3), never()).start()
+ verify(fakeLightBarStore.forDisplay(displayId = DISPLAY_4_NO_SYSTEM_DECOR), never())
+ .start()
}
+
+ companion object {
+ const val DISPLAY_1 = 1
+ const val DISPLAY_2 = 2
+ const val DISPLAY_3 = 3
+ const val DISPLAY_4_NO_SYSTEM_DECOR = 4
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
index 115edd0d3bb0..2b16c00107c3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
@@ -25,16 +25,15 @@ import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
-import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardClockRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.res.R as SysUIR
import com.android.systemui.shared.Flags as SharedFlags
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.wallpapers.data.repository.WallpaperRepositoryImpl.Companion.MAGIC_PORTRAIT_CLASSNAME
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -72,9 +71,12 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
)
}
+ lateinit var focalAreaTarget: String
+
@Before
fun setUp() {
whenever(wallpaperManager.isWallpaperSupported).thenReturn(true)
+ focalAreaTarget = context.resources.getString(SysUIR.string.focal_area_target)
}
@Test
@@ -248,17 +250,17 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
- fun shouldSendNotificationLayout_setMagicPortraitWallpaper_launchSendLayoutJob() =
+ @EnableFlags(SharedFlags.FLAG_EXTENDED_WALLPAPER_EFFECTS)
+ fun shouldSendNotificationLayout_setExtendedEffectsWallpaper_launchSendLayoutJob() =
testScope.runTest {
val latest by collectLastValue(underTest.shouldSendFocalArea)
- val magicPortraitWallpaper =
+ val extedendEffectsWallpaper =
mock<WallpaperInfo>().apply {
- whenever(this.component)
- .thenReturn(ComponentName(context, MAGIC_PORTRAIT_CLASSNAME))
+ whenever(this.component).thenReturn(ComponentName(context, focalAreaTarget))
}
+
whenever(wallpaperManager.getWallpaperInfoForUser(any()))
- .thenReturn(magicPortraitWallpaper)
+ .thenReturn(extedendEffectsWallpaper)
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context,
Intent(Intent.ACTION_WALLPAPER_CHANGED),
@@ -269,13 +271,16 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
- fun shouldSendNotificationLayout_setNotMagicPortraitWallpaper_cancelSendLayoutJob() =
+ @EnableFlags(SharedFlags.FLAG_EXTENDED_WALLPAPER_EFFECTS)
+ fun shouldSendNotificationLayout_setNotExtendedEffectsWallpaper_cancelSendLayoutJob() =
testScope.runTest {
val latest by collectLastValue(underTest.shouldSendFocalArea)
- val magicPortraitWallpaper = MAGIC_PORTRAIT_WP
+ val extendedEffectsWallpaper =
+ mock<WallpaperInfo>().apply {
+ whenever(this.component).thenReturn(ComponentName("", focalAreaTarget))
+ }
whenever(wallpaperManager.getWallpaperInfoForUser(any()))
- .thenReturn(magicPortraitWallpaper)
+ .thenReturn(extendedEffectsWallpaper)
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context,
Intent(Intent.ACTION_WALLPAPER_CHANGED),
@@ -284,9 +289,7 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
- val nonMagicPortraitWallpaper = UNSUPPORTED_WP
- whenever(wallpaperManager.getWallpaperInfoForUser(any()))
- .thenReturn(nonMagicPortraitWallpaper)
+ whenever(wallpaperManager.getWallpaperInfoForUser(any())).thenReturn(UNSUPPORTED_WP)
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context,
Intent(Intent.ACTION_WALLPAPER_CHANGED),
@@ -303,10 +306,5 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
val USER_WITH_SUPPORTED_WP = UserInfo(/* id= */ 4, /* name= */ "user4", /* flags= */ 0)
val SUPPORTED_WP =
mock<WallpaperInfo>().apply { whenever(this.supportsAmbientMode()).thenReturn(true) }
-
- val MAGIC_PORTRAIT_WP =
- mock<WallpaperInfo>().apply {
- whenever(this.component).thenReturn(ComponentName("", MAGIC_PORTRAIT_CLASSNAME))
- }
}
}
diff --git a/packages/SystemUI/res/values-xlarge-land/config.xml b/packages/SystemUI/res/values-xlarge-land/config.xml
index 6d8b64ade259..4c77f30f2e69 100644
--- a/packages/SystemUI/res/values-xlarge-land/config.xml
+++ b/packages/SystemUI/res/values-xlarge-land/config.xml
@@ -16,5 +16,5 @@
<resources>
<item name="shortcut_helper_screen_width_fraction" format="float" type="dimen">0.8</item>
- <bool name="center_align_magic_portrait_shape">true</bool>
+ <bool name="center_align_focal_area_shape">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 68e33f27aefa..9b8926e921c9 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -1107,7 +1107,7 @@
<!-- The dream component used when the device is low light environment. -->
<string translatable="false" name="config_lowLightDreamComponent"/>
- <!--Whether we should position magic portrait shape effects in the center of lockscreen
- it's false by default, and only be true in tablet landscape -->
- <bool name="center_align_magic_portrait_shape">false</bool>
+ <!-- Configuration for wallpaper focal area -->
+ <bool name="center_align_focal_area_shape">false</bool>
+ <string name="focal_area_target" translatable="false" />
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 621cc4666d31..aaad10140a92 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -326,10 +326,7 @@ interface KeyguardRepository {
fun setShortcutAbsoluteTop(top: Float)
- /**
- * Set bottom of notifications from notification stack, and Magic Portrait will layout base on
- * this value
- */
+ /** Set bottom of notifications from notification stack */
fun setNotificationStackAbsoluteBottom(bottom: Float)
fun setWallpaperFocalAreaBounds(bounds: RectF)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt
index 934afe248a36..9c744d63a093 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt
@@ -50,8 +50,7 @@ constructor(
keyguardClockRepository: KeyguardClockRepository,
wallpaperRepository: WallpaperRepository,
) {
- // When there's notifications in splitshade, magic portrait shape effects should be left
- // aligned in foldable
+ // When there's notifications in splitshade, the focal area shape effect should be left aligned
private val notificationInShadeWideLayout: Flow<Boolean> =
combine(
shadeRepository.isShadeLayoutWide,
@@ -104,7 +103,7 @@ constructor(
)
val (left, right) =
// tablet landscape
- if (context.resources.getBoolean(R.bool.center_align_magic_portrait_shape)) {
+ if (context.resources.getBoolean(R.bool.center_align_focal_area_shape)) {
Pair(
scaledBounds.centerX() - maxFocalAreaWidth / 2F,
scaledBounds.centerX() + maxFocalAreaWidth / 2F,
@@ -129,7 +128,7 @@ constructor(
wallpaperZoomedInScale
val top =
// tablet landscape
- if (context.resources.getBoolean(R.bool.center_align_magic_portrait_shape)) {
+ if (context.resources.getBoolean(R.bool.center_align_focal_area_shape)) {
// no strict constraints for top, use bottom margin to make it symmetric
// vertically
scaledBounds.top + scaledBottomMargin
@@ -169,8 +168,8 @@ constructor(
)
}
- // A max width for magic portrait shape effects bounds, to avoid it going too large
- // in large screen portrait mode
+ // A max width for focal area shape effects bounds, to avoid
+ // it becoming too large in large screen portrait mode
const val FOCAL_AREA_MAX_WIDTH_DP = 500
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
index 856e1d6ffdb7..8b213be02969 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
@@ -23,6 +23,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
+import com.android.systemui.keyguard.ui.view.layout.sections.AodPromotedNotificationSection
import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntrySection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
@@ -58,6 +59,7 @@ constructor(
defaultStatusBarSection: DefaultStatusBarSection,
splitShadeNotificationStackScrollLayoutSection: SplitShadeNotificationStackScrollLayoutSection,
splitShadeGuidelines: SplitShadeGuidelines,
+ aodPromotedNotificationSection: AodPromotedNotificationSection,
aodNotificationIconsSection: AodNotificationIconsSection,
aodBurnInSection: AodBurnInSection,
clockSection: ClockSection,
@@ -76,6 +78,7 @@ constructor(
defaultStatusBarSection,
splitShadeNotificationStackScrollLayoutSection,
splitShadeGuidelines,
+ aodPromotedNotificationSection,
aodNotificationIconsSection,
smartspaceSection,
aodBurnInSection,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodPromotedNotificationSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodPromotedNotificationSection.kt
index ed1bdb0e2922..ea4acce037b8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodPromotedNotificationSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodPromotedNotificationSection.kt
@@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.promoted.AODPromotedNotification
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationLogger
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
@@ -36,6 +37,7 @@ class AodPromotedNotificationSection
@Inject
constructor(
private val viewModelFactory: AODPromotedNotificationViewModel.Factory,
+ private val shadeInteractor: ShadeInteractor,
private val logger: PromotedNotificationLogger,
) : KeyguardSection() {
var view: ComposeView? = null
@@ -77,9 +79,12 @@ constructor(
checkNotNull(view)
constraintSet.apply {
+ val isShadeLayoutWide = shadeInteractor.isShadeLayoutWide.value
+ val endGuidelineId = if (isShadeLayoutWide) R.id.split_shade_guideline else PARENT_ID
+
connect(viewId, TOP, R.id.smart_space_barrier_bottom, BOTTOM, 0)
connect(viewId, START, PARENT_ID, START, 0)
- connect(viewId, END, PARENT_ID, END, 0)
+ connect(viewId, END, endGuidelineId, END, 0)
constrainWidth(viewId, ConstraintSet.MATCH_CONSTRAINT)
constrainHeight(viewId, ConstraintSet.WRAP_CONTENT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt
index b057fb0433fe..eeb7a4066eca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.core
import android.view.Display
+import android.view.IWindowManager
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
@@ -54,6 +55,7 @@ constructor(
private val autoHideControllerStore: AutoHideControllerStore,
private val privacyDotWindowControllerStore: PrivacyDotWindowControllerStore,
private val lightBarControllerStore: LightBarControllerStore,
+ private val windowManager: IWindowManager,
) : CoreStartable {
init {
@@ -68,7 +70,13 @@ constructor(
}
.onStart { emit(displayRepository.displays.value) }
.collect { newDisplays ->
- newDisplays.forEach { createAndStartComponentsForDisplay(it) }
+ newDisplays.forEach {
+ // TODO(b/393191204): Split navbar, status bar, etc. functionality
+ // from WindowManager#shouldShowSystemDecors.
+ if (windowManager.shouldShowSystemDecors(it.displayId)) {
+ createAndStartComponentsForDisplay(it)
+ }
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index f7401440cfcb..ece1803e14c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -28,6 +28,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.shared.Flags.extendedWallpaperEffects
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
@@ -143,7 +144,7 @@ constructor(
}
if (!SceneContainerFlag.isEnabled) {
- if (Flags.magicPortraitWallpapers()) {
+ if (extendedWallpaperEffects()) {
launch {
combine(
viewModel.getNotificationStackAbsoluteBottom(
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index 9794c619041e..79a9630e6887 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -27,12 +27,13 @@ import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.R
-import com.android.systemui.Flags
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.res.R as SysUIR
import com.android.systemui.shared.Flags.ambientAod
+import com.android.systemui.shared.Flags.extendedWallpaperEffects
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
@@ -66,7 +67,7 @@ interface WallpaperRepository {
/** Set rootView to get its windowToken afterwards */
var rootView: View?
- /** when we use magic portrait wallpapers, we should always get its bounds from keyguard */
+ /** some wallpapers require bounds to be sent from keyguard */
val shouldSendFocalArea: StateFlow<Boolean>
}
@@ -80,7 +81,7 @@ constructor(
userRepository: UserRepository,
keyguardRepository: KeyguardRepository,
private val wallpaperManager: WallpaperManager,
- context: Context,
+ private val context: Context,
) : WallpaperRepository {
private val wallpaperChanged: Flow<Unit> =
broadcastDispatcher
@@ -125,8 +126,8 @@ constructor(
override val shouldSendFocalArea =
wallpaperInfo
.map {
- val shouldSendNotificationLayout =
- it?.component?.className == MAGIC_PORTRAIT_CLASSNAME
+ val focalAreaTarget = context.resources.getString(SysUIR.string.focal_area_target)
+ val shouldSendNotificationLayout = it?.component?.className == focalAreaTarget
if (shouldSendNotificationLayout) {
sendLockscreenLayoutJob =
scope.launch {
@@ -167,9 +168,8 @@ constructor(
}
.stateIn(
scope,
- // Always be listening for wallpaper changes when magic portrait flag is on
- if (Flags.magicPortraitWallpapers()) SharingStarted.Eagerly else WhileSubscribed(),
- initialValue = Flags.magicPortraitWallpapers(),
+ if (extendedWallpaperEffects()) SharingStarted.Eagerly else WhileSubscribed(),
+ initialValue = extendedWallpaperEffects(),
)
private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
@@ -177,9 +177,4 @@ constructor(
wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
}
}
-
- companion object {
- const val MAGIC_PORTRAIT_CLASSNAME =
- "com.google.android.apps.magicportrait.service.MagicPortraitWallpaperService"
- }
}
diff --git a/packages/SystemUI/tests/utils/src/android/view/WindowManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/view/WindowManagerKosmos.kt
index 025f556991f2..80254d58781a 100644
--- a/packages/SystemUI/tests/utils/src/android/view/WindowManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/view/WindowManagerKosmos.kt
@@ -24,4 +24,6 @@ val Kosmos.fakeWindowManager by Kosmos.Fixture { FakeWindowManager(applicationCo
val Kosmos.mockWindowManager: WindowManager by Kosmos.Fixture { mock(WindowManager::class.java) }
+val Kosmos.mockIWindowManager: IWindowManager by Kosmos.Fixture { mock(IWindowManager::class.java) }
+
var Kosmos.windowManager: WindowManager by Kosmos.Fixture { mockWindowManager }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index ef9bd8282090..5793695a7f01 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -62,6 +62,7 @@ val Kosmos.defaultKeyguardBlueprint by
defaultSettingsPopupMenuSection = mock(),
defaultStatusBarSection = mock(),
defaultNotificationStackScrollLayoutSection = mock(),
+ aodPromotedNotificationSection = mock(),
aodNotificationIconsSection = mock(),
aodBurnInSection = mock(),
clockSection = keyguardClockSection,
@@ -69,7 +70,6 @@ val Kosmos.defaultKeyguardBlueprint by
keyguardSliceViewSection = mock(),
udfpsAccessibilityOverlaySection = mock(),
accessibilityActionsSection = mock(),
- aodPromotedNotificationSection = mock(),
)
}
@@ -84,6 +84,7 @@ val Kosmos.splitShadeBlueprint by
defaultStatusBarSection = mock(),
splitShadeNotificationStackScrollLayoutSection = mock(),
splitShadeGuidelines = mock(),
+ aodPromotedNotificationSection = mock(),
aodNotificationIconsSection = mock(),
aodBurnInSection = mock(),
clockSection = keyguardClockSection,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarOrchestratorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarOrchestratorKosmos.kt
index 8c37bd739bc5..bdcab5fd2eca 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarOrchestratorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarOrchestratorKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.core
import android.content.testableContext
+import android.view.mockIWindowManager
import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.display.data.repository.displayScopeRepository
@@ -84,5 +85,6 @@ val Kosmos.multiDisplayStatusBarStarter by
multiDisplayAutoHideControllerStore,
privacyDotWindowControllerStore,
lightBarControllerStore,
+ mockIWindowManager,
)
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index 373287d76442..a1e8f08db0a6 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -61,7 +61,7 @@ public class DisplayManagerFlags {
private final FlagState mDisplayTopology = new FlagState(
Flags.FLAG_DISPLAY_TOPOLOGY,
- Flags::displayTopology);
+ DesktopExperienceFlags.DISPLAY_TOPOLOGY::isTrue);
private final FlagState mConnectedDisplayErrorHandlingFlagState = new FlagState(
Flags.FLAG_ENABLE_CONNECTED_DISPLAY_ERROR_HANDLING,
@@ -267,7 +267,7 @@ public class DisplayManagerFlags {
private final FlagState mBaseDensityForExternalDisplays = new FlagState(
Flags.FLAG_BASE_DENSITY_FOR_EXTERNAL_DISPLAYS,
- Flags::baseDensityForExternalDisplays
+ DesktopExperienceFlags.BASE_DENSITY_FOR_EXTERNAL_DISPLAYS::isTrue
);
private final FlagState mFramerateOverrideTriggersRrCallbacks = new FlagState(
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
index 3eb38a7029e6..b13dee530ee2 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
@@ -56,8 +56,8 @@ import java.util.stream.Stream;
*/
/* package */ class SystemMediaRoute2Provider2 extends SystemMediaRoute2Provider {
- private static final String ROUTE_ID_PREFIX_SYSTEM = "SYSTEM";
- private static final String ROUTE_ID_SYSTEM_SEPARATOR = ".";
+ private static final String UNIQUE_SYSTEM_ID_PREFIX = "SYSTEM";
+ private static final String UNIQUE_SYSTEM_ID_SEPARATOR = "-";
private final PackageManager mPackageManager;
@@ -67,6 +67,10 @@ import java.util.stream.Stream;
@GuardedBy("mLock")
private final Map<String, ProviderProxyRecord> mProxyRecords = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private final Map<String, SystemMediaSessionRecord> mSessionOriginalIdToSessionRecord =
+ new ArrayMap<>();
+
/**
* Maps package names to corresponding sessions maintained by {@link MediaRoute2ProviderService
* provider services}.
@@ -150,7 +154,7 @@ import java.util.stream.Stream;
if (currentProxyRecord != null) {
currentProxyRecord.releaseSession(
requestId, existingSession.getOriginalId());
- existingSessionRecord.removeSelfFromSessionMap();
+ existingSessionRecord.removeSelfFromSessionMaps();
}
}
}
@@ -240,6 +244,24 @@ import java.util.stream.Stream;
super.setRouteVolume(requestId, routeOriginalId, volume);
}
+ @Override
+ public void setSessionVolume(long requestId, String sessionOriginalId, int volume) {
+ if (SYSTEM_SESSION_ID.equals(sessionOriginalId)) {
+ super.setSessionVolume(requestId, sessionOriginalId, volume);
+ return;
+ }
+ synchronized (mLock) {
+ var sessionRecord = mSessionOriginalIdToSessionRecord.get(sessionOriginalId);
+ var proxyRecord = sessionRecord != null ? sessionRecord.getProxyRecord() : null;
+ if (proxyRecord != null) {
+ proxyRecord.mProxy.setSessionVolume(
+ requestId, sessionRecord.getServiceSessionId(), volume);
+ return;
+ }
+ }
+ notifyRequestFailed(requestId, MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE);
+ }
+
/**
* Returns the uid that corresponds to the given name and user handle, or {@link
* Process#INVALID_UID} if a uid couldn't be found.
@@ -376,16 +398,17 @@ import java.util.stream.Stream;
}
/**
- * Equivalent to {@link #asSystemRouteId}, except it takes a unique route id instead of a
- * original id.
+ * Equivalent to {@link #asUniqueSystemId}, except it takes a unique id instead of an original
+ * id.
*/
private static String uniqueIdAsSystemRouteId(String providerId, String uniqueRouteId) {
- return asSystemRouteId(providerId, MediaRouter2Utils.getOriginalId(uniqueRouteId));
+ return asUniqueSystemId(providerId, MediaRouter2Utils.getOriginalId(uniqueRouteId));
}
/**
* Returns a unique {@link MediaRoute2Info#getOriginalId() original id} for this provider to
- * publish system media routes from {@link MediaRoute2ProviderService provider services}.
+ * publish system media routes and sessions from {@link MediaRoute2ProviderService provider
+ * services}.
*
* <p>This provider will publish system media routes as part of the system routing session.
* However, said routes may also support {@link MediaRoute2Info#FLAG_ROUTING_TYPE_REMOTE remote
@@ -393,12 +416,12 @@ import java.util.stream.Stream;
* we derive a {@link MediaRoute2Info#getOriginalId original id} that is unique among all
* original route ids used by this provider.
*/
- private static String asSystemRouteId(String providerId, String originalRouteId) {
- return ROUTE_ID_PREFIX_SYSTEM
- + ROUTE_ID_SYSTEM_SEPARATOR
+ private static String asUniqueSystemId(String providerId, String originalId) {
+ return UNIQUE_SYSTEM_ID_PREFIX
+ + UNIQUE_SYSTEM_ID_SEPARATOR
+ providerId
- + ROUTE_ID_SYSTEM_SEPARATOR
- + originalRouteId;
+ + UNIQUE_SYSTEM_ID_SEPARATOR
+ + originalId;
}
/**
@@ -485,7 +508,7 @@ import java.util.stream.Stream;
continue;
}
String id =
- asSystemRouteId(providerInfo.getUniqueId(), sourceRoute.getOriginalId());
+ asUniqueSystemId(providerInfo.getUniqueId(), sourceRoute.getOriginalId());
var newRouteBuilder = new MediaRoute2Info.Builder(id, sourceRoute);
if ((sourceRoute.getSupportedRoutingTypes()
& MediaRoute2Info.FLAG_ROUTING_TYPE_SYSTEM_AUDIO)
@@ -534,6 +557,9 @@ import java.util.stream.Stream;
RoutingSessionInfo translatedSession;
synchronized (mLock) {
mSessionRecord = systemMediaSessionRecord;
+ mSessionOriginalIdToSessionRecord.put(
+ systemMediaSessionRecord.mOriginalId,
+ systemMediaSessionRecord);
mPackageNameToSessionRecord.put(
mClientPackageName, systemMediaSessionRecord);
mPendingSessionCreations.remove(mRequestId);
@@ -576,24 +602,38 @@ import java.util.stream.Stream;
private final String mProviderId;
- @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
- @NonNull
- private RoutingSessionInfo mSourceSessionInfo;
+ /**
+ * The {@link RoutingSessionInfo#getOriginalId() original id} with which this session is
+ * published.
+ *
+ * <p>Derived from the service routing session, using {@link #asUniqueSystemId}.
+ */
+ private final String mOriginalId;
+
+ // @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+ @NonNull private RoutingSessionInfo mSourceSessionInfo;
/**
- * The same as {@link #mSourceSessionInfo}, except ids are {@link #asSystemRouteId system
+ * The same as {@link #mSourceSessionInfo}, except ids are {@link #asUniqueSystemId system
* provider ids}.
*/
- @NonNull
- private RoutingSessionInfo mTranslatedSessionInfo;
+ // @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+ @NonNull private RoutingSessionInfo mTranslatedSessionInfo;
SystemMediaSessionRecord(
@NonNull String providerId, @NonNull RoutingSessionInfo sessionInfo) {
mProviderId = providerId;
mSourceSessionInfo = sessionInfo;
+ mOriginalId =
+ asUniqueSystemId(sessionInfo.getProviderId(), sessionInfo.getOriginalId());
mTranslatedSessionInfo = asSystemProviderSession(sessionInfo);
}
+ // @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+ public String getServiceSessionId() {
+ return mSourceSessionInfo.getOriginalId();
+ }
+
@Override
public void onSessionUpdate(@NonNull RoutingSessionInfo sessionInfo) {
RoutingSessionInfo translatedSessionInfo = asSystemProviderSession(sessionInfo);
@@ -612,31 +652,32 @@ import java.util.stream.Stream;
@Override
public void onSessionReleased() {
synchronized (mLock) {
- removeSelfFromSessionMap();
+ removeSelfFromSessionMaps();
}
notifyGlobalSessionInfoUpdated();
}
- @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+ // @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
@Nullable
public ProviderProxyRecord getProxyRecord() {
ProviderProxyRecord provider = mProxyRecords.get(mProviderId);
if (provider == null) {
// Unexpected condition where the proxy is no longer available while there's an
// ongoing session. Could happen due to a crash in the provider process.
- removeSelfFromSessionMap();
+ removeSelfFromSessionMaps();
}
return provider;
}
- @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
- private void removeSelfFromSessionMap() {
+ // @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+ private void removeSelfFromSessionMaps() {
+ mSessionOriginalIdToSessionRecord.remove(mOriginalId);
mPackageNameToSessionRecord.remove(mSourceSessionInfo.getClientPackageName());
}
private RoutingSessionInfo asSystemProviderSession(RoutingSessionInfo session) {
var builder =
- new RoutingSessionInfo.Builder(session)
+ new RoutingSessionInfo.Builder(session, mOriginalId)
.setProviderId(mUniqueId)
.setSystemSession(true)
.clearSelectedRoutes()
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java
index ea85710eab44..a96c477c78d2 100644
--- a/services/supervision/java/com/android/server/supervision/SupervisionService.java
+++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java
@@ -177,23 +177,24 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
}
- /** Ensures that supervision is enabled when the supervision app is the profile owner. */
+ /**
+ * Ensures that supervision is enabled when the supervision app is the profile owner.
+ *
+ * <p>The state syncing with the DevicePolicyManager can only enable supervision and never
+ * disable. Supervision can only be disabled explicitly via calls to the
+ * {@link #setSupervisionEnabledForUser} method.
+ */
private void syncStateWithDevicePolicyManager(@UserIdInt int userId) {
final DevicePolicyManagerInternal dpmInternal = mInjector.getDpmInternal();
final ComponentName po =
dpmInternal != null ? dpmInternal.getProfileOwnerAsUser(userId) : null;
if (po != null && po.getPackageName().equals(getSystemSupervisionPackage())) {
- setSupervisionEnabledForUserInternal(userId, true, po.getPackageName());
+ setSupervisionEnabledForUserInternal(userId, true, getSystemSupervisionPackage());
} else if (po != null && po.equals(getSupervisionProfileOwnerComponent())) {
// TODO(b/392071637): Consider not enabling supervision in case profile owner is given
// to the legacy supervision profile owner component.
setSupervisionEnabledForUserInternal(userId, true, po.getPackageName());
- } else {
- // TODO(b/381428475): Avoid disabling supervision when the app is not the profile owner.
- // This might only be possible after introducing specific and public APIs to enable
- // and disable supervision.
- setSupervisionEnabledForUserInternal(userId, false, /* supervisionAppPackage= */ null);
}
}
@@ -279,7 +280,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
@VisibleForTesting
- @SuppressLint("MissingPermission") // not needed for a service
+ @SuppressLint("MissingPermission") // not needed for a system service
void registerProfileOwnerListener() {
IntentFilter poIntentFilter = new IntentFilter();
poIntentFilter.addAction(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED);
diff --git a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
index b150b1495042..da022780ea75 100644
--- a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
@@ -161,6 +161,18 @@ class SupervisionServiceTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SYNC_WITH_DPM)
+ fun profileOwnerChanged_supervisionAppIsNotProfileOwner_doesNotDisableSupervision() {
+ service.mInternal.setSupervisionEnabledForUser(USER_ID, true)
+ whenever(mockDpmInternal.getProfileOwnerAsUser(USER_ID))
+ .thenReturn(ComponentName("other.package", "MainActivity"))
+
+ broadcastProfileOwnerChanged(USER_ID)
+
+ assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue()
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SYNC_WITH_DPM)
fun profileOwnerChanged_supervisionAppIsNotProfileOwner_doesNotEnableSupervision() {
whenever(mockDpmInternal.getProfileOwnerAsUser(USER_ID))
.thenReturn(ComponentName("other.package", "MainActivity"))
@@ -258,7 +270,7 @@ class SupervisionServiceTest {
private companion object {
const val USER_ID = 100
- val APP_UID = USER_ID * UserHandle.PER_USER_RANGE
+ const val APP_UID = USER_ID * UserHandle.PER_USER_RANGE
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 18f44ddff086..eebe49de0010 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,13 +18,12 @@ package com.android.server.wm.flicker
import android.app.Instrumentation
import android.content.Intent
-import android.os.UserHandle
import android.platform.test.annotations.Presubmit
-import android.provider.Settings
import android.tools.flicker.junit.FlickerBuilderProvider
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.traces.component.ComponentNameMatcher
+import android.tools.traces.executeShellCommand
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
@@ -47,11 +46,8 @@ constructor(
) {
init {
tapl.setExpectedRotationCheckEnabled(true)
- Settings.System.putIntForUser(
- instrumentation.targetContext.contentResolver,
- Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
- 0,
- UserHandle.USER_CURRENT_OR_SELF
+ executeShellCommand(
+ "settings put system hide_rotation_lock_toggle_for_accessibility 1"
)
}