Merge "[Ongoing Call Chip] Don't show the chip on lockscreen." into sc-dev

This commit is contained in:
Caitlin Cassidy
2021-04-23 14:01:58 +00:00
committed by Android (Google) Code Review
6 changed files with 182 additions and 96 deletions

View File

@@ -73,6 +73,9 @@ public class StatusBarManager {
/** @hide */
public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH;
/** @hide */
public static final int DISABLE_ONGOING_CALL_CHIP = View.STATUS_BAR_DISABLE_ONGOING_CALL_CHIP;
/** @hide */
@Deprecated
public static final int DISABLE_NAVIGATION =
@@ -85,7 +88,7 @@ public class StatusBarManager {
public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
| DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
| DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK
| DISABLE_SEARCH;
| DISABLE_SEARCH | DISABLE_ONGOING_CALL_CHIP;
/** @hide */
@IntDef(flag = true, prefix = {"DISABLE_"}, value = {
@@ -99,7 +102,8 @@ public class StatusBarManager {
DISABLE_RECENT,
DISABLE_BACK,
DISABLE_CLOCK,
DISABLE_SEARCH
DISABLE_SEARCH,
DISABLE_ONGOING_CALL_CHIP
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisableFlags {}

View File

@@ -4001,6 +4001,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
/**
* @hide
*
* NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
* out of the public fields to keep the undefined bits out of the developer's way.
*
* Flag to disable the ongoing call chip.
*/
public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
/**
* @hide
*/
@@ -4227,7 +4237,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
name = "STATUS_BAR_DISABLE_RECENT"),
@ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
equals = STATUS_BAR_DISABLE_SEARCH,
name = "STATUS_BAR_DISABLE_SEARCH")
name = "STATUS_BAR_DISABLE_SEARCH"),
@ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
}, formatToHexString = true)
@SystemUiVisibility
int mSystemUiVisibility;
@@ -4256,6 +4269,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
STATUS_BAR_DISABLE_CLOCK,
STATUS_BAR_DISABLE_RECENT,
STATUS_BAR_DISABLE_SEARCH,
STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SystemUiVisibility {}

View File

@@ -23,7 +23,6 @@
android:background="@drawable/ongoing_call_chip_bg"
android:paddingStart="@dimen/ongoing_call_chip_side_padding"
android:paddingEnd="@dimen/ongoing_call_chip_side_padding"
android:visibility="gone"
>
<ImageView

View File

