Merge "Add logic to show all status bar icons." into tm-dev

This commit is contained in:
William Leshner
2022-02-27 00:55:50 +00:00
committed by Android (Google) Code Review
5 changed files with 479 additions and 70 deletions

View File

@@ -29,7 +29,6 @@
android:layout_width="@dimen/dream_overlay_notification_indicator_size" android:layout_width="@dimen/dream_overlay_notification_indicator_size"
android:layout_height="@dimen/dream_overlay_notification_indicator_size" android:layout_height="@dimen/dream_overlay_notification_indicator_size"
android:visibility="gone" android:visibility="gone"
android:contentDescription="@string/dream_overlay_status_bar_notification_indicator"
app:dotColor="@android:color/white" app:dotColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -68,7 +67,7 @@
android:layout_width="@dimen/dream_overlay_status_bar_icon_size" android:layout_width="@dimen/dream_overlay_status_bar_icon_size"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin"
android:src="@drawable/ic_remove_circle" android:src="@drawable/ic_qs_dnd_on"
android:tint="@android:color/white" android:tint="@android:color/white"
android:visibility="gone" android:visibility="gone"
android:contentDescription="@string/dream_overlay_status_bar_priority_mode" /> android:contentDescription="@string/dream_overlay_status_bar_priority_mode" />

View File

