diff options
8 files changed, 78 insertions, 27 deletions
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java index a16f5cd5d930..da9a92a1f6b4 100644 --- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java +++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java @@ -20,9 +20,11 @@ import android.app.PendingIntent; import android.app.smartspace.SmartspaceAction; import android.app.smartspace.SmartspaceTarget; import android.app.smartspace.SmartspaceTargetEvent; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Parcelable; +import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -39,6 +41,7 @@ import java.util.List; public interface BcSmartspaceDataPlugin extends Plugin { String ACTION = "com.android.systemui.action.PLUGIN_BC_SMARTSPACE_DATA"; int VERSION = 1; + String TAG = "BcSmartspaceDataPlugin"; /** Register a listener to get Smartspace data. */ void registerListener(SmartspaceTargetListener listener); @@ -124,10 +127,14 @@ public interface BcSmartspaceDataPlugin extends Plugin { /** Interface for launching Intents, which can differ on the lockscreen */ interface IntentStarter { default void startFromAction(SmartspaceAction action, View v, boolean showOnLockscreen) { - if (action.getIntent() != null) { - startIntent(v, action.getIntent(), showOnLockscreen); - } else if (action.getPendingIntent() != null) { - startPendingIntent(action.getPendingIntent(), showOnLockscreen); + try { + if (action.getIntent() != null) { + startIntent(v, action.getIntent(), showOnLockscreen); + } else if (action.getPendingIntent() != null) { + startPendingIntent(action.getPendingIntent(), showOnLockscreen); + } + } catch (ActivityNotFoundException e) { + Log.w(TAG, "Could not launch intent for action: " + action, e); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index e35b55841f2f..1496f170dffe 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -636,7 +636,9 @@ public abstract class AuthBiometricView extends LinearLayout { mIndicatorView.setText(message); mIndicatorView.setTextColor(mTextColorError); mIndicatorView.setVisibility(View.VISIBLE); - mIndicatorView.setSelected(true); + // select to enable marquee unless a screen reader is enabled + mIndicatorView.setSelected(!mAccessibilityManager.isEnabled() + || !mAccessibilityManager.isTouchExplorationEnabled()); mHandler.postDelayed(resetMessageRunnable, mInjector.getDelayAfterError()); Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java index 07aec6994bd0..73e3aecd8b63 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java @@ -75,7 +75,7 @@ abstract class UdfpsAnimationViewController<T extends UdfpsAnimationView> @Override protected void onViewDetached() { mPanelExpansionStateManager.removeExpansionListener(mPanelExpansionListener); - mDialogManager.registerListener(mDialogListener); + mDialogManager.unregisterListener(mDialogListener); mDumpManger.unregisterDumpable(getDumpTag()); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index fb601e310702..c8cd43287c99 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.annotation.IntDef import android.content.Context +import android.content.res.Configuration import android.graphics.Rect import android.util.MathUtils import android.view.View @@ -41,6 +42,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.Utils import com.android.systemui.util.animation.UniqueObjectHostView import javax.inject.Inject @@ -186,6 +188,8 @@ class MediaHierarchyManager @Inject constructor( @MediaLocation private var currentAttachmentLocation = -1 + private var inSplitShade = false + /** * Is there any active media in the carousel? */ @@ -390,8 +394,9 @@ class MediaHierarchyManager @Inject constructor( init { updateConfiguration() configurationController.addCallback(object : ConfigurationController.ConfigurationListener { - override fun onDensityOrFontScaleChanged() { + override fun onConfigChanged(newConfig: Configuration?) { updateConfiguration() + updateDesiredLocation(forceNoAnimation = true, forceStateUpdate = true) } }) statusBarStateController.addCallback(object : StatusBarStateController.StateListener { @@ -467,6 +472,7 @@ class MediaHierarchyManager @Inject constructor( private fun updateConfiguration() { distanceForFullShadeTransition = context.resources.getDimensionPixelSize( R.dimen.lockscreen_shade_media_transition_distance) + inSplitShade = Utils.shouldUseSplitNotificationShade(context.resources) } /** @@ -803,7 +809,7 @@ class MediaHierarchyManager @Inject constructor( private fun getQSTransformationProgress(): Float { val currentHost = getHost(desiredLocation) val previousHost = getHost(previousLocation) - if (hasActiveMedia && currentHost?.location == LOCATION_QS) { + if (hasActiveMedia && (currentHost?.location == LOCATION_QS && !inSplitShade)) { if (previousHost?.location == LOCATION_QQS) { if (previousHost.visible || statusbarState != StatusBarState.KEYGUARD) { return qsExpansion @@ -934,7 +940,7 @@ class MediaHierarchyManager @Inject constructor( statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER)) val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications() val location = when { - qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS + (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS qsExpansion > 0.4f && onLockscreen -> LOCATION_QS !hasActiveMedia -> LOCATION_QS onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt index 4e5bc8e7d099..6c4051ee18f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt @@ -240,6 +240,10 @@ class LockscreenSmartspaceController @Inject constructor( configurationController.addCallback(configChangeListener) statusBarStateController.addCallback(statusBarStateListener) + plugin.registerSmartspaceEventNotifier { + e -> session?.notifySmartspaceEvent(e) + } + reloadSmartspace() } @@ -265,6 +269,7 @@ class LockscreenSmartspaceController @Inject constructor( statusBarStateController.removeCallback(statusBarStateListener) session = null + plugin?.registerSmartspaceEventNotifier(null) plugin?.onTargetsAvailable(emptyList()) Log.d(TAG, "Ending smartspace session for lockscreen") } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 79231796577b..73a48c3b5cb0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -411,7 +411,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private NotificationShelf mShelf; private int mMaxDisplayedNotifications = -1; private float mKeyguardBottomPadding = -1; - private int mStatusBarHeight; + @VisibleForTesting int mStatusBarHeight; private int mMinInteractionHeight; private final Rect mClipRect = new Rect(); private boolean mIsClipped; @@ -4851,8 +4851,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.COORDINATOR) public int getMinExpansionHeight() { + // shelf height is defined in dp but status bar height can be defined in px, that makes + // relation between them variable - sometimes one might be bigger than the other when + // changing density. That’s why we need to ensure we’re not subtracting negative value below return mShelf.getIntrinsicHeight() - - (mShelf.getIntrinsicHeight() - mStatusBarHeight + mWaterfallTopInset) / 2 + - Math.max(0, + (mShelf.getIntrinsicHeight() - mStatusBarHeight + mWaterfallTopInset) / 2) + mWaterfallTopInset; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt index ff91978c54bb..7869b594c62b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt @@ -213,6 +213,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { // THEN the session is created verify(smartspaceManager).createSmartspaceSession(any()) + // THEN an event notifier is registered + verify(plugin).registerSmartspaceEventNotifier(any()) } @Test @@ -240,7 +242,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { } @Test - fun testEmptyListIsEmittedAfterDisconnect() { + fun testEmptyListIsEmittedAndNotifierRemovedAfterDisconnect() { // GIVEN a registered listener on an active session connectSession() clearInvocations(plugin) @@ -249,8 +251,9 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { controller.stateChangeListener.onViewDetachedFromWindow(smartspaceView as View) controller.disconnect() - // THEN the listener receives an empty list of targets + // THEN the listener receives an empty list of targets and unregisters the notifier verify(plugin).onTargetsAvailable(emptyList()) + verify(plugin).registerSmartspaceEventNotifier(null) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 185d9cd8733e..326369b8e815 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -22,6 +22,7 @@ import static android.view.View.GONE; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; +import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static junit.framework.Assert.assertEquals; @@ -103,6 +104,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Mock private NotificationShelf mNotificationShelf; @Before @UiThreadTest @@ -124,13 +126,13 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectTestDependency(GroupMembershipManager.class, mGroupMembershipManger); mDependency.injectTestDependency(GroupExpansionManager.class, mGroupExpansionManager); mDependency.injectTestDependency(AmbientState.class, mAmbientState); + mDependency.injectTestDependency(NotificationShelf.class, mNotificationShelf); mDependency.injectTestDependency( UnlockedScreenOffAnimationController.class, mUnlockedScreenOffAnimationController); NotificationShelfController notificationShelfController = mock(NotificationShelfController.class); - NotificationShelf notificationShelf = mock(NotificationShelf.class); - when(notificationShelfController.getView()).thenReturn(notificationShelf); + when(notificationShelfController.getView()).thenReturn(mNotificationShelf); when(mNotificationSectionsManager.createSectionsForBuckets()).thenReturn( new NotificationSection[]{ mNotificationSection @@ -160,7 +162,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { anyBoolean()); doNothing().when(mGroupExpansionManager).collapseGroups(); doNothing().when(mExpandHelper).cancelImmediately(); - doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean()); + doNothing().when(mNotificationShelf).setAnimationsEnabled(anyBoolean()); } @Test @@ -203,21 +205,43 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test @UiThreadTest - public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() { - final float[] expectedHeight = {0f}; - final float[] expectedAppear = {0f}; + public void testSetExpandedHeight_listenerReceivedCallbacks() { + final float expectedHeight = 0f; mStackScroller.addOnExpandedHeightChangedListener((height, appear) -> { - Assert.assertEquals(expectedHeight[0], height, 0); - Assert.assertEquals(expectedAppear[0], appear, .1); + Assert.assertEquals(expectedHeight, height, 0); }); - expectedHeight[0] = 1f; - expectedAppear[0] = 1f; - mStackScroller.setExpandedHeight(expectedHeight[0]); + mStackScroller.setExpandedHeight(expectedHeight); + } - expectedHeight[0] = 100f; - expectedAppear[0] = 0f; - mStackScroller.setExpandedHeight(expectedHeight[0]); + @Test + public void testAppearFractionCalculation() { + // appear start position + when(mNotificationShelf.getIntrinsicHeight()).thenReturn(100); + // because it's the same as shelf height, appear start position equals shelf height + mStackScroller.mStatusBarHeight = 100; + // appear end position + when(mEmptyShadeView.getHeight()).thenReturn(200); + + assertEquals(0f, mStackScroller.calculateAppearFraction(100)); + assertEquals(1f, mStackScroller.calculateAppearFraction(200)); + assertEquals(0.5f, mStackScroller.calculateAppearFraction(150)); + } + + @Test + public void testAppearFractionCalculationIsNotNegativeWhenShelfBecomesSmaller() { + // this situation might occur if status bar height is defined in pixels while shelf height + // in dp and screen density changes - appear start position + // (calculated in NSSL#getMinExpansionHeight) that is adjusting for status bar might + // increase and become bigger that end position, which should be prevented + + // appear start position + when(mNotificationShelf.getIntrinsicHeight()).thenReturn(80); + mStackScroller.mStatusBarHeight = 100; + // appear end position + when(mEmptyShadeView.getHeight()).thenReturn(90); + + assertThat(mStackScroller.calculateAppearFraction(100)).isAtLeast(0); } @Test |