diff options
5 files changed, 127 insertions, 41 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 3ed174b2d46f..c626ae9630b8 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2640,6 +2640,20 @@ public class Notification implements Parcelable } /** + * @hide + */ + public boolean suppressAlertingDueToGrouping() { + if (isGroupSummary() + && getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) { + return true; + } else if (isGroupChild() + && getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) { + return true; + } + return false; + } + + /** * Builder class for {@link Notification} objects. * * Provides a convenient way to set the various fields of a {@link Notification} and generate diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 2c9b2e4388f8..435675ba01e5 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -31,7 +31,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Build; import android.os.Handler; -import android.os.Message; +import android.os.Looper; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; @@ -120,34 +120,11 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb final Rect mTmpRect = new Rect(); final Configuration mConfiguration = new Configuration(); - static final int KEEP_SCREEN_ON_MSG = 1; - static final int DRAW_FINISHED_MSG = 2; - int mSubLayer = APPLICATION_MEDIA_SUBLAYER; boolean mIsCreating = false; private volatile boolean mRtHandlingPositionUpdates = false; - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case KEEP_SCREEN_ON_MSG: { - setKeepScreenOn(msg.arg1 != 0); - } break; - case DRAW_FINISHED_MSG: { - mDrawFinished = true; - if (mAttachedToWindow) { - mParent.requestTransparentRegion(SurfaceView.this); - - notifyDrawFinished(); - invalidate(); - } - } break; - } - } - }; - private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() { @Override @@ -751,7 +728,14 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mDeferredDestroySurfaceControl = null; } - mHandler.sendEmptyMessage(DRAW_FINISHED_MSG); + runOnUiThread(() -> { + mDrawFinished = true; + if (mAttachedToWindow) { + mParent.requestTransparentRegion(SurfaceView.this); + notifyDrawFinished(); + invalidate(); + } + }); } private void setParentSpaceRectangle(Rect position, long frameNumber) { @@ -880,6 +864,15 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb + "type=" + type, new Throwable()); } + private void runOnUiThread(Runnable runnable) { + Handler handler = getHandler(); + if (handler != null && handler.getLooper() != Looper.myLooper()) { + handler.post(runnable); + } else { + runnable.run(); + } + } + /** * Check to see if the surface has fixed size dimensions or if the surface's * dimensions are dimensions are dependent on its current layout. @@ -960,9 +953,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb @Override public void setKeepScreenOn(boolean screenOn) { - Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG); - msg.arg1 = screenOn ? 1 : 0; - mHandler.sendMessage(msg); + runOnUiThread(() -> SurfaceView.this.setKeepScreenOn(screenOn)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 51fb204f13a0..07ab6876e42b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -759,6 +759,7 @@ public class StatusBar extends SystemUI implements DemoMode, mBatteryController = Dependency.get(BatteryController.class); mAssistManager = Dependency.get(AssistManager.class); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); + mSystemServicesProxy = SystemServicesProxy.getInstance(mContext); mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); @@ -5192,6 +5193,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected KeyguardManager mKeyguardManager; private LockPatternUtils mLockPatternUtils; private DeviceProvisionedController mDeviceProvisionedController; + protected SystemServicesProxy mSystemServicesProxy; // UI-specific methods @@ -6816,6 +6818,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) { if (!mUseHeadsUp || isDeviceInVrMode()) { + if (DEBUG) Log.d(TAG, "No peeking: no huns or vr mode"); return false; } @@ -6824,8 +6827,7 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } - boolean inUse = mPowerManager.isScreenOn() - && !SystemServicesProxy.getInstance(mContext).isDreaming(); + boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming(); if (!inUse && !isDozing()) { if (DEBUG) { @@ -6868,6 +6870,12 @@ public class StatusBar extends SystemUI implements DemoMode, } } + // Don't peek notifications that are suppressed due to group alert behavior + if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) { + if (DEBUG) Log.d(TAG, "No peeking: suppressed due to group alert behavior"); + return false; + } + return true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index bf6b3946d101..55ec3079bdbb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -16,13 +16,27 @@ package com.android.systemui.statusbar.phone; +import static android.app.NotificationManager.IMPORTANCE_HIGH; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.app.Notification; import android.metrics.LogMaker; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IPowerManager; +import android.os.Looper; +import android.os.PowerManager; +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.support.test.metricshelper.MetricsAsserts; import android.support.test.runner.AndroidJUnit4; @@ -33,9 +47,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.SysuiTestCase; +import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.statusbar.ActivatableNotificationView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import org.junit.Before; @@ -52,19 +68,34 @@ public class StatusBarTest extends SysuiTestCase { NotificationStackScrollLayout mStackScroller; StatusBar mStatusBar; FakeMetricsLogger mMetricsLogger; + HeadsUpManager mHeadsUpManager; + NotificationData mNotificationData; + PowerManager mPowerManager; + SystemServicesProxy mSystemServicesProxy; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @Before - public void setup() { + public void setup() throws Exception { mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class); mUnlockMethodCache = mock(UnlockMethodCache.class); mKeyguardIndicationController = mock(KeyguardIndicationController.class); mStackScroller = mock(NotificationStackScrollLayout.class); mMetricsLogger = new FakeMetricsLogger(); + mHeadsUpManager = mock(HeadsUpManager.class); + mNotificationData = mock(NotificationData.class); + mSystemServicesProxy = mock(SystemServicesProxy.class); + IPowerManager powerManagerService = mock(IPowerManager.class); + HandlerThread handlerThread = new HandlerThread("TestThread"); + handlerThread.start(); + mPowerManager = new PowerManager(mContext, powerManagerService, + new Handler(handlerThread.getLooper())); + when(powerManagerService.isInteractive()).thenReturn(true); + mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache, - mKeyguardIndicationController, mStackScroller); + mKeyguardIndicationController, mStackScroller, mHeadsUpManager, + mNotificationData, mPowerManager, mSystemServicesProxy); doAnswer(invocation -> { OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0]; @@ -210,14 +241,62 @@ public class StatusBarTest extends SysuiTestCase { .setType(MetricsEvent.TYPE_ACTION)); } + @Test + public void testShouldPeek_nonSuppressedGroupSummary() { + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false); + when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false); + when(mNotificationData.shouldFilterOut(any())).thenReturn(false); + when(mSystemServicesProxy.isDreaming()).thenReturn(false); + when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH); + + Notification n = new Notification.Builder(getContext(), "a") + .setGroup("a") + .setGroupSummary(true) + .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY) + .build(); + StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, + UserHandle.of(0), null, 0); + NotificationData.Entry entry = new NotificationData.Entry(sbn); + + assertTrue(mStatusBar.shouldPeek(entry, sbn)); + } + + @Test + public void testShouldPeek_suppressedGroupSummary() { + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false); + when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false); + when(mNotificationData.shouldFilterOut(any())).thenReturn(false); + when(mSystemServicesProxy.isDreaming()).thenReturn(false); + when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH); + + Notification n = new Notification.Builder(getContext(), "a") + .setGroup("a") + .setGroupSummary(true) + .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) + .build(); + StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, + UserHandle.of(0), null, 0); + NotificationData.Entry entry = new NotificationData.Entry(sbn); + + assertFalse(mStatusBar.shouldPeek(entry, sbn)); + } + static class TestableStatusBar extends StatusBar { public TestableStatusBar(StatusBarKeyguardViewManager man, UnlockMethodCache unlock, KeyguardIndicationController key, - NotificationStackScrollLayout stack) { + NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd, + PowerManager pm, SystemServicesProxy ssp) { mStatusBarKeyguardViewManager = man; mUnlockMethodCache = unlock; mKeyguardIndicationController = key; mStackScroller = stack; + mHeadsUpManager = hum; + mNotificationData = nd; + mUseHeadsUp = true; + mPowerManager = pm; + mSystemServicesProxy = ssp; } @Override diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e377d57a0ead..3667e161b7af 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3225,7 +3225,7 @@ public class NotificationManagerService extends SystemService { Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0; if (warningEnabled) { Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText, - Toast.LENGTH_LONG); + Toast.LENGTH_SHORT); toast.show(); } } @@ -3759,13 +3759,7 @@ public class NotificationManagerService extends SystemService { return true; } if (record.sbn.isGroup()) { - if (notification.isGroupSummary() - && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) { - return true; - } else if (notification.isGroupChild() - && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) { - return true; - } + return notification.suppressAlertingDueToGrouping(); } return false; } |