Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e73a0a38 authored by Bryce Lee's avatar Bryce Lee
Browse files

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
parent 36a651cb
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -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
@@ -171,6 +180,52 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase {
                AmbientStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
    }

    @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();
@@ -274,6 +329,7 @@ public class AmbientStatusBarViewControllerTest extends SysuiTestCase {
                mDreamOverlayStateController,
                mUserTracker,
                mKosmos.getWifiInteractor(),
                mPrivacyItemController,
                mKosmos.getCommunalSceneInteractor(),
                mLogBuffer);
        controller.onViewAttached();
+9 −0
Original line number Diff line number Diff line
@@ -52,6 +52,15 @@
        android:visibility="gone"
        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"
+5 −0
Original line number Diff line number Diff line
@@ -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>

+5 −0
Original line number Diff line number Diff line
@@ -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)";
        };
    }
+22 −0
Original line number Diff line number Diff line
@@ -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();