blob: 259f69296ac73ccba91892f7af3ad7e6d08291e8 [file] [log] [blame]
/*
* Copyright (C) 2020 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.wm.shell.bubbles;
import static android.window.ScreenCapture.ScreenshotSync;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.app.NotificationChannel;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Icon;
import android.hardware.HardwareBuffer;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.util.Pair;
import android.util.SparseArray;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
/**
* Interface to engage bubbles feature.
*/
@ExternalThread
public interface Bubbles {
@Retention(SOURCE)
@IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE,
DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT,
DISMISS_OVERFLOW_MAX_REACHED, DISMISS_SHORTCUT_REMOVED, DISMISS_PACKAGE_REMOVED,
DISMISS_NO_BUBBLE_UP, DISMISS_RELOAD_FROM_DISK, DISMISS_USER_REMOVED})
@Target({FIELD, LOCAL_VARIABLE, PARAMETER})
@interface DismissReason {}
int DISMISS_USER_GESTURE = 1;
int DISMISS_AGED = 2;
int DISMISS_TASK_FINISHED = 3;
int DISMISS_BLOCKED = 4;
int DISMISS_NOTIF_CANCEL = 5;
int DISMISS_ACCESSIBILITY_ACTION = 6;
int DISMISS_NO_LONGER_BUBBLE = 7;
int DISMISS_USER_CHANGED = 8;
int DISMISS_GROUP_CANCELLED = 9;
int DISMISS_INVALID_INTENT = 10;
int DISMISS_OVERFLOW_MAX_REACHED = 11;
int DISMISS_SHORTCUT_REMOVED = 12;
int DISMISS_PACKAGE_REMOVED = 13;
int DISMISS_NO_BUBBLE_UP = 14;
int DISMISS_RELOAD_FROM_DISK = 15;
int DISMISS_USER_REMOVED = 16;
/** Returns a binder that can be passed to an external process to manipulate Bubbles. */
default IBubbles createExternalInterface() {
return null;
}
/**
* @return {@code true} if there is a bubble associated with the provided key and if its
* notification is hidden from the shade or there is a group summary associated with the
* provided key that is hidden from the shade because it has been dismissed but still has child
* bubbles active.
*/
boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey);
/**
* @return {@code true} if the current notification entry same as selected bubble
* notification entry and the stack is currently expanded.
*/
boolean isBubbleExpanded(String key);
/** Tell the stack of bubbles to collapse. */
void collapseStack();
/**
* Request the stack expand if needed, then select the specified Bubble as current.
* If no bubble exists for this entry, one is created.
*
* @param entry the notification for the bubble to be selected
*/
void expandStackAndSelectBubble(BubbleEntry entry);
/**
* Request the stack expand if needed, then select the specified Bubble as current.
*
* @param bubble the bubble to be selected
*/
void expandStackAndSelectBubble(Bubble bubble);
/**
* This method has different behavior depending on:
* - if an app bubble exists
* - if an app bubble is expanded
*
* If no app bubble exists, this will add and expand a bubble with the provided intent. The
* intent must be explicit (i.e. include a package name or fully qualified component class name)
* and the activity for it should be resizable.
*
* If an app bubble exists, this will toggle the visibility of it, i.e. if the app bubble is
* expanded, calling this method will collapse it. If the app bubble is not expanded, calling
* this method will expand it.
*
* These bubbles are <b>not</b> backed by a notification and remain until the user dismisses
* the bubble or bubble stack.
*
* Some notes:
* - Only one app bubble is supported at a time, regardless of users. Multi-users support is
* tracked in b/273533235.
* - Calling this method with a different intent than the existing app bubble will do nothing
*
* @param intent the intent to display in the bubble expanded view.
* @param user the {@link UserHandle} of the user to start this activity for.
* @param icon the {@link Icon} to use for the bubble view.
*/
void showOrHideAppBubble(Intent intent, UserHandle user, @Nullable Icon icon);
/** @return true if the specified {@code taskId} corresponds to app bubble's taskId. */
boolean isAppBubbleTaskId(int taskId);
/**
* @return a {@link ScreenshotSync} after performing a screenshot that may exclude the bubble
* layer, if one is present. The underlying {@link ScreenshotHardwareBuffer} can be access via
* {@link ScreenshotSync#get()} asynchronously and care should be taken to
* {@link HardwareBuffer#close()} the associated
* {@link ScreenshotHardwareBuffer#getHardwareBuffer()} when no longer required.
*/
ScreenshotSync getScreenshotExcludingBubble(int displayId);
/**
* @return a bubble that matches the provided shortcutId, if one exists.
*/
@Nullable
Bubble getBubbleWithShortcutId(String shortcutId);
/**
* We intercept notification entries (including group summaries) dismissed by the user when
* there is an active bubble associated with it. We do this so that developers can still
* cancel it (and hence the bubbles associated with it). However, these intercepted
* notifications should then be hidden from the shade since the user has cancelled them, so we
* {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add
* {@link BubbleData#addSummaryToSuppress}.
*
* @param entry the notification of the BubbleEntry should be removed.
* @param children the list of child notification of the BubbleEntry from 1st param entry,
* this will be null if entry does have no children.
* @param removeCallback the remove callback for SystemUI side to remove notification, the int
* number should be list position of children list and use -1 for
* removing the parent notification.
*
* @return true if we want to intercept the dismissal of the entry, else false.
*/
boolean handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children,
IntConsumer removeCallback, Executor callbackExecutor);
/** Set the proxy to commnuicate with SysUi side components. */
void setSysuiProxy(SysuiProxy proxy);
/** Set a listener to be notified of bubble expand events. */
void setExpandListener(BubbleExpandListener listener);
/**
* Called when new notification entry added.
*
* @param entry the {@link BubbleEntry} by the notification.
*/
void onEntryAdded(BubbleEntry entry);
/**
* Called when new notification entry updated.
*
* @param entry the {@link BubbleEntry} by the notification.
* @param shouldBubbleUp {@code true} if this notification should bubble up.
* @param fromSystem {@code true} if this update is from NotificationManagerService.
*/
void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem);
/**
* Called when new notification entry removed.
*
* @param entry the {@link BubbleEntry} by the notification.
*/
void onEntryRemoved(BubbleEntry entry);
/**
* Called when NotificationListener has received adjusted notification rank and reapplied
* filtering and sorting. This is used to dismiss or create bubbles based on changes in
* permissions on the notification channel or the global setting.
*
* @param rankingMap the updated ranking map from NotificationListenerService
* @param entryDataByKey a map of ranking key to bubble entry and whether the entry should
* bubble up
*/
void onRankingUpdated(
RankingMap rankingMap,
HashMap<String, Pair<BubbleEntry, Boolean>> entryDataByKey);
/**
* Called when a notification channel is modified, in response to
* {@link NotificationListenerService#onNotificationChannelModified}.
*
* @param pkg the package the notification channel belongs to.
* @param user the user the notification channel belongs to.
* @param channel the channel being modified.
* @param modificationType the type of modification that occurred to the channel.
*/
void onNotificationChannelModified(
String pkg,
UserHandle user,
NotificationChannel channel,
int modificationType);
/**
* Called when notification panel is expanded or collapsed
*/
void onNotificationPanelExpandedChanged(boolean expanded);
/**
* Called when the status bar has become visible or invisible (either permanently or
* temporarily).
*/
void onStatusBarVisibilityChanged(boolean visible);
/** Called when system zen mode state changed. */
void onZenStateChanged();
/**
* Called when statusBar state changed.
*
* @param isShade {@code true} is state is SHADE.
*/
void onStatusBarStateChanged(boolean isShade);
/**
* Called when the current user changed.
*
* @param newUserId the new user's id.
*/
void onUserChanged(int newUserId);
/**
* Called when the current user profiles change.
*
* @param currentProfiles the user infos for the current profile.
*/
void onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles);
/**
* Called when a user is removed.
*
* @param removedUserId the id of the removed user.
*/
void onUserRemoved(int removedUserId);
/**
* A listener to be notified of bubble state changes, used by launcher to render bubbles in
* its process.
*/
interface BubbleStateListener {
/**
* Called when the bubbles state changes.
*/
void onBubbleStateChange(BubbleBarUpdate update);
}
/** Listener to find out about stack expansion / collapse events. */
interface BubbleExpandListener {
/**
* Called when the expansion state of the bubble stack changes.
*
* @param isExpanding whether it's expanding or collapsing
* @param key the notification key associated with bubble being expanded
*/
void onBubbleExpandChanged(boolean isExpanding, String key);
}
/** Listener to be notified when the flags on BubbleMetadata have changed. */
interface BubbleMetadataFlagListener {
/** Called when the flags on BubbleMetadata have changed for the provided bubble. */
void onBubbleMetadataFlagChanged(Bubble bubble);
}
/** Listener to be notified when a pending intent has been canceled for a bubble. */
interface PendingIntentCanceledListener {
/** Called when the pending intent for a bubble has been canceled. */
void onPendingIntentCanceled(Bubble bubble);
}
/** Callback to tell SysUi components execute some methods. */
interface SysuiProxy {
void isNotificationPanelExpand(Consumer<Boolean> callback);
void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback);
void getShouldRestoredEntries(Set<String> savedBubbleKeys,
Consumer<List<BubbleEntry>> callback);
void setNotificationInterruption(String key);
void requestNotificationShadeTopUi(boolean requestTopUi, String componentTag);
void notifyRemoveNotification(String key, int reason);
void notifyInvalidateNotifications(String reason);
void updateNotificationBubbleButton(String key);
void onStackExpandChanged(boolean shouldExpand);
void onManageMenuExpandChanged(boolean menuExpanded);
void onUnbubbleConversation(String key);
}
}