summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java4
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java2
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java17
-rw-r--r--core/res/res/layout/preference_list_fragment.xml1
-rw-r--r--core/res/res/layout/preference_list_fragment_material.xml1
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java2
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java10
-rw-r--r--libs/WindowManager/Shell/res/drawable/decor_desktop_mode_maximize_button_dark.xml3
-rw-r--r--packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt2
-rw-r--r--packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt16
-rw-r--r--packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt6
-rw-r--r--packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml1
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt136
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt95
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt123
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt12
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt32
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt35
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModel.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt37
-rw-r--r--services/core/java/com/android/server/wm/AppWarnings.java14
-rw-r--r--services/core/java/com/android/server/wm/DragDropController.java29
-rw-r--r--services/core/java/com/android/server/wm/PageSizeMismatchDialog.java12
-rw-r--r--services/tests/wmtests/Android.bp1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java81
37 files changed, 769 insertions, 242 deletions
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 8baa55f8e377..6e2e1009fd40 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -74,8 +74,8 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
}
@Override
- void flush(@FlushReason int reason) {
- mParent.flush(reason);
+ void internalFlush(@FlushReason int reason) {
+ mParent.internalFlush(reason);
}
@Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 3f3484d5a527..b7a77d701045 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -663,7 +663,7 @@ public final class ContentCaptureManager {
@UiThread
public void flush(@FlushReason int reason) {
if (mOptions.lite) return;
- getMainContentCaptureSession().flush(reason);
+ getMainContentCaptureSession().internalFlush(reason);
}
/**
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 6bb2975d9cf1..791a6f4254ec 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -342,7 +342,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Flushes the buffered events to the service.
*/
- abstract void flush(@FlushReason int reason);
+ abstract void internalFlush(@FlushReason int reason);
/**
* Sets the {@link ContentCaptureContext} associated with the session.
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index eddfc42da9bd..29cae857098d 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -375,7 +375,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
void onDestroy() {
clearAndRunOnContentCaptureThread(() -> {
try {
- flush(FLUSH_REASON_SESSION_FINISHED);
+ internalFlush(FLUSH_REASON_SESSION_FINISHED);
} finally {
destroySession();
}
@@ -623,7 +623,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
- flush(flushReason);
+ internalFlush(flushReason);
}
private boolean hasStarted() {
@@ -687,15 +687,18 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (sVerbose) Log.v(TAG, "Nothing to flush");
return;
}
- flush(reason);
+ internalFlush(reason);
}
- /** @hide */
+ /**
+ * Internal API to flush the buffered events to the service.
+ *
+ * Do not confuse this with the public API {@link #flush()}.
+ *
+ * @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Override
- public void flush(@FlushReason int reason) {
- // TODO: b/380381249 renaming the internal APIs to prevent confusions between this and the
- // public API.
+ public void internalFlush(@FlushReason int reason) {
runOnContentCaptureThread(() -> flushImpl(reason));
}
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index 44a5df9b60be..c43975e4ad3c 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -19,7 +19,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
- android:fitsSystemWindows="true"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@android:color/transparent"
diff --git a/core/res/res/layout/preference_list_fragment_material.xml b/core/res/res/layout/preference_list_fragment_material.xml
index 4df76029e606..db2fe7d038e0 100644
--- a/core/res/res/layout/preference_list_fragment_material.xml
+++ b/core/res/res/layout/preference_list_fragment_material.xml
@@ -19,7 +19,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
- android:fitsSystemWindows="true"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@android:color/transparent"
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index f87b6994900f..ee8d428d8370 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -224,7 +224,7 @@ public class ContentCaptureSessionTest {
}
@Override
- void flush(int reason) {
+ void internalFlush(int reason) {
throw new UnsupportedOperationException("should not have been called");
}
diff --git a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
index 4a5123ec0663..a1d7f87614e4 100644
--- a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
@@ -263,7 +263,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.flush(REASON);
+ session.internalFlush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -280,7 +280,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.flush(REASON);
+ session.internalFlush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -298,7 +298,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.flush(REASON);
+ session.internalFlush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -316,7 +316,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.flush(REASON);
+ session.internalFlush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -544,7 +544,7 @@ public class MainContentCaptureSessionTest {
session.mContentCaptureHandler = null;
session.mDirectServiceInterface = null;
- session.flush(REASON);
+ session.internalFlush(REASON);
assertThat(session.mEvents).hasSize(1);
assertThat(session.mEventProcessQueue).isEmpty();
diff --git a/libs/WindowManager/Shell/res/drawable/decor_desktop_mode_maximize_button_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_desktop_mode_maximize_button_dark.xml
index e5fe1b5431eb..83a3959ee2f9 100644
--- a/libs/WindowManager/Shell/res/drawable/decor_desktop_mode_maximize_button_dark.xml
+++ b/libs/WindowManager/Shell/res/drawable/decor_desktop_mode_maximize_button_dark.xml
@@ -22,5 +22,6 @@
android:viewportWidth="960">
<path
android:fillColor="@android:color/black"
- android:pathData="M160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM160,720L800,720Q800,720 800,720Q800,720 800,720L800,320L160,320L160,720Q160,720 160,720Q160,720 160,720Z"/>
+ android:pathData="M 244.79 796.408 C 222.79 796.408 203.79 788.74 187.79 773.408 C 172.457 757.408 164.79 738.408 164.79 716.408 L 164.79 236.408 C 164.79 214.408 172.457 195.741 187.79 180.408 C 203.79 164.408 222.79 156.408 244.79 156.408 L 724.79 156.408 C 746.79 156.408 765.458 164.408 780.79 180.408 C 796.79 195.741 804.79 214.408 804.79 236.408 L 804.79 716.408 C 804.79 738.408 796.79 757.408 780.79 773.408 C 765.458 788.74 746.79 796.408 724.79 796.408 Z M 244.79 716.408 L 724.79 716.408 L 724.79 236.408 L 244.79 236.408 Z M 244.79 236.408 L 244.79 716.408 Z"
+ />
</vector> \ No newline at end of file
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
index bd5d17cb2468..b82c554ea26a 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
@@ -45,7 +45,7 @@ interface PreferenceScreenBinding : PreferenceBinding {
context.getString(screenTitle)
} else {
screenMetadata.getScreenTitle(context)
- ?: (this as? PreferenceTitleProvider)?.getTitle(context)
+ ?: (screenMetadata as? PreferenceTitleProvider)?.getTitle(context)
}
}
}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
index e237a6a4cf14..ffe181d0c350 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
@@ -21,6 +21,7 @@ import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.annotation.XmlRes
+import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceScreen
import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
import com.android.settingslib.metadata.PreferenceScreenBindingKeyProvider
@@ -38,6 +39,11 @@ open class PreferenceFragment :
preferenceScreen = createPreferenceScreen()
}
+ override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
+ super.setPreferenceScreen(preferenceScreen)
+ updateActivityTitle()
+ }
+
fun createPreferenceScreen(): PreferenceScreen? =
createPreferenceScreen(PreferenceScreenFactory(this))
@@ -102,9 +108,19 @@ open class PreferenceFragment :
override fun onResume() {
super.onResume()
+ // Even when activity has several fragments with preference screen, this will keep activity
+ // title in sync when fragment manager pops back stack.
+ updateActivityTitle()
preferenceScreenBindingHelper?.onResume()
}
+ internal fun updateActivityTitle() {
+ if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) return
+ val activity = activity ?: return
+ val title = preferenceScreen?.title ?: return
+ if (activity.title != title) activity.title = title
+ }
+
override fun onPause() {
preferenceScreenBindingHelper?.onPause()
super.onPause()
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
index 7492c2d0aaf2..4a6a589cd3c9 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -52,7 +52,7 @@ import com.google.common.collect.ImmutableMultimap
*/
class PreferenceScreenBindingHelper(
context: Context,
- fragment: PreferenceFragment,
+ private val fragment: PreferenceFragment,
private val preferenceBindingFactory: PreferenceBindingFactory,
private val preferenceScreen: PreferenceScreen,
private val preferenceHierarchy: PreferenceHierarchy,
@@ -156,7 +156,9 @@ class PreferenceScreenBindingHelper(
// bind preference to update UI
preferenceScreen.findPreference<Preference>(key)?.let {
- preferences[key]?.let { node -> preferenceBindingFactory.bind(it, node) }
+ val node = preferences[key] ?: return@let
+ preferenceBindingFactory.bind(it, node)
+ if (it == preferenceScreen) fragment.updateActivityTitle()
}
// check reason to avoid potential infinite loop
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
index 2776544e2948..7d7bec14ed78 100644
--- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
+++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
@@ -48,6 +48,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@android:id/title"
app:layout_constraintStart_toStartOf="parent"
+ android:paddingTop="@dimen/settingslib_expressive_space_extrasmall6"
android:textAlignment="viewStart"
android:clickable="true"
android:visibility="gone"
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index 56a4ed078670..b0af8b180cce 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -343,7 +343,7 @@ class CallChipViewModelTest : SysuiTestCase() {
repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = null))
- assertThat((latest as OngoingActivityChipModel.Shown).onClickListener).isNull()
+ assertThat((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy).isNull()
}
@Test
@@ -353,7 +353,7 @@ class CallChipViewModelTest : SysuiTestCase() {
val pendingIntent = mock<PendingIntent>()
repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = pendingIntent))
- val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListener
+ val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListenerLegacy
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -370,7 +370,8 @@ class CallChipViewModelTest : SysuiTestCase() {
val pendingIntent = mock<PendingIntent>()
repo.setOngoingCallState(inCallModel(startTimeMs = 0, intent = pendingIntent))
- val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListener
+ val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListenerLegacy
+
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
index c511c433d92d..fcf8c834dc12 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel
import android.content.DialogInterface
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -25,6 +26,7 @@ import com.android.internal.jank.Cuj
import com.android.systemui.Flags.FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.Expandable
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
@@ -46,8 +48,10 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.policy.CastDevice
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -84,6 +88,8 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest = kosmos.castToOtherDeviceChipViewModel
@@ -263,7 +269,13 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
// WHEN the stop action on the dialog is clicked
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockScreenCastDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockScreenCastDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden...
@@ -296,7 +308,13 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
// WHEN the stop action on the dialog is clicked
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockGenericCastDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockGenericCastDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden...
@@ -416,13 +434,14 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_projectionStateEntireScreen_clickListenerShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -431,6 +450,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_projectionStateSingleTask_clickListenerShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -442,7 +462,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
createTask(taskId = 1),
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -451,6 +471,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_routerStateCasting_clickListenerShowsGenericCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -466,7 +487,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
)
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -480,13 +501,14 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_projectionStateCasting_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
clickListener!!.onClick(chipView)
val cujCaptor = argumentCaptor<DialogCuj>()
@@ -499,6 +521,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_routerStateCasting_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -514,7 +537,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
)
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
clickListener!!.onClick(chipView)
val cujCaptor = argumentCaptor<DialogCuj>()
@@ -525,4 +548,103 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
.isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
assertThat(cujCaptor.firstValue.tag).contains("Cast")
}
+
+ @Test
+ @EnableFlags(StatusBarChipsModernization.FLAG_NAME)
+ fun chip_routerStateCasting_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaRouterRepo.castDevices.value =
+ listOf(
+ CastDevice(
+ state = CastDevice.CastState.Connected,
+ id = "id",
+ name = "name",
+ description = "desc",
+ origin = CastDevice.CastOrigin.MediaRouter,
+ )
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarChipsModernization.FLAG_NAME)
+ fun chip_projectionStateCasting_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_projectionStateEntireScreen_clickBehaviorShowsScreenCastDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockScreenCastDialog), any(), anyBoolean())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_projectionStateSingleTask_clickBehaviorShowsScreenCastDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.SingleTask(
+ CAST_TO_OTHER_DEVICES_PACKAGE,
+ hostDeviceName = null,
+ createTask(taskId = 1),
+ )
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockScreenCastDialog), any(), anyBoolean())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_routerStateCasting_clickBehaviorShowsGenericCastDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaRouterRepo.castDevices.value =
+ listOf(
+ CastDevice(
+ state = CastDevice.CastState.Connected,
+ id = "id",
+ name = "name",
+ description = "desc",
+ origin = CastDevice.CastOrigin.MediaRouter,
+ )
+ )
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockGenericCastDialog), any(), anyBoolean())
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 902db5e10589..eec23d3ffb1a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -650,7 +650,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
)
val chip = latest!![0]
- chip.onClickListener!!.onClick(mock<View>())
+ chip.onClickListenerLegacy!!.onClick(mock<View>())
assertThat(latestChipTap).isEqualTo("clickTest")
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
index 48d8add6b33a..1f82dcd9c308 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
@@ -17,12 +17,15 @@
package com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel
import android.content.DialogInterface
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.jank.Cuj
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.Expandable
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
@@ -41,8 +44,10 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -77,6 +82,8 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest = kosmos.screenRecordChipViewModel
@@ -106,7 +113,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Countdown::class.java)
assertThat((latest as OngoingActivityChipModel.Shown).icon).isNull()
- assertThat((latest as OngoingActivityChipModel.Shown).onClickListener).isNull()
+ assertThat((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy).isNull()
}
// The millis we typically get from [ScreenRecordRepository] are around 2995, 1995, and 995.
@@ -177,7 +184,13 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
// WHEN the stop action on the dialog is clicked
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockSystemUIDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockSystemUIDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN both the screen record chip and the share-to-app chip are immediately hidden...
@@ -263,13 +276,14 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_notProjecting_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionRepo.mediaProjectionState.value = MediaProjectionState.NotProjecting
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -279,6 +293,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_projectingEntireScreen_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -286,7 +301,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen("host.package")
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -296,6 +311,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_projectingSingleTask_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -307,7 +323,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
FakeActivityTaskManager.createTask(taskId = 1),
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -317,22 +333,85 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
}
@Test
- fun chip_clickListenerHasCuj() =
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ fun chip_clickListenerHasCujLegacy() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen("host.package")
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
clickListener!!.onClick(chipView)
val cujCaptor = argumentCaptor<DialogCuj>()
verify(kosmos.mockDialogTransitionAnimator)
.showFromView(any(), any(), cujCaptor.capture(), anyBoolean())
-
assertThat(cujCaptor.firstValue.cujType)
.isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
assertThat(cujCaptor.firstValue.tag).contains("Screen record")
}
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_recordingState_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
+ assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_notProjecting_expandActionBehaviorShowsDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
+ mediaProjectionRepo.mediaProjectionState.value = MediaProjectionState.NotProjecting
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+
+ expandAction.onClick(mockExpandable)
+ verify(kosmos.mockDialogTransitionAnimator).show(any(), any(), anyBoolean())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_projectingEntireScreen_expandActionBehaviorShowsDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+
+ expandAction.onClick(mockExpandable)
+ verify(kosmos.mockDialogTransitionAnimator).show(any(), any(), anyBoolean())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_projectingSingleTask_expandActionBehaviorShowsDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.SingleTask(
+ "host.package",
+ hostDeviceName = null,
+ FakeActivityTaskManager.createTask(taskId = 1),
+ )
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+
+ expandAction.onClick(mockExpandable)
+ verify(kosmos.mockDialogTransitionAnimator).show(any(), any(), anyBoolean())
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
index b3dec2eaa1c6..36fc5aa16407 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.sharetoapp.ui.viewmodel
import android.content.DialogInterface
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -25,6 +26,7 @@ import com.android.internal.jank.Cuj
import com.android.systemui.Flags.FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.Expandable
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
@@ -45,8 +47,10 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -81,6 +85,8 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest = kosmos.shareToAppChipViewModel
@@ -215,7 +221,13 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
// WHEN the stop action on the dialog is clicked
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockScreenShareDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockScreenShareDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden...
@@ -268,13 +280,14 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_noScreen_clickListenerShowsGenericShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.NoScreen(NORMAL_PACKAGE)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -288,13 +301,14 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_entireScreen_clickListenerShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
mediaProjectionRepo.mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -308,6 +322,7 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_singleTask_clickListenerShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -318,7 +333,7 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
createTask(taskId = 1),
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
assertThat(clickListener).isNotNull()
clickListener!!.onClick(chipView)
@@ -332,6 +347,7 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -342,7 +358,7 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
createTask(taskId = 1),
)
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
+ val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
clickListener!!.onClick(chipView)
val cujCaptor = argumentCaptor<DialogCuj>()
@@ -353,4 +369,101 @@ class ShareToAppChipViewModelTest : SysuiTestCase() {
.isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
assertThat(cujCaptor.firstValue.tag).contains("Share")
}
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_noScreen_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.NoScreen(NORMAL_PACKAGE)
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_entireScreen_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_singleTask_hasClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.SingleTask(
+ NORMAL_PACKAGE,
+ hostDeviceName = null,
+ createTask(taskId = 1),
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ }
+
+ @Test
+ @EnableFlags(
+ FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP,
+ StatusBarRootModernization.FLAG_NAME,
+ StatusBarChipsModernization.FLAG_NAME,
+ )
+ fun chip_noScreen_clickBehaviorShowsGenericShareDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.NoScreen(NORMAL_PACKAGE)
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockGenericShareDialog), any(), any())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_entireScreen_clickBehaviorShowsScreenShareDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockScreenShareDialog), any(), any())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_singleTask_clickBehaviorShowsScreenShareDialog() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.SingleTask(
+ NORMAL_PACKAGE,
+ hostDeviceName = null,
+ createTask(taskId = 1),
+ )
+
+ val expandAction =
+ ((latest as OngoingActivityChipModel.Shown).clickBehavior
+ as OngoingActivityChipModel.ClickBehavior.ExpandAction)
+ expandAction.onClick(mockExpandable)
+
+ verify(kosmos.mockDialogTransitionAnimator)
+ .show(eq(mockScreenShareDialog), any(), any())
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
index 8d4c68de8c79..d099e70c9bc5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
@@ -57,7 +57,8 @@ class ChipTransitionHelperTest : SysuiTestCase() {
icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
- onClickListener = null,
+ onClickListenerLegacy = null,
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
inputChipFlow.value = newChip
@@ -68,7 +69,8 @@ class ChipTransitionHelperTest : SysuiTestCase() {
OngoingActivityChipModel.Shown.IconOnly(
icon = createIcon(R.drawable.ic_hotspot),
colors = ColorsModel.Themed,
- onClickListener = null,
+ onClickListenerLegacy = null,
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
inputChipFlow.value = newerChip
@@ -89,7 +91,8 @@ class ChipTransitionHelperTest : SysuiTestCase() {
icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
- onClickListener = null,
+ onClickListenerLegacy = null,
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
inputChipFlow.value = shownChip
@@ -129,7 +132,8 @@ class ChipTransitionHelperTest : SysuiTestCase() {
icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
- onClickListener = null,
+ onClickListenerLegacy = null,
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
inputChipFlow.value = shownChip
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
index e3510f5ce280..fc3af11c30b3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.chips.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -23,14 +25,19 @@ import com.android.internal.jank.Cuj
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
+import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickCallback
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import kotlin.test.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
@@ -53,8 +60,11 @@ class OngoingActivityChipViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun createDialogLaunchOnClickListener_showsDialogOnClick() {
val cuj = DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Test")
val clickListener =
@@ -68,11 +78,23 @@ class OngoingActivityChipViewModelTest : SysuiTestCase() {
clickListener.onClick(chipView)
verify(dialogTransitionAnimator)
- .showFromView(
- eq(mockSystemUIDialog),
- eq(chipBackgroundView),
- eq(cuj),
- anyBoolean(),
+ .showFromView(eq(mockSystemUIDialog), eq(chipBackgroundView), eq(cuj), anyBoolean())
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun createDialogLaunchOnClickCallback_showsDialogOnClick() {
+ val cuj = DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Test")
+ val clickCallback =
+ createDialogLaunchOnClickCallback(
+ dialogDelegate,
+ dialogTransitionAnimator,
+ cuj,
+ logcatLogBuffer("OngoingActivityChipViewModelTest"),
+ "tag",
)
+
+ clickCallback.invoke(mockExpandable)
+ verify(dialogTransitionAnimator).show(eq(mockSystemUIDialog), any(), anyBoolean())
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index 42358cce59a2..a4b6a841d61b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -26,6 +26,7 @@ import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
@@ -44,6 +45,7 @@ import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
@@ -91,6 +93,8 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest = kosmos.ongoingActivityChipsViewModel
@@ -294,7 +298,13 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
// WHEN screen record gets stopped via dialog
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockSystemUIDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockSystemUIDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden with no animation
@@ -315,7 +325,13 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
// WHEN media projection gets stopped via dialog
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockSystemUIDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockSystemUIDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden with no animation
@@ -330,6 +346,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
fun getStopActionFromDialog(
latest: OngoingActivityChipModel?,
chipView: View,
+ expandable: Expandable,
dialog: SystemUIDialog,
kosmos: Kosmos,
): DialogInterface.OnClickListener {
@@ -349,9 +366,17 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
.create(any<SystemUIDialog.Delegate>())
whenever(kosmos.packageManager.getApplicationInfo(eq(NORMAL_PACKAGE), any<Int>()))
.thenThrow(PackageManager.NameNotFoundException())
- // Click the chip so that we open the dialog and we fill in [dialogStopAction]
- val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
- clickListener!!.onClick(chipView)
+
+ if (StatusBarChipsModernization.isEnabled) {
+ val clickBehavior = (latest as OngoingActivityChipModel.Shown).clickBehavior
+ (clickBehavior as OngoingActivityChipModel.ClickBehavior.ExpandAction).onClick(
+ expandable
+ )
+ } else {
+ val clickListener =
+ ((latest as OngoingActivityChipModel.Shown).onClickListenerLegacy)
+ clickListener!!.onClick(chipView)
+ }
return dialogStopAction
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
index 0f42f29e76ee..28f360108e50 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
@@ -25,6 +25,7 @@ import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Expandable
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
@@ -104,6 +105,8 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest by lazy { kosmos.ongoingActivityChipsViewModel }
@@ -679,7 +682,13 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
// WHEN screen record gets stopped via dialog
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockSystemUIDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockSystemUIDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden with no animation
@@ -700,7 +709,13 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
// WHEN media projection gets stopped via dialog
val dialogStopAction =
- getStopActionFromDialog(latest, chipView, mockSystemUIDialog, kosmos)
+ getStopActionFromDialog(
+ latest,
+ chipView,
+ mockExpandable,
+ mockSystemUIDialog,
+ kosmos,
+ )
dialogStopAction.onClick(mock<DialogInterface>(), 0)
// THEN the chip is immediately hidden with no animation
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index 4fb8f724c971..108d737e7658 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -92,7 +92,10 @@ constructor(
OngoingActivityChipModel.Shown.IconOnly(
icon = icon,
colors = colors,
- getOnClickListener(state),
+ onClickListenerLegacy = getOnClickListener(state),
+ // TODO(b/372657935): Add click support for the call chip when
+ // StatusBarChipModernization is enabled.
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
} else {
val startTimeInElapsedRealtime =
@@ -102,7 +105,10 @@ constructor(
icon = icon,
colors = colors,
startTimeMs = startTimeInElapsedRealtime,
- getOnClickListener(state),
+ onClickListenerLegacy = getOnClickListener(state),
+ // TODO(b/372657935): Add click support for the call chip when
+ // StatusBarChipModernization is enabled.
+ clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
index 3422337523f9..baa8eec5f767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.ChipTransitionHelper
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
+import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickCallback
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
@@ -204,13 +205,25 @@ constructor(
colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
startTimeMs = systemClock.elapsedRealtime(),
- createDialogLaunchOnClickListener(
- createCastScreenToOtherDeviceDialogDelegate(state),
- dialogTransitionAnimator,
- DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Cast to other device"),
- logger,
- TAG,
- ),
+ onClickListenerLegacy =
+ createDialogLaunchOnClickListener(
+ createCastScreenToOtherDeviceDialogDelegate(state),
+ dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ ),
+ clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ onClick =
+ createDialogLaunchOnClickCallback(
+ createCastScreenToOtherDeviceDialogDelegate(state),
+ dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ )
+ ),
)
}
@@ -225,16 +238,24 @@ constructor(
)
),
colors = ColorsModel.Red,
- createDialogLaunchOnClickListener(
- createGenericCastToOtherDeviceDialogDelegate(deviceName),
- dialogTransitionAnimator,
- DialogCuj(
- Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP,
- tag = "Cast to other device audio only",
+ onClickListenerLegacy =
+ createDialogLaunchOnClickListener(
+ createGenericCastToOtherDeviceDialogDelegate(deviceName),
+ dialogTransitionAnimator,
+ DIALOG_CUJ_AUDIO_ONLY,
+ logger,
+ TAG,
+ ),
+ clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ createDialogLaunchOnClickCallback(
+ createGenericCastToOtherDeviceDialogDelegate(deviceName),
+ dialogTransitionAnimator,
+ DIALOG_CUJ_AUDIO_ONLY,
+ logger,
+ TAG,
+ )
),
- logger,
- TAG,
- ),
)
}
@@ -256,6 +277,13 @@ constructor(
companion object {
@DrawableRes val CAST_TO_OTHER_DEVICE_ICON = R.drawable.ic_cast_connected
+ private val DIALOG_CUJ =
+ DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Cast to other device")
+ private val DIALOG_CUJ_AUDIO_ONLY =
+ DialogCuj(
+ Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP,
+ tag = "Cast to other device audio only",
+ )
private val TAG = "CastToOtherVM".pad()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index 18b0dee1c08f..b7cad625b7b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -83,6 +83,7 @@ constructor(
)
}
}
+ val clickBehavior = OngoingActivityChipModel.ClickBehavior.None
val isShowingHeadsUpFromChipTap =
headsUpState is TopPinnedState.Pinned &&
@@ -91,7 +92,12 @@ constructor(
if (isShowingHeadsUpFromChipTap) {
// If the user tapped this chip to show the HUN, we want to just show the icon because
// the HUN will show the rest of the information.
- return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
+ return OngoingActivityChipModel.Shown.IconOnly(
+ icon,
+ colors,
+ onClickListener,
+ clickBehavior,
+ )
}
if (this.promotedContent.shortCriticalText != null) {
@@ -100,6 +106,7 @@ constructor(
colors,
this.promotedContent.shortCriticalText,
onClickListener,
+ clickBehavior,
)
}
@@ -111,11 +118,21 @@ constructor(
// notification will likely just be set to the current time, which would cause the chip
// to always show "now". We don't want early testers to get that experience since it's
// not what will happen at launch, so just don't show any time.
- return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
+ return OngoingActivityChipModel.Shown.IconOnly(
+ icon,
+ colors,
+ onClickListener,
+ clickBehavior,
+ )
}
if (this.promotedContent.time == null) {
- return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
+ return OngoingActivityChipModel.Shown.IconOnly(
+ icon,
+ colors,
+ onClickListener,
+ clickBehavior,
+ )
}
when (this.promotedContent.time.mode) {
PromotedNotificationContentModel.When.Mode.BasicTime -> {
@@ -124,6 +141,7 @@ constructor(
colors,
time = this.promotedContent.time.time,
onClickListener,
+ clickBehavior,
)
}
PromotedNotificationContentModel.When.Mode.CountUp -> {
@@ -132,6 +150,7 @@ constructor(
colors,
startTimeMs = this.promotedContent.time.time,
onClickListener,
+ clickBehavior,
)
}
PromotedNotificationContentModel.When.Mode.CountDown -> {
@@ -141,6 +160,7 @@ constructor(
colors,
startTimeMs = this.promotedContent.time.time,
onClickListener,
+ clickBehavior,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
index 0065593c7b73..7f2327a742e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.ChipTransitionHelper
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
+import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickCallback
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.time.SystemClock
@@ -91,16 +92,24 @@ constructor(
),
colors = ColorsModel.Red,
startTimeMs = systemClock.elapsedRealtime(),
- createDialogLaunchOnClickListener(
- createDelegate(state.recordedTask),
- dialogTransitionAnimator,
- DialogCuj(
- Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP,
- tag = "Screen record",
+ onClickListenerLegacy =
+ createDialogLaunchOnClickListener(
+ createDelegate(state.recordedTask),
+ dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ ),
+ clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ createDialogLaunchOnClickCallback(
+ dialogDelegate = createDelegate(state.recordedTask),
+ dialogTransitionAnimator = dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ )
),
- logger,
- TAG,
- ),
)
}
}
@@ -154,6 +163,8 @@ constructor(
companion object {
@DrawableRes val ICON = R.drawable.ic_screenrecord
+ private val DIALOG_CUJ =
+ DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Screen record")
private val TAG = "ScreenRecordVM".pad()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
index 2af86a51cf70..6654d4a8f104 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
@@ -39,6 +39,7 @@ import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.ChipTransitionHelper
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
+import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickCallback
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
@@ -128,13 +129,25 @@ constructor(
colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
startTimeMs = systemClock.elapsedRealtime(),
- createDialogLaunchOnClickListener(
- createShareScreenToAppDialogDelegate(state),
- dialogTransitionAnimator,
- DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Share to app"),
- logger,
- TAG,
- ),
+ onClickListenerLegacy =
+ createDialogLaunchOnClickListener(
+ createShareScreenToAppDialogDelegate(state),
+ dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ ),
+ clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ onClick =
+ createDialogLaunchOnClickCallback(
+ createShareScreenToAppDialogDelegate(state),
+ dialogTransitionAnimator,
+ DIALOG_CUJ,
+ logger,
+ TAG,
+ )
+ ),
)
}
@@ -150,16 +163,24 @@ constructor(
)
),
colors = ColorsModel.Red,
- createDialogLaunchOnClickListener(
- createGenericShareToAppDialogDelegate(),
- dialogTransitionAnimator,
- DialogCuj(
- Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP,
- tag = "Share to app audio only",
+ onClickListenerLegacy =
+ createDialogLaunchOnClickListener(
+ createGenericShareToAppDialogDelegate(),
+ dialogTransitionAnimator,
+ DIALOG_CUJ_AUDIO_ONLY,
+ logger,
+ TAG,
+ ),
+ clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ createDialogLaunchOnClickCallback(
+ createGenericShareToAppDialogDelegate(),
+ dialogTransitionAnimator,
+ DIALOG_CUJ_AUDIO_ONLY,
+ logger,
+ TAG,
+ )
),
- logger,
- TAG,
- ),
)
}
@@ -180,6 +201,10 @@ constructor(
companion object {
@DrawableRes val SHARE_TO_APP_ICON = R.drawable.ic_present_to_all
+ private val DIALOG_CUJ =
+ DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Share to app")
+ private val DIALOG_CUJ_AUDIO_ONLY =
+ DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Share to app audio only")
private val TAG = "ShareToAppVM".pad()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
index b0fa9d842480..d46638fac46c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -56,7 +56,8 @@ object OngoingActivityChipBinder {
// Data
setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView, iconViewStore)
setChipMainContent(chipModel, chipTextView, chipTimeView, chipShortTimeDeltaView)
- viewBinding.rootView.setOnClickListener(chipModel.onClickListener)
+
+ viewBinding.rootView.setOnClickListener(chipModel.onClickListenerLegacy)
updateChipPadding(
chipModel,
chipBackgroundView,
@@ -424,7 +425,7 @@ object OngoingActivityChipBinder {
// Clickable chips need to be a minimum size for accessibility purposes, but let
// non-clickable chips be smaller.
val minimumWidth =
- if (chipModel.onClickListener != null) {
+ if (chipModel.onClickListenerLegacy != null) {
chipBackgroundView.context.resources.getDimensionPixelSize(
R.dimen.min_clickable_item_size
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
index 1be5842bceeb..6ce3228531d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
@@ -35,10 +35,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
+import com.android.compose.animation.Expandable
+import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth
@@ -47,23 +50,42 @@ import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
@Composable
fun OngoingActivityChip(model: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) {
+ when (val clickBehavior = model.clickBehavior) {
+ is OngoingActivityChipModel.ClickBehavior.ExpandAction -> {
+ // Wrap the chip in an Expandable so we can animate the expand transition.
+ ExpandableChip(
+ color = { Color.Transparent },
+ shape =
+ RoundedCornerShape(
+ dimensionResource(id = R.dimen.ongoing_activity_chip_corner_radius)
+ ),
+ modifier = modifier,
+ ) { expandable ->
+ ChipBody(model, onClick = { clickBehavior.onClick(expandable) })
+ }
+ }
+
+ is OngoingActivityChipModel.ClickBehavior.None -> {
+ ChipBody(model, modifier = modifier)
+ }
+ }
+}
+
+@Composable
+private fun ChipBody(
+ model: OngoingActivityChipModel.Shown,
+ modifier: Modifier = Modifier,
+ onClick: () -> Unit = {},
+) {
val context = LocalContext.current
- val isClickable = model.onClickListener != null
+ val isClickable = onClick != {}
val hasEmbeddedIcon = model.icon is OngoingActivityChipModel.ChipIcon.StatusBarView
// Use a Box with `fillMaxHeight` to create a larger click surface for the chip. The visible
// height of the chip is determined by the height of the background of the Row below.
Box(
contentAlignment = Alignment.Center,
- modifier =
- modifier
- .fillMaxHeight()
- .clickable(
- enabled = isClickable,
- onClick = {
- // TODO(b/372657935): Implement click actions.
- },
- ),
+ modifier = modifier.fillMaxHeight().clickable(enabled = isClickable, onClick = onClick),
) {
Row(
horizontalArrangement = Arrangement.Center,
@@ -206,3 +228,13 @@ private fun ChipContent(viewModel: OngoingActivityChipModel.Shown, modifier: Mod
}
}
}
+
+@Composable
+private fun ExpandableChip(
+ color: () -> Color,
+ shape: Shape,
+ modifier: Modifier = Modifier,
+ content: @Composable (Expandable) -> Unit,
+) {
+ Expandable(color = color(), shape = shape, modifier = modifier.clip(shape)) { content(it) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
index 956d99e46766..68c8f8cb4254 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.ui.model
import android.view.View
+import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
@@ -46,17 +47,20 @@ sealed class OngoingActivityChipModel {
open val colors: ColorsModel,
/**
* Listener method to invoke when this chip is clicked. If null, the chip won't be
- * clickable.
+ * clickable. Will be deprecated after [StatusBarChipsModernization] is enabled.
*/
- open val onClickListener: View.OnClickListener?,
+ open val onClickListenerLegacy: View.OnClickListener?,
+ /** Data class that determines how clicks on the chip should be handled. */
+ open val clickBehavior: ClickBehavior,
) : OngoingActivityChipModel() {
/** This chip shows only an icon and nothing else. */
data class IconOnly(
override val icon: ChipIcon,
override val colors: ColorsModel,
- override val onClickListener: View.OnClickListener?,
- ) : Shown(icon, colors, onClickListener) {
+ override val onClickListenerLegacy: View.OnClickListener?,
+ override val clickBehavior: ClickBehavior,
+ ) : Shown(icon, colors, onClickListenerLegacy, clickBehavior) {
override val logName = "Shown.Icon"
}
@@ -74,8 +78,9 @@ sealed class OngoingActivityChipModel {
* [android.widget.Chronometer.setBase].
*/
val startTimeMs: Long,
- override val onClickListener: View.OnClickListener?,
- ) : Shown(icon, colors, onClickListener) {
+ override val onClickListenerLegacy: View.OnClickListener?,
+ override val clickBehavior: ClickBehavior,
+ ) : Shown(icon, colors, onClickListenerLegacy, clickBehavior) {
override val logName = "Shown.Timer"
}
@@ -88,8 +93,9 @@ sealed class OngoingActivityChipModel {
override val colors: ColorsModel,
/** The time of the event that this chip represents. */
val time: Long,
- override val onClickListener: View.OnClickListener?,
- ) : Shown(icon, colors, onClickListener) {
+ override val onClickListenerLegacy: View.OnClickListener?,
+ override val clickBehavior: ClickBehavior,
+ ) : Shown(icon, colors, onClickListenerLegacy, clickBehavior) {
init {
StatusBarNotifChips.assertInNewMode()
}
@@ -105,7 +111,13 @@ sealed class OngoingActivityChipModel {
override val colors: ColorsModel,
/** The number of seconds until an event is started. */
val secondsUntilStarted: Long,
- ) : Shown(icon = null, colors, onClickListener = null) {
+ ) :
+ Shown(
+ icon = null,
+ colors,
+ onClickListenerLegacy = null,
+ clickBehavior = ClickBehavior.None,
+ ) {
override val logName = "Shown.Countdown"
}
@@ -115,8 +127,9 @@ sealed class OngoingActivityChipModel {
override val colors: ColorsModel,
// TODO(b/361346412): Enforce a max length requirement?
val text: String,
- override val onClickListener: View.OnClickListener? = null,
- ) : Shown(icon, colors, onClickListener) {
+ override val onClickListenerLegacy: View.OnClickListener? = null,
+ override val clickBehavior: ClickBehavior,
+ ) : Shown(icon, colors, onClickListenerLegacy, clickBehavior) {
override val logName = "Shown.Text"
}
}
@@ -149,4 +162,13 @@ sealed class OngoingActivityChipModel {
*/
data class SingleColorIcon(val impl: Icon) : ChipIcon
}
+
+ /** Defines the behavior of the chip when it is clicked. */
+ sealed interface ClickBehavior {
+ /** No specific click behavior. */
+ data object None : ClickBehavior
+
+ /** The chip expands into a dialog or activity on click. */
+ data class ExpandAction(val onClick: (Expandable) -> Unit) : ClickBehavior
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModel.kt
index 2fc366b7f078..a978c04d2a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModel.kt
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.chips.ui.viewmodel
import android.view.View
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.res.R
@@ -26,6 +27,7 @@ import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import kotlinx.coroutines.flow.StateFlow
/**
@@ -46,6 +48,7 @@ interface OngoingActivityChipViewModel {
tag: String,
): View.OnClickListener {
return View.OnClickListener { view ->
+ StatusBarChipsModernization.assertInLegacyMode()
logger.log(tag, LogLevel.INFO, {}, { "Chip clicked" })
val dialog = dialogDelegate.createDialog()
val launchableView =
@@ -55,5 +58,28 @@ interface OngoingActivityChipViewModel {
dialogTransitionAnimator.showFromView(dialog, launchableView, cuj)
}
}
+
+ /**
+ * Creates a chip click callback with an [Expandable] parameter that launches a dialog
+ * created by [dialogDelegate].
+ */
+ fun createDialogLaunchOnClickCallback(
+ dialogDelegate: SystemUIDialog.Delegate,
+ dialogTransitionAnimator: DialogTransitionAnimator,
+ cuj: DialogCuj,
+ @StatusBarChipsLog logger: LogBuffer,
+ tag: String,
+ ): (Expandable) -> Unit {
+ return { expandable ->
+ StatusBarChipsModernization.assertInNewMode()
+ logger.log(tag, LogLevel.INFO, {}, { "Chip clicked" })
+ val dialog = dialogDelegate.createDialog()
+
+ val controller = expandable.dialogTransitionController(cuj)
+ if (controller != null) {
+ dialogTransitionAnimator.show(dialog, controller)
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
index 2ab2b68bbb2e..9f8b45578903 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2024 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.
-*/
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.systemui.statusbar.phone.ongoingcall
import com.android.systemui.Flags
@@ -44,9 +44,16 @@ object StatusBarChipsModernization {
RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
/**
+ * Called to ensure code is only run when the flag is enabled. This will throw an exception if
+ * the flag is not enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, FLAG_NAME)
+
+ /**
* Called to ensure code is only run when the flag is disabled. This will throw an exception if
* the flag is enabled to ensure that the refactor author catches issues in testing.
*/
@JvmStatic
inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index 601b17c46c03..576e5d5d0cd2 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -51,6 +51,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
+import android.view.ContextThemeWrapper;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
@@ -498,10 +499,21 @@ class AppWarnings {
}
}
if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_PAGE_SIZE_MISMATCH)) {
+ Context context = getUiContextForActivity(ar);
+ // PageSizeMismatchDialog has link in message which should open in browser.
+ // Starting activity from non-activity context is not allowed and flag
+ // FLAG_ACTIVITY_NEW_TASK is needed to start activity.
+ context = new ContextThemeWrapper(context, context.getThemeResId()) {
+ @Override
+ public void startActivity(Intent intent) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ super.startActivity(intent);
+ }
+ };
pageSizeMismatchDialog =
new PageSizeMismatchDialog(
AppWarnings.this,
- getUiContextForActivity(ar),
+ context,
ar.info.applicationInfo,
userId,
warning);
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 5b0cc9ab6909..fa748d3a22a5 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -28,11 +28,9 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.NonNull;
import android.content.ClipData;
import android.content.Context;
-import android.hardware.display.DisplayTopology;
import android.hardware.input.InputManagerGlobal;
import android.os.Binder;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -51,7 +49,6 @@ import android.window.IGlobalDragListener;
import android.window.IUnhandledDragCallback;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.hidden_from_bootclasspath.com.android.window.flags.Flags;
import com.android.server.wm.WindowManagerInternal.IDragDropCallback;
import java.util.Objects;
@@ -59,7 +56,6 @@ import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
/**
* Managing drag and drop operations initiated by View#startDragAndDrop.
@@ -87,8 +83,6 @@ class DragDropController {
private WindowManagerService mService;
private final Handler mHandler;
- private final Consumer<DisplayTopology> mDisplayTopologyListener =
- this::handleDisplayTopologyChange;
// The global drag listener for handling cross-window drags
private IGlobalDragListener mGlobalDragListener;
@@ -114,17 +108,6 @@ class DragDropController {
DragDropController(WindowManagerService service, Looper looper) {
mService = service;
mHandler = new DragHandler(service, looper);
- if (Flags.enableConnectedDisplaysDnd()) {
- mService.mDisplayManager.registerTopologyListener(
- new HandlerExecutor(mService.mH), mDisplayTopologyListener);
- }
- }
-
- @VisibleForTesting
- void cleanupListeners() {
- if (Flags.enableConnectedDisplaysDnd()) {
- mService.mDisplayManager.unregisterTopologyListener(mDisplayTopologyListener);
- }
}
@VisibleForTesting
@@ -498,18 +481,6 @@ class DragDropController {
}
}
- private void handleDisplayTopologyChange(DisplayTopology unused) {
- synchronized (mService.mGlobalLock) {
- if (mDragState == null) {
- return;
- }
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "DisplayTopology changed, cancelling DragAndDrop");
- }
- cancelDragAndDrop(mDragState.mToken, true /* skipAnimation */);
- }
- }
-
/**
* Handles motion events.
* @param keepHandling Whether if the drag operation is continuing or this is the last motion
diff --git a/services/core/java/com/android/server/wm/PageSizeMismatchDialog.java b/services/core/java/com/android/server/wm/PageSizeMismatchDialog.java
index 29922f0f85c5..24235ef2d585 100644
--- a/services/core/java/com/android/server/wm/PageSizeMismatchDialog.java
+++ b/services/core/java/com/android/server/wm/PageSizeMismatchDialog.java
@@ -24,8 +24,10 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.text.Html;
+import android.text.method.LinkMovementMethod;
import android.view.Window;
import android.view.WindowManager;
+import android.widget.TextView;
import com.android.internal.R;
@@ -69,6 +71,14 @@ class PageSizeMismatchDialog extends AppWarnings.BaseDialog {
mDialog.create();
final Window window = mDialog.getWindow();
- window.setType(WindowManager.LayoutParams.TYPE_PHONE);
+ window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ // Make the links in dialog clickable
+ final TextView msgTxt = (TextView) mDialog.findViewById(android.R.id.message);
+ msgTxt.setMovementMethod(LinkMovementMethod.getInstance());
}
}
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 08ae6371559a..b328fc2d5868 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -101,7 +101,6 @@ android_test {
"testng",
"truth",
"wmtests-support",
- "display_flags_lib",
],
libs: [
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 6ced26920ff4..f509706d1692 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -32,12 +32,10 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_TOPOLOGY;
import static com.android.server.wm.DragDropController.MSG_UNHANDLED_DROP_LISTENER_TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -58,7 +56,6 @@ import android.content.Intent;
import android.content.pm.ShortcutServiceInternal;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.hardware.display.VirtualDisplay;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -69,7 +66,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.view.DragEvent;
import android.view.InputChannel;
import android.view.SurfaceControl;
@@ -83,14 +79,12 @@ import androidx.test.filters.SmallTest;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
-import com.android.server.wm.utils.VirtualDisplayTestRule;
import com.android.window.flags.Flags;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -111,8 +105,6 @@ import java.util.function.Consumer;
@Presubmit
@RunWith(WindowTestRunner.class)
public class DragDropControllerTests extends WindowTestsBase {
- @Rule
- public VirtualDisplayTestRule mVirtualDisplayTestRule = new VirtualDisplayTestRule();
private static final int TIMEOUT_MS = 3000;
private static final int TEST_UID = 12345;
private static final int TEST_PROFILE_UID = 12345 * UserHandle.PER_USER_RANGE;
@@ -228,17 +220,13 @@ public class DragDropControllerTests extends WindowTestsBase {
@After
public void tearDown() throws Exception {
- // Besides TestDragDropController, WMService also creates another DragDropController in
- // test, and since listeners are added on instantiation, it has to be cleared here as well.
- mTarget.cleanupListeners();
- mWm.mDragDropController.cleanupListeners();
+ final CountDownLatch latch;
if (!mTarget.dragDropActiveLocked()) {
return;
}
if (mToken != null) {
mTarget.cancelDragAndDrop(mToken, false);
}
- final CountDownLatch latch;
latch = new CountDownLatch(1);
mTarget.setOnClosedCallbackLocked(latch::countDown);
if (mTarget.mIsAccessibilityDrag) {
@@ -349,13 +337,12 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify the drop event is only sent for the global intercept window
assertTrue(nonLocalWindowDragEvents.isEmpty());
- assertNotEquals(ACTION_DROP, localWindowDragEvents.getLast().getAction());
- assertEquals(ACTION_DROP,
- globalInterceptWindowDragEvents.getLast().getAction());
+ assertTrue(last(localWindowDragEvents).getAction() != ACTION_DROP);
+ assertTrue(last(globalInterceptWindowDragEvents).getAction() == ACTION_DROP);
// Verify that item extras were not sent with the drop event
- assertNull(localWindowDragEvents.getLast().getClipData());
- assertFalse(globalInterceptWindowDragEvents.getLast().getClipData()
+ assertNull(last(localWindowDragEvents).getClipData());
+ assertFalse(last(globalInterceptWindowDragEvents).getClipData()
.willParcelWithActivityInfo());
});
}
@@ -397,7 +384,7 @@ public class DragDropControllerTests extends WindowTestsBase {
}
@Test
- public void testDragEventCoordinatesOverlappingWindows() {
+ public void testDragEventCoordinates() {
int dragStartX = mWindow.getBounds().centerX();
int dragStartY = mWindow.getBounds().centerY();
int startOffsetPx = 10;
@@ -442,7 +429,7 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify only window2 received the DROP event and coords are sent as-is.
assertEquals(1, dragEvents.size());
assertEquals(2, dragEvents2.size());
- final DragEvent dropEvent = dragEvents2.getLast();
+ final DragEvent dropEvent = last(dragEvents2);
assertEquals(ACTION_DROP, dropEvent.getAction());
assertEquals(dropCoordsPx, dropEvent.getX(), 0.0 /* delta */);
assertEquals(dropCoordsPx, dropEvent.getY(), 0.0 /* delta */);
@@ -450,10 +437,10 @@ public class DragDropControllerTests extends WindowTestsBase {
mTarget.reportDropResult(iwindow2, true);
// Verify both windows received ACTION_DRAG_ENDED event.
- assertEquals(ACTION_DRAG_ENDED, dragEvents.getLast().getAction());
- assertEquals(window2.getDisplayId(), dragEvents.getLast().getDisplayId());
- assertEquals(ACTION_DRAG_ENDED, dragEvents2.getLast().getAction());
- assertEquals(window2.getDisplayId(), dragEvents2.getLast().getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents).getAction());
+ assertEquals(window2.getDisplayId(), last(dragEvents).getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents2).getAction());
+ assertEquals(window2.getDisplayId(), last(dragEvents2).getDisplayId());
} finally {
mTarget.continueDragStateClose();
}
@@ -506,7 +493,7 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify only window2 received the DROP event and coords are sent as-is
assertEquals(1, dragEvents.size());
assertEquals(2, dragEvents2.size());
- final DragEvent dropEvent = dragEvents2.getLast();
+ final DragEvent dropEvent = last(dragEvents2);
assertEquals(ACTION_DROP, dropEvent.getAction());
assertEquals(dropCoordsPx, dropEvent.getX(), 0.0 /* delta */);
assertEquals(dropCoordsPx, dropEvent.getY(), 0.0 /* delta */);
@@ -514,12 +501,10 @@ public class DragDropControllerTests extends WindowTestsBase {
mTarget.reportDropResult(iwindow2, true);
// Verify both windows received ACTION_DRAG_ENDED event.
- assertEquals(ACTION_DRAG_ENDED, dragEvents.getLast().getAction());
- assertEquals(testDisplay.getDisplayId(),
- dragEvents.getLast().getDisplayId());
- assertEquals(ACTION_DRAG_ENDED, dragEvents2.getLast().getAction());
- assertEquals(testDisplay.getDisplayId(),
- dragEvents2.getLast().getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents).getAction());
+ assertEquals(testDisplay.getDisplayId(), last(dragEvents).getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents2).getAction());
+ assertEquals(testDisplay.getDisplayId(), last(dragEvents2).getDisplayId());
} finally {
mTarget.continueDragStateClose();
}
@@ -576,30 +561,8 @@ public class DragDropControllerTests extends WindowTestsBase {
});
}
- @Test
- @RequiresFlagsEnabled(FLAG_DISPLAY_TOPOLOGY)
- @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_DND)
- public void testDragCancelledOnTopologyChange() {
- VirtualDisplay virtualDisplay = createVirtualDisplay();
- // Necessary for now since DragState.sendDragStartedLocked() will recycle drag events
- // immediately after dispatching, which is a problem when using mockito arguments captor
- // because it returns and modifies the same drag event.
- TestIWindow iwindow = (TestIWindow) mWindow.mClient;
- final ArrayList<DragEvent> dragEvents = new ArrayList<>();
- iwindow.setDragEventJournal(dragEvents);
-
- startDrag(0, 0, View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ,
- ClipData.newPlainText("label", "text"), (surface) -> {
- final CountDownLatch latch = new CountDownLatch(1);
- mTarget.setOnClosedCallbackLocked(latch::countDown);
-
- // Release virtual display to trigger drag-and-drop cancellation.
- virtualDisplay.release();
- assertTrue(awaitInWmLock(() -> latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)));
-
- assertEquals(2, dragEvents.size());
- assertEquals(ACTION_DRAG_ENDED, dragEvents.getLast().getAction());
- });
+ private DragEvent last(ArrayList<DragEvent> list) {
+ return list.get(list.size() - 1);
}
@Test
@@ -979,12 +942,4 @@ public class DragDropControllerTests extends WindowTestsBase {
assertNotNull(mToken);
r.run();
}
-
- private VirtualDisplay createVirtualDisplay() {
- final int width = 800;
- final int height = 600;
- final String name = getClass().getSimpleName() + "_VirtualDisplay";
- return mVirtualDisplayTestRule.createDisplayManagerAttachedVirtualDisplay(name, width,
- height);
- }
}