Loading packages/SystemUI/aconfig/systemui.aconfig +6 −0 Original line number Diff line number Diff line Loading @@ -2031,3 +2031,9 @@ flag { } } flag { name: "ongoing_activity_chips_on_dream" namespace: "systemui" description: "Enables ongoing activity chips in dream status bar" bug: "418243972" } packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.privacy.PrivacyType; import com.android.systemui.res.R; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.ConnectedDisplaysStatusBarNotificationIconViewStore; import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.NextAlarmController; Loading Loading @@ -114,6 +115,10 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { UserTracker mUserTracker; @Mock PrivacyItemController mPrivacyItemController; @Mock AmbientStatusBarViewModel.Factory mAmbientStatusBarViewModelFactory; @Mock ConnectedDisplaysStatusBarNotificationIconViewStore.Factory mIconViewStoreFactory; LogBuffer mLogBuffer = FakeLogBuffer.Factory.Companion.create(); Loading Loading @@ -155,6 +160,8 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mKosmos.getWifiInteractor(), mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mAmbientStatusBarViewModelFactory, mIconViewStoreFactory, mLogBuffer); mController.onInit(); } Loading Loading @@ -331,6 +338,8 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mKosmos.getWifiInteractor(), mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mAmbientStatusBarViewModelFactory, mIconViewStoreFactory, mLogBuffer); controller.onViewAttached(); verify(mView, never()).showIcon( Loading packages/SystemUI/res/layout/ambient_status_bar_view.xml +9 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,15 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/dream_overlay_ongoing_activity_chips" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center_vertical" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <LinearLayout android:id="@+id/dream_overlay_extra_items" android:layout_width="wrap_content" Loading packages/SystemUI/src/com/android/systemui/ambient/statusbar/shared/flag/OngoingActivityChipsOnDream.kt 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.ambient.statusbar.shared.flag import com.android.systemui.Flags import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the ongoing activity chips on dream flag state. */ @Suppress("NOTHING_TO_INLINE") object OngoingActivityChipsOnDream { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_ONGOING_ACTIVITY_CHIPS_ON_DREAM /** A token used for dependency declaration */ val token: FlagToken get() = FlagToken(FLAG_NAME, isEnabled) /** Is the refactor enabled */ @JvmStatic inline val isEnabled get() = Flags.ongoingActivityChipsOnDream() /** * Called to ensure code is only run when the flag is enabled. This can be used to protect users * from the unintended behaviors caused by accidentally running new logic, while also crashing * on an eng build to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun isUnexpectedlyInLegacyMode() = RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) /** * Called to ensure code is only run when the flag is enabled. This will call Log.wtf if the * flag is not enabled to ensure that the refactor author catches issues in testing. * * NOTE: This can be useful for simple methods, but does not return the flag state, so it cannot * be used to implement a safe exit, and as such it does not support code stripping. If the * calling code will do work that is unsafe when the flag is off, it is recommended to write an * early return with `if (isUnexpectedlyInLegacyMode()) return`. */ @JvmStatic inline fun expectInNewMode() { RefactorFlagUtils.isUnexpectedlyInLegacyMode(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) } packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java +20 −0 Original line number Diff line number Diff line Loading @@ -30,7 +30,10 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.compose.ui.platform.ComposeView; import com.android.systemui.ambient.statusbar.shared.flag.OngoingActivityChipsOnDream; import com.android.systemui.ambient.statusbar.ui.binder.AmbientStatusBarViewBinder; import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamLogger; Loading @@ -46,6 +49,7 @@ import com.android.systemui.privacy.PrivacyType; import com.android.systemui.res.R; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.ConnectedDisplaysStatusBarNotificationIconViewStore; import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor; import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; Loading Loading @@ -90,6 +94,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus private final List<DreamOverlayStatusBarItemsProvider.StatusBarItem> mExtraStatusBarItems = new ArrayList<>(); private final CommunalSceneInteractor mCommunalSceneInteractor; private final AmbientStatusBarViewModel.Factory mAmbientStatusBarViewModelFactory; private final ConnectedDisplaysStatusBarNotificationIconViewStore.Factory mIconViewStoreFactory; private final DreamLogger mLogger; private boolean mIsAttached; Loading Loading @@ -157,6 +163,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus WifiInteractor wifiInteractor, PrivacyItemController privacyItemController, CommunalSceneInteractor communalSceneInteractor, AmbientStatusBarViewModel.Factory ambientStatusBarViewModelFactory, ConnectedDisplaysStatusBarNotificationIconViewStore.Factory iconViewStoreFactory, @DreamLog LogBuffer logBuffer) { super(view); mResources = resources; Loading @@ -174,6 +182,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus mWifiInteractor = wifiInteractor; mPrivacyItemController = privacyItemController; mCommunalSceneInteractor = communalSceneInteractor; mAmbientStatusBarViewModelFactory = ambientStatusBarViewModelFactory; mIconViewStoreFactory = iconViewStoreFactory; mLogger = new DreamLogger(logBuffer, TAG); } Loading @@ -199,6 +209,16 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus protected void onViewAttached() { mIsAttached = true; if (OngoingActivityChipsOnDream.isEnabled()) { final ComposeView ongoingActivityChipsView = mView.findViewById(R.id.dream_overlay_ongoing_activity_chips); AmbientStatusBarViewBinder.bindOngoingActivityChipsView( getContext(), ongoingActivityChipsView, mAmbientStatusBarViewModelFactory, mIconViewStoreFactory); } collectFlow( mView, mWifiInteractor.getWifiNetwork(), Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +6 −0 Original line number Diff line number Diff line Loading @@ -2031,3 +2031,9 @@ flag { } } flag { name: "ongoing_activity_chips_on_dream" namespace: "systemui" description: "Enables ongoing activity chips in dream status bar" bug: "418243972" }
packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.privacy.PrivacyType; import com.android.systemui.res.R; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.ConnectedDisplaysStatusBarNotificationIconViewStore; import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.NextAlarmController; Loading Loading @@ -114,6 +115,10 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { UserTracker mUserTracker; @Mock PrivacyItemController mPrivacyItemController; @Mock AmbientStatusBarViewModel.Factory mAmbientStatusBarViewModelFactory; @Mock ConnectedDisplaysStatusBarNotificationIconViewStore.Factory mIconViewStoreFactory; LogBuffer mLogBuffer = FakeLogBuffer.Factory.Companion.create(); Loading Loading @@ -155,6 +160,8 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mKosmos.getWifiInteractor(), mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mAmbientStatusBarViewModelFactory, mIconViewStoreFactory, mLogBuffer); mController.onInit(); } Loading Loading @@ -331,6 +338,8 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mKosmos.getWifiInteractor(), mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mAmbientStatusBarViewModelFactory, mIconViewStoreFactory, mLogBuffer); controller.onViewAttached(); verify(mView, never()).showIcon( Loading
packages/SystemUI/res/layout/ambient_status_bar_view.xml +9 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,15 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/dream_overlay_ongoing_activity_chips" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center_vertical" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <LinearLayout android:id="@+id/dream_overlay_extra_items" android:layout_width="wrap_content" Loading
packages/SystemUI/src/com/android/systemui/ambient/statusbar/shared/flag/OngoingActivityChipsOnDream.kt 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.ambient.statusbar.shared.flag import com.android.systemui.Flags import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the ongoing activity chips on dream flag state. */ @Suppress("NOTHING_TO_INLINE") object OngoingActivityChipsOnDream { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_ONGOING_ACTIVITY_CHIPS_ON_DREAM /** A token used for dependency declaration */ val token: FlagToken get() = FlagToken(FLAG_NAME, isEnabled) /** Is the refactor enabled */ @JvmStatic inline val isEnabled get() = Flags.ongoingActivityChipsOnDream() /** * Called to ensure code is only run when the flag is enabled. This can be used to protect users * from the unintended behaviors caused by accidentally running new logic, while also crashing * on an eng build to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun isUnexpectedlyInLegacyMode() = RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) /** * Called to ensure code is only run when the flag is enabled. This will call Log.wtf if the * flag is not enabled to ensure that the refactor author catches issues in testing. * * NOTE: This can be useful for simple methods, but does not return the flag state, so it cannot * be used to implement a safe exit, and as such it does not support code stripping. If the * calling code will do work that is unsafe when the flag is off, it is recommended to write an * early return with `if (isUnexpectedlyInLegacyMode()) return`. */ @JvmStatic inline fun expectInNewMode() { RefactorFlagUtils.isUnexpectedlyInLegacyMode(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) }
packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java +20 −0 Original line number Diff line number Diff line Loading @@ -30,7 +30,10 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.compose.ui.platform.ComposeView; import com.android.systemui.ambient.statusbar.shared.flag.OngoingActivityChipsOnDream; import com.android.systemui.ambient.statusbar.ui.binder.AmbientStatusBarViewBinder; import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamLogger; Loading @@ -46,6 +49,7 @@ import com.android.systemui.privacy.PrivacyType; import com.android.systemui.res.R; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.ConnectedDisplaysStatusBarNotificationIconViewStore; import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor; import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; Loading Loading @@ -90,6 +94,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus private final List<DreamOverlayStatusBarItemsProvider.StatusBarItem> mExtraStatusBarItems = new ArrayList<>(); private final CommunalSceneInteractor mCommunalSceneInteractor; private final AmbientStatusBarViewModel.Factory mAmbientStatusBarViewModelFactory; private final ConnectedDisplaysStatusBarNotificationIconViewStore.Factory mIconViewStoreFactory; private final DreamLogger mLogger; private boolean mIsAttached; Loading Loading @@ -157,6 +163,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus WifiInteractor wifiInteractor, PrivacyItemController privacyItemController, CommunalSceneInteractor communalSceneInteractor, AmbientStatusBarViewModel.Factory ambientStatusBarViewModelFactory, ConnectedDisplaysStatusBarNotificationIconViewStore.Factory iconViewStoreFactory, @DreamLog LogBuffer logBuffer) { super(view); mResources = resources; Loading @@ -174,6 +182,8 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus mWifiInteractor = wifiInteractor; mPrivacyItemController = privacyItemController; mCommunalSceneInteractor = communalSceneInteractor; mAmbientStatusBarViewModelFactory = ambientStatusBarViewModelFactory; mIconViewStoreFactory = iconViewStoreFactory; mLogger = new DreamLogger(logBuffer, TAG); } Loading @@ -199,6 +209,16 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus protected void onViewAttached() { mIsAttached = true; if (OngoingActivityChipsOnDream.isEnabled()) { final ComposeView ongoingActivityChipsView = mView.findViewById(R.id.dream_overlay_ongoing_activity_chips); AmbientStatusBarViewBinder.bindOngoingActivityChipsView( getContext(), ongoingActivityChipsView, mAmbientStatusBarViewModelFactory, mIconViewStoreFactory); } collectFlow( mView, mWifiInteractor.getWifiNetwork(), Loading