/*
|
* Copyright (C) 2018 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;
|
|
import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
|
|
import android.annotation.NonNull;
|
import android.content.Context;
|
import android.content.res.Resources;
|
import android.util.ArraySet;
|
|
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.systemui.R;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
|
|
import javax.inject.Inject;
|
import javax.inject.Singleton;
|
|
/**
|
* Manager which handles high priority notifications that should "pulse" in when the device is
|
* dozing and/or in AOD. The pulse uses the notification's ambient view and pops in briefly
|
* before automatically dismissing the alert.
|
*/
|
@Singleton
|
public class AmbientPulseManager extends AlertingNotificationManager {
|
|
protected final ArraySet<OnAmbientChangedListener> mListeners = new ArraySet<>();
|
@VisibleForTesting
|
protected long mExtensionTime;
|
|
@Inject
|
public AmbientPulseManager(@NonNull final Context context) {
|
Resources resources = context.getResources();
|
mAutoDismissNotificationDecay = resources.getInteger(R.integer.ambient_notification_decay);
|
mMinimumDisplayTime = resources.getInteger(R.integer.ambient_notification_minimum_time);
|
mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
|
}
|
|
/**
|
* Adds an OnAmbientChangedListener to observe events.
|
*/
|
public void addListener(@NonNull OnAmbientChangedListener listener) {
|
mListeners.add(listener);
|
}
|
|
/**
|
* Removes the OnAmbientChangedListener from the observer list.
|
*/
|
public void removeListener(@NonNull OnAmbientChangedListener listener) {
|
mListeners.remove(listener);
|
}
|
|
/**
|
* Extends the lifetime of the currently showing pulsing notification so that the pulse lasts
|
* longer.
|
*/
|
public void extendPulse() {
|
AmbientEntry topEntry = getTopEntry();
|
if (topEntry == null) {
|
return;
|
}
|
topEntry.extendPulse();
|
}
|
|
public @InflationFlag int getContentFlag() {
|
return FLAG_CONTENT_VIEW_AMBIENT;
|
}
|
|
@Override
|
protected void onAlertEntryAdded(AlertEntry alertEntry) {
|
NotificationEntry entry = alertEntry.mEntry;
|
entry.setAmbientPulsing(true);
|
for (OnAmbientChangedListener listener : mListeners) {
|
listener.onAmbientStateChanged(entry, true);
|
}
|
}
|
|
@Override
|
protected void onAlertEntryRemoved(AlertEntry alertEntry) {
|
NotificationEntry entry = alertEntry.mEntry;
|
entry.setAmbientPulsing(false);
|
for (OnAmbientChangedListener listener : mListeners) {
|
listener.onAmbientStateChanged(entry, false);
|
}
|
entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
|
}
|
|
@Override
|
protected AlertEntry createAlertEntry() {
|
return new AmbientEntry();
|
}
|
|
/**
|
* Get the top pulsing entry. This should be the currently showing one if there are multiple.
|
* @return the currently showing entry
|
*/
|
private AmbientEntry getTopEntry() {
|
if (mAlertEntries.isEmpty()) {
|
return null;
|
}
|
AlertEntry topEntry = null;
|
for (AlertEntry entry : mAlertEntries.values()) {
|
if (topEntry == null || entry.compareTo(topEntry) < 0) {
|
topEntry = entry;
|
}
|
}
|
return (AmbientEntry) topEntry;
|
}
|
|
/**
|
* Observer interface for any changes in the ambient entries.
|
*/
|
public interface OnAmbientChangedListener {
|
/**
|
* Called when an entry starts or stops pulsing.
|
* @param entry the entry that changed
|
* @param isPulsing true if the entry is now pulsing, false otherwise
|
*/
|
void onAmbientStateChanged(@NonNull NotificationEntry entry, boolean isPulsing);
|
}
|
|
private final class AmbientEntry extends AlertEntry {
|
private boolean extended;
|
|
/**
|
* Extend the lifetime of the alertEntry so that it auto-removes later. Can only be
|
* extended once.
|
*/
|
private void extendPulse() {
|
if (!extended) {
|
extended = true;
|
updateEntry(false);
|
}
|
}
|
|
@Override
|
public void reset() {
|
super.reset();
|
extended = false;
|
}
|
|
@Override
|
protected long calculateFinishTime() {
|
return super.calculateFinishTime() + (extended ? mExtensionTime : 0);
|
}
|
}
|
}
|