@@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone;
import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
import static android.app.StatusBarManager.DISABLE_CLOCK;
import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
import static android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP;
import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN;
@@ -92,6 +93,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final PrivacyDotViewController mDotViewController;
private NotificationIconAreaController mNotificationIconAreaController;
private List<String> mBlockedIcons = new ArrayList<>();
@@ -106,13 +108,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override
public void onOngoingCallStarted(boolean animate) {
disable(getContext().getDisplayId(), mDisabled1, mDisabled2, animate);
animateShow(mOngoingCallChip, animate);
}
@Override
public void onOngoingCallEnded(boolean animate) {
disable(getContext().getDisplayId(), mDisabled1, mDisabled2, animate);
animateHiddenState(mOngoingCallChip, View.GONE, animate);
}
};
@@ -120,11 +120,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
public CollapsedStatusBarFragment(
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
PrivacyDotViewController dotViewController
PrivacyDotViewController dotViewController,
NotificationIconAreaController notificationIconAreaController
) {
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mDotViewController = dotViewController;
mNotificationIconAreaController = notificationIconAreaController;
}
@Override
@@ -168,6 +170,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
showClock(false);
initEmergencyCryptkeeperText();
initOperatorName();
initNotificationIconArea();
mAnimationScheduler.addCallback(this);
}
@@ -204,11 +207,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
}
}
public void initNotificationIconArea(NotificationIconAreaController
notificationIconAreaController) {
/** Initializes views related to the notification icon area. */
public void initNotificationIconArea() {
ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
mNotificationIconAreaInner =
notificationIconAreaController.getNotificationInnerAreaView();
mNotificationIconAreaController.getNotificationInnerAreaView();
if (mNotificationIconAreaInner.getParent() != null) {
((ViewGroup) mNotificationIconAreaInner.getParent())
.removeView(mNotificationIconAreaInner);
@@ -216,15 +219,15 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
notificationIconArea.addView(mNotificationIconAreaInner);
ViewGroup statusBarCenteredIconArea = mStatusBar.findViewById(R.id.centered_icon_area);
mCenteredIconArea = notificationIconAreaController.getCenteredNotificationAreaView();
mCenteredIconArea = mNotificationIconAreaController.getCenteredNotificationAreaView();
if (mCenteredIconArea.getParent() != null) {
((ViewGroup) mCenteredIconArea.getParent())
.removeView(mCenteredIconArea);
}
statusBarCenteredIconArea.addView(mCenteredIconArea);
// Default to showing until we know otherwise.
showNotificationIconArea(false);
// #disable should have already been called, so use the disable values to set visibility.
updateNotificationIconAreaAndCallChip(mDisabled1, false);
}
@Override
@@ -249,13 +252,14 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
showOperatorName(animate);
}
}
if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
hideNotificationIconArea(animate);
} else {
showNotificationIconArea(animate);
}
// The ongoing call chip and notification icon visibilities are intertwined, so update both
// if either change.
if (((diff1 & DISABLE_ONGOING_CALL_CHIP) != 0)
|| ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0)) {
updateNotificationIconAreaAndCallChip(state1, animate);
}
// The clock may have already been hidden, but we might want to shift its
// visibility to GONE from INVISIBLE or vice versa
if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
@@ -273,10 +277,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
state |= DISABLE_CLOCK;
}
if (mOngoingCallController.hasOngoingCall()) {
state |= DISABLE_NOTIFICATION_ICONS;
}
if (!mKeyguardStateController.isLaunchTransitionFadingAway()
&& !mKeyguardStateController.isKeyguardFadingAway()
&& shouldHideNotificationIcons()
@@ -304,9 +304,40 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
}
if (mOngoingCallController.hasOngoingCall()) {
state &= ~DISABLE_ONGOING_CALL_CHIP;
} else {
state |= DISABLE_ONGOING_CALL_CHIP;
}
return state;
}
/**
* Updates the visibility of the notification icon area and ongoing call chip based on disabled1
* state.
*/
private void updateNotificationIconAreaAndCallChip(int state1, boolean animate) {
boolean disableNotifications = (state1 & DISABLE_NOTIFICATION_ICONS) != 0;
boolean hasOngoingCall = (state1 & DISABLE_ONGOING_CALL_CHIP) == 0;
// Hide notifications if the disable flag is set or we have an ongoing call.
if (disableNotifications || hasOngoingCall) {
hideNotificationIconArea(animate);
} else {
showNotificationIconArea(animate);
}
// Show the ongoing call chip only if there is an ongoing call *and* notification icons
// are allowed. (The ongoing call chip occupies the same area as the notification icons,
// so if the icons are disabled then the call chip should be, too.)
if (hasOngoingCall && !disableNotifications) {
showOngoingCallChip(animate);
} else {
hideOngoingCallChip(animate);
}
}
private boolean shouldHideNotificationIcons() {
if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
return true;
@@ -336,6 +367,16 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
animateShow(mClockView, animate);
}
/** Hides the ongoing call chip. */
public void hideOngoingCallChip(boolean animate) {
animateHiddenState(mOngoingCallChip, View.GONE, animate);
}
/** Displays the ongoing call chip. */
public void showOngoingCallChip(boolean animate) {
animateShow(mOngoingCallChip, animate);
}
/**
* If panel is expanded/expanding it usually means QS shade is opening, so
* don't set the clock GONE otherwise it'll mess up the animation.
@@ -457,7 +498,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override
public void onDozingChanged(boolean isDozing) {
disable(getContext().getDisplayId(), mDisabled1, mDisabled1, false /* animate */);
disable(getContext().getDisplayId(), mDisabled1, mDisabled2, false /* animate */);
}
@Override

View File

@@ -1139,7 +1139,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarView.setScrimController(mScrimController);
mStatusBarView.setExpansionChangedListeners(mExpansionChangedListeners);
statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
// CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of
// mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false.
// PhoneStatusBarView's new instance will set to be gone in
@@ -1182,7 +1181,8 @@ public class StatusBar extends SystemUI implements DemoMode,
new CollapsedStatusBarFragment(
mOngoingCallController,
mAnimationScheduler,
mDotViewController),
mDotViewController,
mNotificationIconAreaController),
CollapsedStatusBarFragment.TAG)
.commit();

View File

