Merge "Change SystemUI implementation for prioritized HUNs."
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 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.
|
||||
-->
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:startColor="@android:color/black"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:angle="90" />
|
||||
</shape>
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 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.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/notification_headsup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/gradient_edge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_begin="@dimen/headsup_scrim_height"/>
|
||||
|
||||
<!-- Include a FocusParkingView at the beginning. The rotary controller "parks" the focus here
|
||||
when the user navigates to another window. This is also used to prevent wrap-around. -->
|
||||
<com.android.car.ui.FocusParkingView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/scrim"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/headsup_scrim_bottom"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/gradient_edge"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/headsup_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/headsup_notification_top_margin"
|
||||
app:layout_constraintEnd_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -70,13 +70,6 @@
|
||||
|
||||
<!-- Whether heads-up notifications should be shown when shade is open. -->
|
||||
<bool name="config_enableHeadsUpNotificationWhenNotificationShadeOpen">true</bool>
|
||||
<!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up
|
||||
notifications will be shown pushed to the top of their parent container. If true, they will
|
||||
be shown pushed to the bottom of their parent container. If true, then should override
|
||||
config_headsUpNotificationAnimationHelper to use a different AnimationHelper, such as
|
||||
com.android.car.notification.headsup.animationhelper.
|
||||
CarHeadsUpNotificationBottomAnimationHelper. -->
|
||||
<bool name="config_showHeadsUpNotificationOnBottom">false</bool>
|
||||
|
||||
<bool name="config_hideNavWhenKeyguardBouncerShown">true</bool>
|
||||
<bool name="config_enablePersistentDockedActivity">false</bool>
|
||||
|
||||
@@ -17,45 +17,41 @@
|
||||
package com.android.systemui.car.notification;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.car.notification.R;
|
||||
import com.android.car.notification.headsup.CarHeadsUpNotificationContainer;
|
||||
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||
import com.android.systemui.car.window.OverlayViewGlobalStateController;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* A controller for SysUI's HUN display.
|
||||
*
|
||||
* Used to attach HUNs views to window and determine whether to show HUN panel.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotificationContainer {
|
||||
public class CarHeadsUpNotificationSystemContainer extends CarHeadsUpNotificationContainer {
|
||||
private static final String WINDOW_TITLE = "HeadsUpNotification";
|
||||
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
|
||||
private final OverlayViewGlobalStateController mOverlayViewGlobalStateController;
|
||||
|
||||
private final ViewGroup mWindow;
|
||||
private final ViewGroup mHeadsUpContentFrame;
|
||||
|
||||
@Inject
|
||||
CarHeadsUpNotificationSystemContainer(Context context,
|
||||
@Main Resources resources,
|
||||
CarDeviceProvisionedController deviceProvisionedController,
|
||||
WindowManager windowManager,
|
||||
OverlayViewGlobalStateController overlayViewGlobalStateController) {
|
||||
super(context, windowManager);
|
||||
mCarDeviceProvisionedController = deviceProvisionedController;
|
||||
mOverlayViewGlobalStateController = overlayViewGlobalStateController;
|
||||
}
|
||||
|
||||
boolean showOnBottom = resources.getBoolean(R.bool.config_showHeadsUpNotificationOnBottom);
|
||||
|
||||
@Override
|
||||
protected WindowManager.LayoutParams getWindowManagerLayoutParams() {
|
||||
// Use TYPE_STATUS_BAR_SUB_PANEL window type since we need to find a window that is above
|
||||
// status bar but below navigation bar.
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
@@ -66,45 +62,15 @@ public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotifica
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
lp.gravity = showOnBottom ? Gravity.BOTTOM : Gravity.TOP;
|
||||
lp.setTitle("HeadsUpNotification");
|
||||
lp.gravity = getShowHunOnBottom() ? Gravity.BOTTOM : Gravity.TOP;
|
||||
lp.setTitle(WINDOW_TITLE);
|
||||
|
||||
int layoutId = showOnBottom
|
||||
? R.layout.headsup_container_bottom
|
||||
: R.layout.headsup_container;
|
||||
mWindow = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
|
||||
windowManager.addView(mWindow, lp);
|
||||
mWindow.setVisibility(View.INVISIBLE);
|
||||
mHeadsUpContentFrame = mWindow.findViewById(R.id.headsup_content);
|
||||
}
|
||||
|
||||
private void animateShow() {
|
||||
if (mCarDeviceProvisionedController.isCurrentUserFullySetup()
|
||||
&& mOverlayViewGlobalStateController.shouldShowHUN()) {
|
||||
mWindow.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void animateHide() {
|
||||
mWindow.setVisibility(View.INVISIBLE);
|
||||
return lp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayNotification(View notificationView) {
|
||||
mHeadsUpContentFrame.addView(notificationView);
|
||||
animateShow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotification(View notificationView) {
|
||||
mHeadsUpContentFrame.removeView(notificationView);
|
||||
if (mHeadsUpContentFrame.getChildCount() == 0) {
|
||||
animateHide();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return mWindow.getVisibility() == View.VISIBLE;
|
||||
public boolean shouldShowHunPanel() {
|
||||
return mCarDeviceProvisionedController.isCurrentUserFullySetup()
|
||||
&& mOverlayViewGlobalStateController.shouldShowHUN();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableResources;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.car.notification.CarNotificationTypeItem;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||
import com.android.systemui.car.CarSystemUiTest;
|
||||
@@ -64,37 +64,41 @@ public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase {
|
||||
when(mOverlayViewGlobalStateController.shouldShowHUN()).thenReturn(true);
|
||||
when(mCarDeviceProvisionedController.isCurrentUserFullySetup()).thenReturn(true);
|
||||
|
||||
TestableResources testableResources = mContext.getOrCreateTestableResources();
|
||||
mContext.ensureTestableResources();
|
||||
|
||||
mCarHeadsUpNotificationSystemContainer = new CarHeadsUpNotificationSystemContainer(mContext,
|
||||
testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager,
|
||||
mOverlayViewGlobalStateController);
|
||||
mCarDeviceProvisionedController, mWindowManager, mOverlayViewGlobalStateController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNotification_firstNotification_isVisible() {
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNotification_lastNotification_isInvisible() {
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
mCarHeadsUpNotificationSystemContainer.removeNotification(mNotificationView);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNotification_nonLastNotification_isVisible() {
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView2);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView2,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
mCarHeadsUpNotificationSystemContainer.removeNotification(mNotificationView);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNotification_userFullySetupTrue_isInvisible() {
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
|
||||
|
||||
}
|
||||
@@ -102,20 +106,23 @@ public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testDisplayNotification_userFullySetupFalse_isInvisible() {
|
||||
when(mCarDeviceProvisionedController.isCurrentUserFullySetup()).thenReturn(false);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNotification_overlayWindowStateShouldShowHUNFalse_isInvisible() {
|
||||
when(mOverlayViewGlobalStateController.shouldShowHUN()).thenReturn(false);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNotification_overlayWindowStateShouldShowHUNTrue_isVisible() {
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
|
||||
mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView,
|
||||
CarNotificationTypeItem.INBOX);
|
||||
assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user