@@ -2421,6 +2421,9 @@
<string name="dream_overlay_status_bar_assistant_guest_mode_enabled">Assistant guest mode enabled</string> <string name="dream_overlay_status_bar_assistant_guest_mode_enabled">Assistant guest mode enabled</string>
<!-- Content description for the camera and mic off icon in the dream overlay status bar [CHAR LIMIT=NONE] --> <!-- Content description for the camera and mic off icon in the dream overlay status bar [CHAR LIMIT=NONE] -->
<string name="dream_overlay_status_bar_camera_mic_off">Camera and mic are off</string> <string name="dream_overlay_status_bar_camera_mic_off">Camera and mic are off</string>
<!-- Content description for the camera and mic off icon in the dream overlay status bar [CHAR LIMIT=NONE] --> <!-- Content description for the notifications indicator icon in the dream overlay status bar [CHAR LIMIT=NONE] -->
<string name="dream_overlay_status_bar_notification_indicator">There are notifications</string> <string name="dream_overlay_status_bar_notification_indicator">{count, plural,
=1 {# notification}
other {# notifications}
}</string>
</resources> </resources>

View File

@@ -16,23 +16,44 @@
package com.android.systemui.dreams; package com.android.systemui.dreams;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.internal.util.Preconditions;
import com.android.systemui.R; import com.android.systemui.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/** /**
* {@link DreamOverlayStatusBarView} is the view responsible for displaying the status bar in a * {@link DreamOverlayStatusBarView} is the view responsible for displaying the status bar in a
* dream. The status bar displays conditional status icons such as "priority mode" and "no wifi". * dream. The status bar displays conditional status icons such as "priority mode" and "no wifi".
*/ */
public class DreamOverlayStatusBarView extends ConstraintLayout { public class DreamOverlayStatusBarView extends ConstraintLayout {
private ImageView mWifiStatusView; @Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "STATUS_ICON_" }, value = {
STATUS_ICON_NOTIFICATIONS,
STATUS_ICON_WIFI_UNAVAILABLE,
STATUS_ICON_ALARM_SET,
STATUS_ICON_MIC_CAMERA_DISABLED,
STATUS_ICON_PRIORITY_MODE_ON
})
public @interface StatusIconType {}
public static final int STATUS_ICON_NOTIFICATIONS = 0;
public static final int STATUS_ICON_WIFI_UNAVAILABLE = 1;
public static final int STATUS_ICON_ALARM_SET = 2;
public static final int STATUS_ICON_MIC_CAMERA_DISABLED = 3;
public static final int STATUS_ICON_PRIORITY_MODE_ON = 4;
private final Map<Integer, View> mStatusIcons = new HashMap<>();
public DreamOverlayStatusBarView(Context context) { public DreamOverlayStatusBarView(Context context) {
this(context, null); this(context, null);
@@ -55,16 +76,35 @@ public class DreamOverlayStatusBarView extends ConstraintLayout {
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
mWifiStatusView = Preconditions.checkNotNull(findViewById(R.id.dream_overlay_wifi_status), mStatusIcons.put(STATUS_ICON_WIFI_UNAVAILABLE,
"R.id.dream_overlay_wifi_status must not be null"); fetchStatusIconForResId(R.id.dream_overlay_wifi_status));
mStatusIcons.put(STATUS_ICON_ALARM_SET,
fetchStatusIconForResId(R.id.dream_overlay_alarm_set));
mStatusIcons.put(STATUS_ICON_MIC_CAMERA_DISABLED,
fetchStatusIconForResId(R.id.dream_overlay_camera_mic_off));
mStatusIcons.put(STATUS_ICON_NOTIFICATIONS,
fetchStatusIconForResId(R.id.dream_overlay_notification_indicator));
mStatusIcons.put(STATUS_ICON_PRIORITY_MODE_ON,
fetchStatusIconForResId(R.id.dream_overlay_priority_mode));
} }
/** void showIcon(@StatusIconType int iconType, boolean show) {
* Whether to show the wifi status icon. showIcon(iconType, show, null);
* @param show True if the wifi status icon should be shown. }
*/
void showWifiStatus(boolean show) { void showIcon(@StatusIconType int iconType, boolean show, @Nullable String contentDescription) {
// Only show the wifi status icon when wifi isn't available. View icon = mStatusIcons.get(iconType);
mWifiStatusView.setVisibility(show ? View.VISIBLE : View.GONE); if (icon == null) {
return;
}
if (show && contentDescription != null) {
icon.setContentDescription(contentDescription);
}
icon.setVisibility(show ? View.VISIBLE : View.GONE);
}
private View fetchStatusIconForResId(int resId) {
final View statusIcon = findViewById(resId);
return Objects.requireNonNull(statusIcon);
} }
} }

View File

@@ -16,19 +16,35 @@
package com.android.systemui.dreams; package com.android.systemui.dreams;
import android.annotation.IntDef; import android.app.AlarmManager;
import android.content.res.Resources;
import android.hardware.SensorPrivacyManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.text.format.DateFormat;
import android.util.PluralsMessageFormatter;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController;
import com.android.systemui.util.time.DateFormatUtil;
import java.lang.annotation.Retention; import java.util.Locale;
import java.lang.annotation.RetentionPolicy; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
@@ -37,19 +53,15 @@ import javax.inject.Inject;
*/ */
@DreamOverlayComponent.DreamOverlayScope @DreamOverlayComponent.DreamOverlayScope
public class DreamOverlayStatusBarViewController extends ViewController<DreamOverlayStatusBarView> { public class DreamOverlayStatusBarViewController extends ViewController<DreamOverlayStatusBarView> {
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "WIFI_STATUS_" }, value = {
WIFI_STATUS_UNKNOWN,
WIFI_STATUS_UNAVAILABLE,
WIFI_STATUS_AVAILABLE
})
private @interface WifiStatus {}
private static final int WIFI_STATUS_UNKNOWN = 0;
private static final int WIFI_STATUS_UNAVAILABLE = 1;
private static final int WIFI_STATUS_AVAILABLE = 2;
private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager;
private final TouchInsetManager.TouchInsetSession mTouchInsetSession; private final TouchInsetManager.TouchInsetSession mTouchInsetSession;
private final NextAlarmController mNextAlarmController;
private final AlarmManager mAlarmManager;
private final Resources mResources;
private final DateFormatUtil mDateFormatUtil;
private final IndividualSensorPrivacyController mSensorPrivacyController;
private final NotificationListener mNotificationListener;
private final ZenModeController mZenModeController;
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder() private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities() .clearCapabilities()
@@ -59,61 +71,183 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
@Override @Override
public void onCapabilitiesChanged( public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) { Network network, NetworkCapabilities networkCapabilities) {
onWifiAvailabilityChanged( updateWifiUnavailableStatusIcon();
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
} }
@Override @Override
public void onAvailable(Network network) { public void onAvailable(Network network) {
onWifiAvailabilityChanged(true); updateWifiUnavailableStatusIcon();
} }
@Override @Override
public void onLost(Network network) { public void onLost(Network network) {
onWifiAvailabilityChanged(false); updateWifiUnavailableStatusIcon();
} }
}; };
private @WifiStatus int mWifiStatus = WIFI_STATUS_UNKNOWN; private final IndividualSensorPrivacyController.Callback mSensorCallback =
(sensor, blocked) -> updateMicCameraBlockedStatusIcon();
private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
nextAlarm -> updateAlarmStatusIcon();
private final NotificationHandler mNotificationHandler = new NotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
updateNotificationsStatusIcon();
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
updateNotificationsStatusIcon();
}
@Override
public void onNotificationRemoved(
StatusBarNotification sbn,
RankingMap rankingMap,
int reason) {
updateNotificationsStatusIcon();
}
@Override
public void onNotificationRankingUpdate(RankingMap rankingMap) {
}
@Override
public void onNotificationsInitialized() {
updateNotificationsStatusIcon();
}
};
private final ZenModeController.Callback mZenModeCallback = new ZenModeController.Callback() {
@Override
public void onZenChanged(int zen) {
updatePriorityModeStatusIcon();
}
};
@Inject @Inject
public DreamOverlayStatusBarViewController( public DreamOverlayStatusBarViewController(
DreamOverlayStatusBarView view, DreamOverlayStatusBarView view,
@Main Resources resources,
ConnectivityManager connectivityManager, ConnectivityManager connectivityManager,
TouchInsetManager.TouchInsetSession touchInsetSession) { TouchInsetManager.TouchInsetSession touchInsetSession,
AlarmManager alarmManager,
NextAlarmController nextAlarmController,
DateFormatUtil dateFormatUtil,
IndividualSensorPrivacyController sensorPrivacyController,
NotificationListener notificationListener,
ZenModeController zenModeController) {
super(view); super(view);
mResources = resources;
mConnectivityManager = connectivityManager; mConnectivityManager = connectivityManager;
mTouchInsetSession = touchInsetSession; mTouchInsetSession = touchInsetSession;
mAlarmManager = alarmManager;
mNextAlarmController = nextAlarmController;
mDateFormatUtil = dateFormatUtil;
mSensorPrivacyController = sensorPrivacyController;
mNotificationListener = notificationListener;
mZenModeController = zenModeController;
// Handlers can be added to NotificationListener, but apparently they can't be removed. So
// add the handler here in the constructor rather than in onViewAttached to avoid confusion.
mNotificationListener.addNotificationHandler(mNotificationHandler);
} }
@Override @Override
protected void onViewAttached() { protected void onViewAttached() {
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback); updateNotificationsStatusIcon();
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
updateWifiUnavailableStatusIcon();
mNextAlarmController.addCallback(mNextAlarmCallback);
updateAlarmStatusIcon();
mSensorPrivacyController.addCallback(mSensorCallback);
updateMicCameraBlockedStatusIcon();
mZenModeController.addCallback(mZenModeCallback);
updatePriorityModeStatusIcon();
NetworkCapabilities capabilities =
mConnectivityManager.getNetworkCapabilities(
mConnectivityManager.getActiveNetwork());
onWifiAvailabilityChanged(
capabilities != null
&& capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
mTouchInsetSession.addViewToTracking(mView); mTouchInsetSession.addViewToTracking(mView);
} }
@Override @Override
protected void onViewDetached() { protected void onViewDetached() {
mZenModeController.removeCallback(mZenModeCallback);
mSensorPrivacyController.removeCallback(mSensorCallback);
mNextAlarmController.removeCallback(mNextAlarmCallback);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mTouchInsetSession.clear(); mTouchInsetSession.clear();
} }
/** private void updateWifiUnavailableStatusIcon() {
* Wifi availability has changed. Update the wifi status icon as appropriate. final NetworkCapabilities capabilities =
* @param available Whether wifi is available. mConnectivityManager.getNetworkCapabilities(
*/ mConnectivityManager.getActiveNetwork());
private void onWifiAvailabilityChanged(boolean available) { final boolean available = capabilities != null
final int newWifiStatus = available ? WIFI_STATUS_AVAILABLE : WIFI_STATUS_UNAVAILABLE; && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
if (mWifiStatus != newWifiStatus) { mView.showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available);
mWifiStatus = newWifiStatus; }
mView.showWifiStatus(mWifiStatus == WIFI_STATUS_UNAVAILABLE);
private void updateAlarmStatusIcon() {
final AlarmManager.AlarmClockInfo alarm =
mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
mView.showIcon(
DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET,
hasAlarm,
hasAlarm ? buildAlarmContentDescription(alarm) : null);
}
private String buildAlarmContentDescription(AlarmManager.AlarmClockInfo alarm) {
final String skeleton = mDateFormatUtil.is24HourFormat() ? "EHm" : "Ehma";
final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
final String dateString = DateFormat.format(pattern, alarm.getTriggerTime()).toString();
return mResources.getString(R.string.accessibility_quick_settings_alarm, dateString);
}
private void updateMicCameraBlockedStatusIcon() {
final boolean micBlocked = mSensorPrivacyController
.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE);
final boolean cameraBlocked = mSensorPrivacyController
.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA);
mView.showIcon(
DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
micBlocked && cameraBlocked);
}
private void updateNotificationsStatusIcon() {
if (mView == null) {
// It is possible for this method to be called before the view is attached, which makes
// null-checking necessary.
return;
} }
final StatusBarNotification[] notifications =
mNotificationListener.getActiveNotifications();
final int notificationCount = notifications != null ? notifications.length : 0;
mView.showIcon(
DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS,
notificationCount > 0,
notificationCount > 0
? buildNotificationsContentDescription(notificationCount)
: null);
}
private String buildNotificationsContentDescription(int notificationCount) {
return PluralsMessageFormatter.format(
mResources,
Map.of("count", notificationCount),
R.string.dream_overlay_status_bar_notification_indicator);
}
private void updatePriorityModeStatusIcon() {
mView.showIcon(
DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON,
mZenModeController.getZen() != Settings.Global.ZEN_MODE_OFF);
} }
} }