@@ -31,6 +31,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
@@ -40,24 +41,19 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.util.Objects;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
private NotificationIconAreaController mMockNotificiationAreaController;
private NotificationIconAreaController mMockNotificationAreaController;
private View mNotificationAreaInner;
private View mCenteredNotificationAreaView;
private StatusBarStateController mStatusBarStateController;
private OngoingCallController mOngoingCallController;
private SystemStatusAnimationScheduler mAnimationScheduler;
@@ -74,26 +70,16 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mStatusBarStateController = mDependency
.injectMockDependency(StatusBarStateController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
mMockNotificiationAreaController = mock(NotificationIconAreaController.class);
mNotificationAreaInner = mock(View.class);
mCenteredNotificationAreaView = mock(View.class);
when(statusBar.getPanelController()).thenReturn(
mock(NotificationPanelViewController.class));
when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mMockNotificiationAreaController.getNotificationInnerAreaView()).thenReturn(
mNotificationAreaInner);
when(mCenteredNotificationAreaView.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mMockNotificiationAreaController.getCenteredNotificationAreaView()).thenReturn(
mCenteredNotificationAreaView);
}
@Test
public void testDisableNone() throws Exception {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
@@ -106,9 +92,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
public void testDisableSystemInfo() throws Exception {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
@@ -124,12 +109,11 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
public void testDisableNotifications() throws Exception {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.INVISIBLE));
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
@@ -140,9 +124,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
public void testDisableClock() throws Exception {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_CLOCK, 0, false);
assertEquals(View.GONE, mFragment.getView().findViewById(R.id.clock).getVisibility());
@@ -152,16 +135,82 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
}
@Test
public void disable_noOngoingCall_chipHidden() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
assertEquals(View.GONE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
}
@Test
public void disable_hasOngoingCall_chipDisplayedAndNotificationIconsHidden() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
assertEquals(View.VISIBLE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
}
@Test
public void disable_hasOngoingCallButNotificationIconsDisabled_chipHidden() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY,
StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
assertEquals(View.GONE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
}
@Test
public void disable_ongoingCallEnded_chipHidden() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
// Ongoing call started
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
assertEquals(View.VISIBLE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
// Ongoing call ended
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
assertEquals(View.GONE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
}
@Test
public void testOnDozingChanged() throws Exception {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.INVISIBLE));
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
reset(mStatusBarStateController);
when(mStatusBarStateController.isDozing()).thenReturn(true);
@@ -171,56 +220,35 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
}
@Test
public void onOngoingCallStarted_notificationsHiddenAndOngoingCallChipDisplayed() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
ArgumentCaptor<OngoingCallListener> ongoingCallListenerCaptor = ArgumentCaptor.forClass(
OngoingCallListener.class);
Mockito.verify(mOngoingCallController).addCallback(ongoingCallListenerCaptor.capture());
OngoingCallListener listener = Objects.requireNonNull(ongoingCallListenerCaptor.getValue());
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
listener.onOngoingCallStarted(/* animate= */ false);
assertEquals(View.VISIBLE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
}
@Test
public void onOngoingCallEnded_notificationsDisplayedAndOngoingCallChipHidden() {
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
ArgumentCaptor<OngoingCallListener> ongoingCallListenerCaptor = ArgumentCaptor.forClass(
OngoingCallListener.class);
Mockito.verify(mOngoingCallController).addCallback(ongoingCallListenerCaptor.capture());
OngoingCallListener listener = Objects.requireNonNull(ongoingCallListenerCaptor.getValue());
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
listener.onOngoingCallEnded(/* animate= */ false);
assertEquals(View.GONE,
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
}
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
mOngoingCallController = mock(OngoingCallController.class);
mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
mDotViewController = mock(PrivacyDotViewController.class);
setUpNotificationIconAreaController();
return new CollapsedStatusBarFragment(
mOngoingCallController,
mAnimationScheduler,
mDotViewController);
mDotViewController,
mMockNotificationAreaController);
}
private void setUpNotificationIconAreaController() {
mMockNotificationAreaController = mock(NotificationIconAreaController.class);
mNotificationAreaInner = mock(View.class);
View centeredNotificationAreaView = mock(View.class);
when(mNotificationAreaInner.getLayoutParams()).thenReturn(
new FrameLayout.LayoutParams(100, 100));
when(centeredNotificationAreaView.getLayoutParams()).thenReturn(
new FrameLayout.LayoutParams(100, 100));
when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(centeredNotificationAreaView.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mMockNotificationAreaController.getCenteredNotificationAreaView()).thenReturn(
centeredNotificationAreaView);
when(mMockNotificationAreaController.getNotificationInnerAreaView()).thenReturn(
mNotificationAreaInner);
}
}