Merge changes I089fa8ff,I8db745c1,I6fa83189 into qt-r1-dev

am: a0aa088c9f

Change-Id: I6d97a64ad21a4125761da9a833ca4bf0654e7642
This commit is contained in:
Selim Cinek
2019-06-29 16:49:07 -07:00
committed by android-build-merger
21 changed files with 345 additions and 56 deletions

View File

@@ -8275,6 +8275,16 @@ public final class Settings {
private static final Validator FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR =
BOOLEAN_VALIDATOR;
/**
* Whether or not media is shown automatically when bypassing as a heads up.
* @hide
*/
public static final String SHOW_MEDIA_WHEN_BYPASSING =
"show_media_when_bypassing";
private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR =
BOOLEAN_VALIDATOR;
/**
* Whether or not face unlock requires attention. This is a cached value, the source of
* truth is obtained through the HAL.
@@ -8979,6 +8989,7 @@ public final class Settings {
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
SHOW_MEDIA_WHEN_BYPASSING,
FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
@@ -9155,6 +9166,7 @@ public final class Settings {
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);

View File

@@ -138,6 +138,9 @@
<!-- The number of milliseconds before the heads up notification auto-dismisses. -->
<integer name="heads_up_notification_decay">5000</integer>
<!-- The number of milliseconds before the heads up notification sent automatically by the system auto-dismisses. -->
<integer name="auto_heads_up_notification_decay">3000</integer>
<!-- The number of milliseconds after a heads up notification is pushed back
before the app can interrupt again. -->
<integer name="heads_up_default_snooze_length_ms">60000</integer>

View File

@@ -52,6 +52,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -103,8 +104,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
private final Date mCurrentTime = new Date();
private final Handler mHandler;
private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
private final HashSet<Integer> mMediaInvisibleStates;
private final Object mMediaToken = new Object();
private DozeParameters mDozeParameters;
@VisibleForTesting
protected SettableWakeLock mMediaWakeLock;
@VisibleForTesting
@@ -184,11 +185,6 @@ public class KeyguardSliceProvider extends SliceProvider implements
mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
mDndUri = Uri.parse(KEYGUARD_DND_URI);
mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
mMediaInvisibleStates = new HashSet<>();
mMediaInvisibleStates.add(PlaybackState.STATE_NONE);
mMediaInvisibleStates.add(PlaybackState.STATE_STOPPED);
mMediaInvisibleStates.add(PlaybackState.STATE_PAUSED);
}
/**
@@ -201,12 +197,14 @@ public class KeyguardSliceProvider extends SliceProvider implements
public void initDependencies(
NotificationMediaManager mediaManager,
StatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController) {
KeyguardBypassController keyguardBypassController,
DozeParameters dozeParameters) {
mMediaManager = mediaManager;
mMediaManager.addCallback(this);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mKeyguardBypassController = keyguardBypassController;
mDozeParameters = dozeParameters;
}
@AnyThread
@@ -231,9 +229,9 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
protected boolean needsMediaLocked() {
boolean isBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.getBypassEnabled();
return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || isBypass);
boolean keepWhenAwake = mKeyguardBypassController != null
&& mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn();
return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake);
}
protected void addMediaLocked(ListBuilder listBuilder) {
@@ -458,7 +456,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
synchronized (this) {
boolean nextVisible = !mMediaInvisibleStates.contains(state);
boolean nextVisible = NotificationMediaManager.isPlayingState(state);
mHandler.removeCallbacksAndMessages(mMediaToken);
if (mMediaIsVisible && !nextVisible) {
// We need to delay this event for a few millis when stopping to avoid jank in the
@@ -477,7 +475,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) {
boolean nextVisible = !mMediaInvisibleStates.contains(state);
boolean nextVisible = NotificationMediaManager.isPlayingState(state);
CharSequence title = null;
if (metadata != null) {
title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE);

View File

@@ -69,6 +69,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -91,6 +92,14 @@ public class NotificationMediaManager implements Dumpable {
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
private final KeyguardBypassController mKeyguardBypassController;
private static final HashSet<Integer> PAUSED_MEDIA_STATES = new HashSet<>();
static {
PAUSED_MEDIA_STATES.add(PlaybackState.STATE_NONE);
PAUSED_MEDIA_STATES.add(PlaybackState.STATE_STOPPED);
PAUSED_MEDIA_STATES.add(PlaybackState.STATE_PAUSED);
PAUSED_MEDIA_STATES.add(PlaybackState.STATE_ERROR);
}
// Late binding
private NotificationEntryManager mEntryManager;
@@ -207,6 +216,10 @@ public class NotificationMediaManager implements Dumpable {
mPropertiesChangedListener);
}
public static boolean isPlayingState(int state) {
return !PAUSED_MEDIA_STATES.contains(state);
}
public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.statusbar;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
import android.content.res.Configuration;
@@ -48,8 +49,12 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import javax.inject.Inject;
import javax.inject.Named;
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
@@ -63,6 +68,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
private final KeyguardBypassController mBypassController;
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
@@ -93,8 +99,12 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mCutoutHeight;
private int mGapHeight;
public NotificationShelf(Context context, AttributeSet attrs) {
@Inject
public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
KeyguardBypassController keyguardBypassController) {
super(context, attrs);
mBypassController = keyguardBypassController;
}
@Override
@@ -309,7 +319,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
colorTwoBefore = previousColor;
transitionAmount = inShelfAmount;
}
if (isLastChild) {
// We don't want to modify the color if the notification is hun'd
boolean canModifyColor = mAmbientState.isShadeExpanded()
&& !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
if (isLastChild && canModifyColor) {
if (colorOfViewBeforeLast == NO_COLOR) {
colorOfViewBeforeLast = ownColorUntinted;
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2019 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
*/
package com.android.systemui.statusbar.notification
import android.content.Context
import android.media.MediaMetadata
import android.provider.Settings
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.tuner.TunerService
import javax.inject.Inject
import javax.inject.Singleton
/**
* A class that automatically creates heads up for important notification when bypassing the
* lockscreen
*/
@Singleton
class BypassHeadsUpNotifier @Inject constructor(
private val context: Context,
private val bypassController: KeyguardBypassController,
private val statusBarStateController: StatusBarStateController,
private val headsUpManager: HeadsUpManagerPhone,
private val mediaManager: NotificationMediaManager,
tunerService: TunerService) : StatusBarStateController.StateListener,
NotificationMediaManager.MediaListener {
private lateinit var entryManager: NotificationEntryManager
private var currentMediaEntry: NotificationEntry? = null
private var enabled = true
var fullyAwake = false
set(value) {
field = value
if (value) {
updateAutoHeadsUp(currentMediaEntry)
}
}
init {
statusBarStateController.addCallback(this)
tunerService.addTunable(
TunerService.Tunable { _, _ ->
enabled = Settings.Secure.getIntForUser(
context.contentResolver,
Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING,
1 /* default */,
KeyguardUpdateMonitor.getCurrentUser()) != 0
}, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING)
}
fun setUp(entryManager: NotificationEntryManager) {
this.entryManager = entryManager
mediaManager.addCallback(this)
}
override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
val previous = currentMediaEntry
var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
if (!NotificationMediaManager.isPlayingState(state)) {
newEntry = null
}
if (newEntry?.isSensitive == true) {
newEntry = null
}
currentMediaEntry = newEntry
updateAutoHeadsUp(previous)
updateAutoHeadsUp(currentMediaEntry)
}
private fun updateAutoHeadsUp(entry: NotificationEntry?) {
entry?.let {
val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp()
it.isAutoHeadsUp = autoHeadsUp
if (autoHeadsUp) {
headsUpManager.showNotification(it)
}
}
}
override fun onStatePostChange() {
updateAutoHeadsUp(currentMediaEntry)
}
private fun canAutoHeadsUp() : Boolean {
if (!enabled) {
return false
}
if (!bypassController.bypassEnabled) {
return false
}
if (statusBarStateController.state != StatusBarState.KEYGUARD) {
return false
}
if (!fullyAwake) {
return false
}
return true
}
}

