diff options
| author | 2024-09-11 12:58:55 -0700 | |
|---|---|---|
| committer | 2024-09-11 15:32:19 -0700 | |
| commit | e73a0a381ff00a8fe1c2dca282280fc8f874f3ba (patch) | |
| tree | 41d5089f1751ee3b771eecbfda88d7bdc63b2f4c | |
| parent | 36a651cb94da67cd5f71528024b13c816772547f (diff) | |
Add location to dream overlay status bar.
This changelist adds a location icon to the dream overlay status bar
when location services are active.
Test: atest AmbientStatusBarViewControllerTest#testLocationIconShownWhenLocationActive
Test: atest AmbientStatusBarViewControllerTest#testLocationIconNotShownForOtherPrivacyItems
Test: atest AmbientStatusBarViewControllerTest#testLocationIconNotShownForNoItems
Fixes: 354688091
Flag: EXEMPT bugfix
Change-Id: I794a31ebce58a9d411de2b3a9e7687ed9174f24b
5 files changed, 97 insertions, 0 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java index 43db5a70849f..ab59051dcd4a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java @@ -50,6 +50,9 @@ import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider; import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.log.LogBuffer; import com.android.systemui.log.core.FakeLogBuffer; +import com.android.systemui.privacy.PrivacyItem; +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.pipeline.wifi.data.repository.FakeWifiRepository; @@ -66,8 +69,10 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.Executor; @@ -107,6 +112,8 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { DreamOverlayStateController mDreamOverlayStateController; @Mock UserTracker mUserTracker; + @Mock + PrivacyItemController mPrivacyItemController; LogBuffer mLogBuffer = FakeLogBuffer.Factory.Companion.create(); @@ -146,6 +153,7 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mDreamOverlayStateController, mUserTracker, mKosmos.getWifiInteractor(), + mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mLogBuffer); mController.onInit(); @@ -160,6 +168,7 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { verify(mDreamOverlayNotificationCountProvider).addCallback(any()); verify(mDreamOverlayStatusBarItemsProvider).addCallback(any()); verify(mDreamOverlayStateController).addCallback(any()); + verify(mPrivacyItemController).addCallback(any()); } @Test @@ -172,6 +181,52 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { } @Test + public void testLocationIconShownWhenLocationActive() { + mController.onViewAttached(); + final ArgumentCaptor<PrivacyItemController.Callback> callbackCaptor = + ArgumentCaptor.forClass(PrivacyItemController.Callback.class); + verify(mPrivacyItemController).addCallback(callbackCaptor.capture()); + + final PrivacyItem item = Mockito.mock(PrivacyItem.class); + when(item.getPrivacyType()).thenReturn(PrivacyType.TYPE_LOCATION); + callbackCaptor.getValue().onPrivacyItemsChanged(Arrays.asList(item)); + + verify(mView).showIcon( + eq(AmbientStatusBarView.STATUS_ICON_LOCATION_ACTIVE), eq(true), any()); + } + + @Test + public void testLocationIconNotShownForOtherPrivacyItems() { + mController.onViewAttached(); + final ArgumentCaptor<PrivacyItemController.Callback> callbackCaptor = + ArgumentCaptor.forClass(PrivacyItemController.Callback.class); + verify(mPrivacyItemController).addCallback(callbackCaptor.capture()); + + final PrivacyItem item = Mockito.mock(PrivacyItem.class); + when(item.getPrivacyType()).thenReturn(PrivacyType.TYPE_CAMERA); + callbackCaptor.getValue().onPrivacyItemsChanged(Arrays.asList(item)); + + verify(mView, never()).showIcon( + eq(AmbientStatusBarView.STATUS_ICON_LOCATION_ACTIVE), eq(true), any()); + } + + @Test + public void testLocationIconNotShownForNoItems() { + mController.onViewAttached(); + final ArgumentCaptor<PrivacyItemController.Callback> callbackCaptor = + ArgumentCaptor.forClass(PrivacyItemController.Callback.class); + verify(mPrivacyItemController).addCallback(callbackCaptor.capture()); + + verify(mView, never()).showIcon( + eq(AmbientStatusBarView.STATUS_ICON_LOCATION_ACTIVE), eq(true), any()); + + callbackCaptor.getValue().onPrivacyItemsChanged(Arrays.asList()); + + verify(mView, never()).showIcon( + eq(AmbientStatusBarView.STATUS_ICON_LOCATION_ACTIVE), eq(true), any()); + } + + @Test public void testWifiIconHiddenWhenWifiAvailable() { mController.onViewAttached(); mController.updateWifiUnavailableStatusIcon(true); @@ -274,6 +329,7 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase { mDreamOverlayStateController, mUserTracker, mKosmos.getWifiInteractor(), + mPrivacyItemController, mKosmos.getCommunalSceneInteractor(), mLogBuffer); controller.onViewAttached(); diff --git a/packages/SystemUI/res/layout/ambient_status_bar_view.xml b/packages/SystemUI/res/layout/ambient_status_bar_view.xml index 7d765ce7ac6f..825824aa958a 100644 --- a/packages/SystemUI/res/layout/ambient_status_bar_view.xml +++ b/packages/SystemUI/res/layout/ambient_status_bar_view.xml @@ -53,6 +53,15 @@ app:layout_constraintEnd_toEndOf="parent"> <com.android.systemui.statusbar.AlphaOptimizedImageView + android:id="@+id/dream_overlay_location_active" + android:layout_width="@dimen/dream_overlay_status_bar_icon_size" + android:layout_height="match_parent" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" + android:src="@drawable/ic_location" + android:visibility="gone" + android:contentDescription="@string/location_active_dream_overlay_content_description" /> + + <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/dream_overlay_alarm_set" android:layout_width="@dimen/dream_overlay_status_bar_icon_size" android:layout_height="match_parent" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d3d757bcdb46..3fe34b51d50b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3365,6 +3365,8 @@ <!-- Toast shown when a notification does not support dragging to split [CHAR LIMIT=NONE] --> <string name="drag_split_not_supported">This notification does not support dragging to split screen</string> + <!-- Content description for the location icon in the dream overlay status bar [CHAR LIMIT=NONE] --> + <string name="dream_overlay_location_active">Location active</string> <!-- Content description for the Wi-Fi off icon in the dream overlay status bar [CHAR LIMIT=NONE] --> <string name="dream_overlay_status_bar_wifi_off">Wi\u2011Fi unavailable</string> <!-- Content description for the priority mode icon in the dream overlay status bar [CHAR LIMIT=NONE] --> @@ -3557,6 +3559,9 @@ <!-- Content description for Wi-Fi not available icon on dream [CHAR LIMIT=NONE]--> <string name="wifi_unavailable_dream_overlay_content_description">Wi-Fi not available</string> + <!-- Content description for location in use icon on dream [CHAR LIMIT=NONE] --> + <string name="location_active_dream_overlay_content_description">Location active</string> + <!-- Content description for camera blocked icon on dream [CHAR LIMIT=NONE] --> <string name="camera_blocked_dream_overlay_content_description">Camera blocked</string> diff --git a/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java index aa9623127d17..d4e74d3bb906 100644 --- a/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java @@ -54,6 +54,7 @@ public class AmbientStatusBarView extends ConstraintLayout { STATUS_ICON_MIC_CAMERA_DISABLED, STATUS_ICON_PRIORITY_MODE_ON, STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE, + STATUS_ICON_LOCATION_ACTIVE, }) public @interface StatusIconType {} public static final int STATUS_ICON_NOTIFICATIONS = 0; @@ -64,6 +65,7 @@ public class AmbientStatusBarView extends ConstraintLayout { public static final int STATUS_ICON_MIC_CAMERA_DISABLED = 5; public static final int STATUS_ICON_PRIORITY_MODE_ON = 6; public static final int STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE = 7; + public static final int STATUS_ICON_LOCATION_ACTIVE = 8; private final Map<Integer, View> mStatusIcons = new HashMap<>(); private Context mContext; @@ -136,6 +138,8 @@ public class AmbientStatusBarView extends ConstraintLayout { addDoubleShadow(fetchStatusIconForResId(R.id.dream_overlay_priority_mode))); mStatusIcons.put(STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE, fetchStatusIconForResId(R.id.dream_overlay_assistant_attention_indicator)); + mStatusIcons.put(STATUS_ICON_LOCATION_ACTIVE, + fetchStatusIconForResId(R.id.dream_overlay_location_active)); mSystemStatusViewGroup = findViewById(R.id.dream_overlay_system_status); mExtraSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items); @@ -151,6 +155,7 @@ public class AmbientStatusBarView extends ConstraintLayout { case STATUS_ICON_MIC_CAMERA_DISABLED -> "mic_camera_disabled"; case STATUS_ICON_PRIORITY_MODE_ON -> "priority_mode_on"; case STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE -> "assistant_attention_active"; + case STATUS_ICON_LOCATION_ACTIVE -> "location_active"; default -> type + "(unknown)"; }; } diff --git a/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java index 04595a2a698e..75024c66d558 100644 --- a/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java @@ -27,6 +27,7 @@ import android.text.format.DateFormat; import android.util.PluralsMessageFormatter; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -39,6 +40,9 @@ import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider; import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem; import com.android.systemui.log.LogBuffer; import com.android.systemui.log.dagger.DreamLog; +import com.android.systemui.privacy.PrivacyItem; +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.CrossFadeHelper; @@ -79,6 +83,7 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus private final DreamOverlayStateController mDreamOverlayStateController; private final UserTracker mUserTracker; private final WifiInteractor mWifiInteractor; + private final PrivacyItemController mPrivacyItemController; private final StatusBarWindowStateController mStatusBarWindowStateController; private final DreamOverlayStatusBarItemsProvider mStatusBarItemsProvider; private final Executor mMainExecutor; @@ -131,6 +136,9 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus private final StatusBarWindowStateListener mStatusBarWindowStateListener = this::onSystemStatusBarStateChanged; + private final PrivacyItemController.Callback mPrivacyItemControllerCallback = + this::onPrivacyItemsChanged; + @Inject public AmbientStatusBarViewController( AmbientStatusBarView view, @@ -147,6 +155,7 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus DreamOverlayStateController dreamOverlayStateController, UserTracker userTracker, WifiInteractor wifiInteractor, + PrivacyItemController privacyItemController, CommunalSceneInteractor communalSceneInteractor, @DreamLog LogBuffer logBuffer) { super(view); @@ -163,6 +172,7 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus mDreamOverlayStateController = dreamOverlayStateController; mUserTracker = userTracker; mWifiInteractor = wifiInteractor; + mPrivacyItemController = privacyItemController; mCommunalSceneInteractor = communalSceneInteractor; mLogger = new DreamLogger(logBuffer, TAG); } @@ -174,10 +184,12 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus // Register to receive show/hide updates for the system status bar. Our custom status bar // needs to hide when the system status bar is showing to ovoid overlapping status bars. mStatusBarWindowStateController.addListener(mStatusBarWindowStateListener); + mPrivacyItemController.addCallback(mPrivacyItemControllerCallback); } @Override public void destroy() { + mPrivacyItemController.removeCallback(mPrivacyItemControllerCallback); mStatusBarWindowStateController.removeListener(mStatusBarWindowStateListener); super.destroy(); @@ -274,6 +286,11 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus R.string.wifi_unavailable_dream_overlay_content_description); } + void updateLocationStatusIcon(boolean enabled) { + showIcon(AmbientStatusBarView.STATUS_ICON_LOCATION_ACTIVE, enabled, + R.string.location_active_dream_overlay_content_description); + } + private void updateAlarmStatusIcon() { final AlarmManager.AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(mUserTracker.getUserId()); @@ -369,6 +386,11 @@ public class AmbientStatusBarViewController extends ViewController<AmbientStatus mMainExecutor.execute(this::updateVisibility); } + private void onPrivacyItemsChanged(@NonNull List<PrivacyItem> privacyItems) { + updateLocationStatusIcon(privacyItems.stream() + .anyMatch(item -> item.getPrivacyType() == PrivacyType.TYPE_LOCATION)); + } + private void onStatusBarItemsChanged(List<StatusBarItem> newItems) { mMainExecutor.execute(() -> { mExtraStatusBarItems.clear(); |