View File

@@ -17,19 +17,34 @@
package com.android.systemui.dreams; package com.android.systemui.dreams;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.content.res.Resources;
import android.hardware.SensorPrivacyManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.time.DateFormatUtil;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -41,6 +56,8 @@ import org.mockito.MockitoAnnotations;
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
private static final String NOTIFICATION_INDICATOR_FORMATTER_STRING =
"{count, plural, =1 {# notification} other {# notifications}}";
@Mock @Mock
DreamOverlayStatusBarView mView; DreamOverlayStatusBarView mView;
@@ -52,14 +69,55 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
Network mNetwork; Network mNetwork;
@Mock @Mock
TouchInsetManager.TouchInsetSession mTouchSession; TouchInsetManager.TouchInsetSession mTouchSession;
@Mock
Resources mResources;
@Mock
AlarmManager mAlarmManager;
@Mock
AlarmManager.AlarmClockInfo mAlarmClockInfo;
@Mock
NextAlarmController mNextAlarmController;
@Mock
DateFormatUtil mDateFormatUtil;
@Mock
IndividualSensorPrivacyController mSensorPrivacyController;
@Mock
StatusBarNotification mStatusBarNotification;
@Mock
NotificationListenerService.RankingMap mRankingMap;
@Mock
NotificationListener mNotificationListener;
@Mock
ZenModeController mZenModeController;
DreamOverlayStatusBarViewController mController; DreamOverlayStatusBarViewController mController;
@Before @Before
public void setup() { public void setup() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mController = new DreamOverlayStatusBarViewController(mView, mConnectivityManager,
mTouchSession); when(mResources.getString(R.string.dream_overlay_status_bar_notification_indicator))
.thenReturn(NOTIFICATION_INDICATOR_FORMATTER_STRING);
mController = new DreamOverlayStatusBarViewController(
mView,
mResources,
mConnectivityManager,
mTouchSession,
mAlarmManager,
mNextAlarmController,
mDateFormatUtil,
mSensorPrivacyController,
mNotificationListener,
mZenModeController);
}
@Test
public void testOnViewAttachedAddsCallbacks() {
mController.onViewAttached();
verify(mNextAlarmController).addCallback(any());
verify(mSensorPrivacyController).addCallback(any());
verify(mZenModeController).addCallback(any());
} }
@Test @Test
@@ -71,28 +129,97 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
} }
@Test @Test
public void testOnViewAttachedShowsWifiStatusWhenWifiUnavailable() { public void testOnViewAttachedShowsWifiIconWhenWifiUnavailable() {
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(false); .thenReturn(false);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached(); mController.onViewAttached();
verify(mView).showWifiStatus(true); verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true);
} }
@Test @Test
public void testOnViewAttachedHidesWifiStatusWhenWifiAvailable() { public void testOnViewAttachedHidesWifiIconWhenWifiAvailable() {
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true); .thenReturn(true);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached(); mController.onViewAttached();
verify(mView).showWifiStatus(false); verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
} }
@Test @Test
public void testOnViewAttachedShowsWifiStatusWhenNetworkCapabilitiesUnavailable() { public void testOnViewAttachedShowsWifiIconWhenNetworkCapabilitiesUnavailable() {
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(null); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(null);
mController.onViewAttached(); mController.onViewAttached();
verify(mView).showWifiStatus(true); }
@Test
public void testOnViewAttachedShowsAlarmIconWhenAlarmExists() {
when(mAlarmClockInfo.getTriggerTime()).thenReturn(1L);
when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(mAlarmClockInfo);
mController.onViewAttached();
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET), eq(true), any());
}
@Test
public void testOnViewAttachedHidesAlarmIconWhenNoAlarmExists() {
when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(null);
mController.onViewAttached();
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET), eq(false), isNull());
}
@Test
public void testOnViewAttachedShowsMicCameraIconWhenDisabled() {
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE))
.thenReturn(true);
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(true);
mController.onViewAttached();
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true);
}
@Test
public void testOnViewAttachedHidesMicCameraIconWhenEnabled() {
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE))
.thenReturn(false);
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(false);
mController.onViewAttached();
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false);
}
@Test
public void testOnViewAttachedShowsNotificationsIconWhenNotificationsExist() {
StatusBarNotification[] notifications = { mStatusBarNotification };
when(mNotificationListener.getActiveNotifications()).thenReturn(notifications);
mController.onViewAttached();
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
}
@Test
public void testOnViewAttachedHidesNotificationsIconWhenNoNotificationsExist() {
when(mNotificationListener.getActiveNotifications()).thenReturn(null);
mController.onViewAttached();
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), isNull());
}
@Test
public void testOnViewAttachedShowsPriorityModeIconWhenEnabled() {
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
mController.onViewAttached();
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true);
}
@Test
public void testOnViewAttachedHidesPriorityModeIconWhenDisabled() {
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_OFF);
mController.onViewAttached();
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false);
} }
@Test @Test
@@ -103,10 +230,19 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
} }
@Test @Test
public void testWifiStatusHiddenWhenWifiBecomesAvailable() { public void testOnViewDetachedRemovesCallbacks() {
// Make sure wifi starts out unavailable when onViewAttached is called. mController.onViewDetached();
verify(mNextAlarmController).removeCallback(any());
verify(mSensorPrivacyController).removeCallback(any());
verify(mZenModeController).removeCallback(any());
}
@Test
public void testWifiIconHiddenWhenWifiBecomesAvailable() {
// Make sure wifi starts out unavailable when onViewAttached is called, and then returns
// true on the second query.
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(false); .thenReturn(false).thenReturn(true);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached(); mController.onViewAttached();
@@ -114,14 +250,15 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture()); verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
callbackCapture.getValue().onAvailable(mNetwork); callbackCapture.getValue().onAvailable(mNetwork);
verify(mView).showWifiStatus(false); verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
} }
@Test @Test
public void testWifiStatusShownWhenWifiBecomesUnavailable() { public void testWifiIconShownWhenWifiBecomesUnavailable() {
// Make sure wifi starts out available when onViewAttached is called. // Make sure wifi starts out available when onViewAttached is called, then returns false
// on the second query.
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true); .thenReturn(true).thenReturn(false);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached(); mController.onViewAttached();
@@ -129,11 +266,11 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture()); verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
callbackCapture.getValue().onLost(mNetwork); callbackCapture.getValue().onLost(mNetwork);
verify(mView).showWifiStatus(true); verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true);
} }
@Test @Test
public void testWifiStatusHiddenWhenCapabilitiesChange() { public void testWifiIconHiddenWhenCapabilitiesChange() {
// Make sure wifi starts out unavailable when onViewAttached is called. // Make sure wifi starts out unavailable when onViewAttached is called.
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(false); .thenReturn(false);
@@ -146,6 +283,102 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true); .thenReturn(true);
callbackCapture.getValue().onCapabilitiesChanged(mNetwork, mNetworkCapabilities); callbackCapture.getValue().onCapabilitiesChanged(mNetwork, mNetworkCapabilities);
verify(mView).showWifiStatus(false); verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
}
@Test
public void testNotificationsIconShownWhenNotificationAdded() {
mController.onViewAttached();
StatusBarNotification[] notifications = { mStatusBarNotification };
when(mNotificationListener.getActiveNotifications()).thenReturn(notifications);
final ArgumentCaptor<NotificationListener.NotificationHandler> callbackCapture =
ArgumentCaptor.forClass(NotificationListener.NotificationHandler.class);
verify(mNotificationListener).addNotificationHandler(callbackCapture.capture());
callbackCapture.getValue().onNotificationPosted(mStatusBarNotification, mRankingMap);
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
}
@Test
public void testNotificationsIconHiddenWhenLastNotificationRemoved() {
StatusBarNotification[] notifications = { mStatusBarNotification };
when(mNotificationListener.getActiveNotifications()).thenReturn(notifications)
.thenReturn(null);
mController.onViewAttached();
final ArgumentCaptor<NotificationListener.NotificationHandler> callbackCapture =
ArgumentCaptor.forClass(NotificationListener.NotificationHandler.class);
verify(mNotificationListener).addNotificationHandler(callbackCapture.capture());
callbackCapture.getValue().onNotificationPosted(mStatusBarNotification, mRankingMap);
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), any());
}
@Test
public void testMicCameraIconShownWhenSensorsBlocked() {
mController.onViewAttached();
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE))
.thenReturn(true);
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(true);
final ArgumentCaptor<IndividualSensorPrivacyController.Callback> callbackCapture =
ArgumentCaptor.forClass(IndividualSensorPrivacyController.Callback.class);
verify(mSensorPrivacyController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onSensorBlockedChanged(
SensorPrivacyManager.Sensors.MICROPHONE, true);
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true);
}
@Test
public void testMicCameraIconHiddenWhenSensorsNotBlocked() {
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE))
.thenReturn(true).thenReturn(false);
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(true).thenReturn(false);
mController.onViewAttached();
final ArgumentCaptor<IndividualSensorPrivacyController.Callback> callbackCapture =
ArgumentCaptor.forClass(IndividualSensorPrivacyController.Callback.class);
verify(mSensorPrivacyController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onSensorBlockedChanged(
SensorPrivacyManager.Sensors.MICROPHONE, false);
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false);
}
@Test
public void testPriorityModeIconShownWhenZenModeEnabled() {
mController.onViewAttached();
when(mZenModeController.getZen()).thenReturn(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS);
final ArgumentCaptor<ZenModeController.Callback> callbackCapture =
ArgumentCaptor.forClass(ZenModeController.Callback.class);
verify(mZenModeController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS);
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true);
}
@Test
public void testPriorityModeIconHiddenWhenZenModeDisabled() {
when(mZenModeController.getZen()).thenReturn(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS)
.thenReturn(Settings.Global.ZEN_MODE_OFF);
mController.onViewAttached();
final ArgumentCaptor<ZenModeController.Callback> callbackCapture =
ArgumentCaptor.forClass(ZenModeController.Callback.class);
verify(mZenModeController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_OFF);
verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false);
} }
} }