View File

@@ -24,7 +24,6 @@ import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -119,12 +118,11 @@ public class NotificationAlertingManager {
shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
if (wasAlerting) {
if (!shouldAlert) {
// We don't want this to be interrupting anymore, let's remove it
mHeadsUpManager.removeNotification(entry.key,
false /* ignoreEarliestRemovalTime */);
} else {
if (shouldAlert) {
mHeadsUpManager.updateNotification(entry.key, alertAgain);
} else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
// We don't want this to be interrupting anymore, let's remove it
mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
}
} else if (shouldAlert && alertAgain) {
// This notification was updated to be alerting, show it!

View File

@@ -24,6 +24,8 @@ import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import androidx.annotation.NonNull;
/**
* Listener interface for changes sent by NotificationEntryManager.
*/
@@ -45,7 +47,7 @@ public interface NotificationEntryListener {
/**
* Called when a new entry is created.
*/
default void onNotificationAdded(NotificationEntry entry) {
default void onNotificationAdded(@NonNull NotificationEntry entry) {
}
/**
@@ -61,7 +63,7 @@ public interface NotificationEntryListener {
/**
* Called when a notification was updated, after any filtering of notifications have occurred.
*/
default void onPostEntryUpdated(NotificationEntry entry) {
default void onPostEntryUpdated(@NonNull NotificationEntry entry) {
}
/**

View File

@@ -175,6 +175,7 @@ public final class NotificationEntry {
private boolean mHighPriority;
private boolean mSensitive = true;
private Runnable mOnSensitiveChangedListener;
private boolean mAutoHeadsUp;
public NotificationEntry(StatusBarNotification n) {
this(n, null);
@@ -670,11 +671,25 @@ public final class NotificationEntry {
if (row != null) row.setHeadsUp(shouldHeadsUp);
}
public void setHeadsUpAnimatingAway(boolean animatingAway) {
if (row != null) row.setHeadsUpAnimatingAway(animatingAway);
}
/**
* Set that this notification was automatically heads upped. This happens for example when
* the user bypasses the lockscreen and media is playing.
*/
public void setAutoHeadsUp(boolean autoHeadsUp) {
mAutoHeadsUp = autoHeadsUp;
}
/**
* @return if this notification was automatically heads upped. This happens for example when
* * the user bypasses the lockscreen and media is playing.
*/
public boolean isAutoHeadsUp() {
return mAutoHeadsUp;
}
public boolean mustStayOnScreen() {
return row != null && row.mustStayOnScreen();

View File

@@ -2698,6 +2698,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
l.setAlpha(1.0f);
l.setLayerType(LAYER_TYPE_NONE, null);
}
} else {
setHeadsUpAnimatingAway(false);
}
}

View File

@@ -837,7 +837,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
break;
}
}
if (!mAmbientState.isDozing() || anySectionHasVisibleChild) {
boolean shouldDrawBackground;
if (mKeyguardBypassController.getBypassEnabled() && onKeyguard()) {
shouldDrawBackground = isPulseExpanding();
} else {
shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild;
}
if (shouldDrawBackground) {
drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
}
@@ -3396,10 +3402,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
ExpandableNotificationRow row = eventPair.first;
boolean isHeadsUp = eventPair.second;
if (isHeadsUp != row.isHeadsUp()) {
// For cases where we have a heads up showing and appearing again we shouldn't
// do the animations at all.
continue;
}
int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
boolean onBottom = false;
boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
if (!mIsExpanded && !isHeadsUp) {
boolean performDisappearAnimation = !mIsExpanded
// Only animate if we still have pinned heads up, otherwise we just have the
// regular collapse animation of the lock screen
|| (mKeyguardBypassController.getBypassEnabled() && onKeyguard()
&& mHeadsUpManager.hasPinnedHeadsUp());
if (performDisappearAnimation && !isHeadsUp) {
type = row.wasJustClicked()
? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
: AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
@@ -6246,6 +6262,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mAmbientState.onDragFinished(animView);
updateContinuousShadowDrawing();
updateContinuousBackgroundDrawing();
if (animView instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
if (row.isPinned() && !canChildBeDismissed(row)
&& row.getStatusBarNotification().getNotification().fullScreenIntent
== null) {
mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
true /* removeImmediately */);
}
}
}
@Override

View File

@@ -546,12 +546,12 @@ public class StackScrollAlgorithm {
ExpandableViewState topState =
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
if (topState != null && !isTopEntry && (!mIsExpanded
|| unmodifiedEndLocation < topState.yTranslation + topState.height)) {
|| unmodifiedEndLocation > topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
childState.height = row.getIntrinsicHeight();
childState.yTranslation = topState.yTranslation + topState.height
- childState.height;
childState.yTranslation = Math.min(topState.yTranslation + topState.height
- childState.height, childState.yTranslation);
}
// heads up notification show and this row is the top entry of heads up

View File

@@ -28,6 +28,7 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -451,7 +452,11 @@ public class StackStateAnimator {
if (row.isDismissed()) {
needsAnimation = false;
}
StatusBarIconView icon = row.getEntry().icon;
NotificationEntry entry = row.getEntry();
StatusBarIconView icon = entry.icon;
if (entry.centeredIcon != null && entry.centeredIcon.getParent() != null) {
icon = entry.centeredIcon;
}
if (icon.getParent() != null) {
icon.getLocationOnScreen(mTmpLocation);
float iconPosition = mTmpLocation[0] - icon.getTranslationX()

View File

@@ -32,7 +32,6 @@ import android.view.ViewTreeObserver;
import androidx.collection.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
@@ -67,6 +66,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
final int mExtensionTime;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mBypassController;
private final int mAutoHeadsUpNotificationDecay;
private View mStatusBarWindowView;
private NotificationGroupManager mGroupManager;
private VisualStabilityManager mVisualStabilityManager;
@@ -81,6 +81,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
private boolean mTrackingHeadsUp;
private HashSet<String> mSwipedOutKeys = new HashSet<>();
private HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
private HashSet<String> mKeysToRemoveWhenLeavingKeyguard = new HashSet<>();
private ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
= new ArraySet<>();
private boolean mIsExpanded;
@@ -121,6 +122,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
mAutoDismissNotificationDecayDozing = resources.getInteger(
R.integer.heads_up_notification_decay_dozing);
mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
mAutoHeadsUpNotificationDecay = resources.getInteger(
R.integer.auto_heads_up_notification_decay);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mBypassController = bypassController;
@@ -231,7 +234,16 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
public void onStateChanged(int newState) {
boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
boolean isKeyguard = newState == StatusBarState.KEYGUARD;
mStatusBarState = newState;
if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
for (String key : keys) {
removeAlertEntry(key);
}
mKeysToRemoveWhenLeavingKeyguard.clear();
}
}
@Override
@@ -245,6 +257,15 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
}
@Override
public boolean isEntryAutoHeadsUpped(String key) {
HeadsUpEntryPhone headsUpEntryPhone = getHeadsUpEntryPhone(key);
if (headsUpEntryPhone == null) {
return false;
}
return headsUpEntryPhone.isAutoHeadsUp();
}
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a sane state.
@@ -420,6 +441,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
protected void onAlertEntryRemoved(AlertEntry alertEntry) {
mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
super.onAlertEntryRemoved(alertEntry);
mEntryPool.release((HeadsUpEntryPhone) alertEntry);
}
@@ -479,6 +501,11 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
*/
private boolean extended;
/**
* Was this entry received while on keyguard
*/
private boolean mIsAutoHeadsUp;
@Override
protected boolean isSticky() {
@@ -494,10 +521,12 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
mEntriesToRemoveWhenReorderingAllowed.add(entry);
mVisualStabilityManager.addReorderingAllowedCallback(
HeadsUpManagerPhone.this);
} else if (!mTrackingHeadsUp) {
removeAlertEntry(entry.key);
} else {
} else if (mTrackingHeadsUp) {
mEntriesToRemoveAfterExpand.add(entry);
} else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
} else {
removeAlertEntry(entry.key);
}
};
@@ -506,6 +535,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
public void updateEntry(boolean updatePostTime) {
mIsAutoHeadsUp = mEntry.isAutoHeadsUp();
super.updateEntry(updatePostTime);
if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
@@ -514,6 +544,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
}
mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
}
@Override
@@ -548,6 +579,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
super.reset();
mMenuShownPinned = false;
extended = false;
mIsAutoHeadsUp = false;
}
private void extendPulse() {
@@ -557,14 +589,36 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
}
@Override
public int compareTo(AlertEntry alertEntry) {
HeadsUpEntryPhone headsUpEntry = (HeadsUpEntryPhone) alertEntry;
boolean autoShown = isAutoHeadsUp();
boolean otherAutoShown = headsUpEntry.isAutoHeadsUp();
if (autoShown && !otherAutoShown) {
return 1;
} else if (!autoShown && otherAutoShown) {
return -1;
}
return super.compareTo(alertEntry);
}
@Override
protected long calculateFinishTime() {
return mPostTime + getDecayDuration() + (extended ? mExtensionTime : 0);
}
private int getDecayDuration() {
return mStatusBarStateController.isDozing() ? mAutoDismissNotificationDecayDozing
: getRecommendedHeadsUpTimeoutMs();
if (mStatusBarStateController.isDozing()) {
return mAutoDismissNotificationDecayDozing;
} else if (isAutoHeadsUp()) {
return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay);
} else {
return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
}
}
private boolean isAutoHeadsUp() {
return mIsAutoHeadsUp;
}
}

