blob: 5f878cee12d6c3b830c2d7c1c370a22c13a78c68 [file] [log] [blame]
/*
* 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);
}
}
}