View File

@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import java.lang.annotation.Retention;
@@ -67,7 +68,8 @@ import javax.inject.Named;
public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener {
NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener,
OnHeadsUpChangedListener {
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
@@ -82,6 +84,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private final KeyguardMonitor mKeyguardMonitor;
private final KeyguardBypassController mBypassController;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final HeadsUpManagerPhone mHeadsUpManager;
private int mLastState = 0;
private boolean mForceUpdate;
@@ -94,7 +97,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private boolean mDocked;
private int mIconColor;
private float mDozeAmount;
private boolean mBouncerShowing;
private boolean mBouncerShowingScrimmed;
private boolean mWakeAndUnlockRunning;
private boolean mKeyguardShowing;
private boolean mShowingLaunchAffordance;
@@ -155,7 +158,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
KeyguardBypassController bypassController,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardMonitor keyguardMonitor,
@Nullable DockManager dockManager) {
@Nullable DockManager dockManager,
HeadsUpManagerPhone headsUpManager) {
super(context, attrs);
mContext = context;
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
@@ -167,6 +171,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mWakeUpCoordinator = wakeUpCoordinator;
mKeyguardMonitor = keyguardMonitor;
mDockManager = dockManager;
mHeadsUpManager = headsUpManager;
}
@Override
@@ -296,11 +301,13 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
|| mShowingLaunchAffordance;
if (mBypassController.getBypassEnabled()
&& mStatusBarStateController.getState() == StatusBarState.KEYGUARD
&& !mWakeUpCoordinator.getNotificationsFullyHidden()
&& !mBouncerShowing) {
invisible = true;
if (mBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) {
if (mHeadsUpManager.isHeadsUpGoingAway()
|| mHeadsUpManager.hasPinnedHeadsUp()
|| (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
&& !mWakeUpCoordinator.getNotificationsFullyHidden())) {
invisible = true;
}
}
boolean wasInvisible = getVisibility() == INVISIBLE;
if (invisible != wasInvisible) {
@@ -408,8 +415,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
}
public void setBouncerShowing(boolean bouncerShowing) {
mBouncerShowing = bouncerShowing;
public void setBouncerShowingScrimmed(boolean bouncerShowing) {
mBouncerShowingScrimmed = bouncerShowing;
if (mBypassController.getBypassEnabled()) {
update();
}

View File

@@ -248,7 +248,7 @@ public class NotificationIconAreaController implements DarkReceiver,
if (onlyShowCenteredIcon) {
return isCenteredNotificationIcon;
}
if (hideCenteredIcon && isCenteredNotificationIcon) {
if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
return false;
}
if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {

View File

@@ -80,6 +80,7 @@ import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -193,6 +194,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -373,6 +375,8 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardBypassController mKeyguardBypassController;
@Inject
protected HeadsUpManagerPhone mHeadsUpManager;
@Inject
BypassHeadsUpNotifier mBypassHeadsUpNotifier;
@Nullable
@Inject
protected KeyguardLiftController mKeyguardLiftController;
@@ -633,6 +637,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mGutsManager = Dependency.get(NotificationGutsManager.class);
mMediaManager = Dependency.get(NotificationMediaManager.class);
mEntryManager = Dependency.get(NotificationEntryManager.class);
mBypassHeadsUpNotifier.setUp(mEntryManager);
mNotificationInterruptionStateProvider =
Dependency.get(NotificationInterruptionStateProvider.class);
mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
@@ -649,7 +654,7 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
if (sliceProvider != null) {
sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
mKeyguardBypassController);
mKeyguardBypassController, DozeParameters.getInstance(mContext));
} else {
Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
}
@@ -1154,8 +1159,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private void inflateShelf() {
mNotificationShelf =
(NotificationShelf) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_shelf, mStackScroller, false);
(NotificationShelf) mInjectionInflater.injectable(
LayoutInflater.from(mContext)).inflate(
R.layout.status_bar_notification_shelf, mStackScroller, false);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -3576,7 +3582,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mBouncerShowing = bouncerShowing;
mKeyguardBypassController.setBouncerShowing(bouncerShowing);
mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
mStatusBarWindow.setBouncerShowing(bouncerShowing);
mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
updateHideIconsForBouncer(true /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3629,6 +3635,7 @@ public class StatusBar extends SystemUI implements DemoMode,
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
mWakeUpCoordinator.setFullyAwake(false);
mBypassHeadsUpNotifier.setFullyAwake(false);
mKeyguardBypassController.onStartedGoingToSleep();
}
@@ -3653,6 +3660,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onFinishedWakingUp() {
mWakeUpCoordinator.setFullyAwake(true);
mBypassHeadsUpNotifier.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);

View File

@@ -525,9 +525,9 @@ public class StatusBarWindowView extends FrameLayout {
mBypassController = bypassController;
}
public void setBouncerShowing(boolean bouncerShowing) {
public void setBouncerShowingScrimmed(boolean bouncerShowing) {
if (mLockIcon != null) {
mLockIcon.setBouncerShowing(bouncerShowing);
mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
}
}

View File

@@ -356,6 +356,10 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
public void onDensityOrFontScaleChanged() {
}
public boolean isEntryAutoHeadsUpped(String key) {
return false;
}
/**
* This represents a notification and how long it is in a heads up mode. It also manages its
* lifecycle automatically when created.
@@ -416,16 +420,17 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
@Override
protected long calculateFinishTime() {
return mPostTime + getRecommendedHeadsUpTimeoutMs();
return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
}
/**
* Get user-preferred or default timeout duration. The larger one will be returned.
* @return milliseconds before auto-dismiss
* @param requestedTimeout
*/
protected int getRecommendedHeadsUpTimeoutMs() {
protected int getRecommendedHeadsUpTimeoutMs(int requestedTimeout) {
return mAccessibilityMgr.getRecommendedTimeoutMillis(
mAutoDismissNotificationDecay,
requestedTimeout,
AccessibilityManager.FLAG_CONTENT_CONTROLS
| AccessibilityManager.FLAG_CONTENT_ICONS
| AccessibilityManager.FLAG_CONTENT_TEXT);

View File

@@ -32,6 +32,7 @@ import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -137,6 +138,11 @@ public class InjectionInflationController {
*/
QSCarrierGroup createQSCarrierGroup();
/**
* Creates the Shelf.
*/
NotificationShelf creatNotificationShelf();
/**
* Creates the KeyguardClockSwitch.
*/

View File

@@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -84,6 +85,8 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
private SettableWakeLock mMediaWakeLock;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
private DozeParameters mDozeParameters;
private TestableKeyguardSliceProvider mProvider;
private boolean mIsZenMode;
@@ -94,7 +97,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
mProvider = new TestableKeyguardSliceProvider();
mProvider.attachInfo(getContext(), null);
mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController,
mKeyguardBypassController);
mKeyguardBypassController, mDozeParameters);
SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
}
@@ -130,6 +133,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
MediaMetadata metadata = mock(MediaMetadata.class);
when(metadata.getText(any())).thenReturn("metadata");
when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
mProvider.onBindSlice(mProvider.getUri());
verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));