Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e15c6dd8 authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge changes from topic "mm_setSuppress" into sc-dev

* changes:
  SysUI changes for setSuppressBubble
  Track locusId visibility in ShellTaskOrganizer
  Add locus id to ActivityRecord / TaskInfo
  Bubble API: suppress bubble
parents cc22a26a c9871c4d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -5819,6 +5819,8 @@ package android.app {
    method @Nullable public android.graphics.drawable.Icon getIcon();
    method @Nullable public android.app.PendingIntent getIntent();
    method @Nullable public String getShortcutId();
    method public boolean isBubbleSuppressable();
    method public boolean isBubbleSuppressed();
    method public boolean isNotificationSuppressed();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR;
@@ -5835,6 +5837,7 @@ package android.app {
    method @NonNull public android.app.Notification.BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int);
    method @NonNull public android.app.Notification.BubbleMetadata.Builder setIcon(@NonNull android.graphics.drawable.Icon);
    method @NonNull public android.app.Notification.BubbleMetadata.Builder setIntent(@NonNull android.app.PendingIntent);
    method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressBubble(boolean);
    method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressNotification(boolean);
  }
+59 −0
Original line number Diff line number Diff line
@@ -9907,6 +9907,22 @@ public class Notification implements Parcelable
         */
        public static final int FLAG_SUPPRESS_NOTIFICATION = 0x00000002;

        /**
         * Indicates whether the bubble should be visually suppressed from the bubble stack if the
         * user is viewing the same content outside of the bubble. For example, the user has a
         * bubble with Alice and then opens up the main app and navigates to Alice's page.
         *
         * @hide
         */
        public static final int FLAG_SHOULD_SUPPRESS_BUBBLE = 0x00000004;

        /**
         * Indicates whether the bubble is visually suppressed from the bubble stack.
         *
         * @hide
         */
        public static final int FLAG_SUPPRESS_BUBBLE = 0x00000008;

        private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent,
                Icon icon, int height, @DimenRes int heightResId, String shortcutId) {
            mPendingIntent = expandIntent;
@@ -10049,6 +10065,32 @@ public class Notification implements Parcelable
            return (mFlags & FLAG_SUPPRESS_NOTIFICATION) != 0;
        }

        /**
         * Indicates whether the bubble should be visually suppressed from the bubble stack if the
         * user is viewing the same content outside of the bubble. For example, the user has a
         * bubble with Alice and then opens up the main app and navigates to Alice's page.
         *
         * To match the activity and the bubble notification, the bubble notification should
         * have a locus id set that matches a locus id set on the activity.
         *
         * @return whether this bubble should be suppressed when the same content is visible
         * outside of the bubble.
         *
         * @see BubbleMetadata.Builder#setSuppressBubble(boolean)
         */
        public boolean isBubbleSuppressable() {
            return (mFlags & FLAG_SHOULD_SUPPRESS_BUBBLE) != 0;
        }

        /**
         * Indicates whether the bubble is currently visually suppressed from the bubble stack.
         *
         * @see BubbleMetadata.Builder#setSuppressBubble(boolean)
         */
        public boolean isBubbleSuppressed() {
            return (mFlags & FLAG_SUPPRESS_BUBBLE) != 0;
        }

        public static final @android.annotation.NonNull Parcelable.Creator<BubbleMetadata> CREATOR =
                new Parcelable.Creator<BubbleMetadata>() {

@@ -10390,6 +10432,23 @@ public class Notification implements Parcelable
                return this;
            }

            /**
             * Indicates whether the bubble should be visually suppressed from the bubble stack if
             * the user is viewing the same content outside of the bubble. For example, the user has
             * a bubble with Alice and then opens up the main app and navigates to Alice's page.
             *
             * To match the activity and the bubble notification, the bubble notification should
             * have a locus id set that matches a locus id set on the activity.
             *
             * {@link Notification.Builder#setLocusId(LocusId)}
             * {@link Activity#setLocusContext(LocusId, Bundle)}
             */
            @NonNull
            public BubbleMetadata.Builder setSuppressBubble(boolean suppressBubble) {
                setFlag(FLAG_SHOULD_SUPPRESS_BUBBLE, suppressBubble);
                return this;
            }

            /**
             * Sets an intent to send when this bubble is explicitly removed by the user.
             *
+11 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.LocusId;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
@@ -122,6 +123,13 @@ public class TaskInfo {
    @Nullable
    public ActivityManager.TaskDescription taskDescription;

    /**
     * The locusId of the task.
     * @hide
     */
    @Nullable
    public LocusId mTopActivityLocusId;

    /**
     * True if the task can go in the split-screen primary stack.
     * @hide
@@ -381,6 +389,7 @@ public class TaskInfo {
        isVisible = source.readBoolean();
        topActivityToken = source.readStrongBinder();
        topActivityInSizeCompat = source.readBoolean();
        mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
    }

    /**
@@ -417,6 +426,7 @@ public class TaskInfo {
        dest.writeBoolean(isVisible);
        dest.writeStrongBinder(topActivityToken);
        dest.writeBoolean(topActivityInSizeCompat);
        dest.writeTypedObject(mTopActivityLocusId, flags);
    }

    @Override
@@ -443,6 +453,7 @@ public class TaskInfo {
                + " isVisible=" + isVisible
                + " topActivityToken=" + topActivityToken
                + " topActivityInSizeCompat=" + topActivityInSizeCompat
                + " locusId= " + mTopActivityLocusId
                + "}";
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ interface IStatusBarService
            in int notificationLocation, boolean modifiedBeforeSending);
    void onNotificationSettingsViewed(String key);
    void onNotificationBubbleChanged(String key, boolean isBubble, int flags);
    void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
    void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, boolean isBubbleSuppressed);
    void hideCurrentInputMethodForBubbles();
    void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
    void clearInlineReplyUriPermissions(String key);
+80 −0
Original line number Diff line number Diff line
@@ -28,10 +28,13 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
import android.content.Context;
import android.content.LocusId;
import android.os.Binder;
import android.os.IBinder;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
@@ -50,6 +53,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * Unified task organizer for all components in the shell.
@@ -95,6 +99,17 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        default void dump(@NonNull PrintWriter pw, String prefix) {};
    }

    /**
     * Callbacks for events on a task with a locus id.
     */
    public interface LocusIdListener {
        /**
         * Notifies when a task with a locusId becomes visible, when a visible task's locusId
         * changes, or if a previously visible task with a locusId becomes invisible.
         */
        void onVisibilityChanged(int taskId, LocusId locus, boolean visible);
    }

    /**
     * Keys map from either a task id or {@link TaskListenerType}.
     * @see #addListenerForTaskId
@@ -109,6 +124,13 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    /** @see #setPendingLaunchCookieListener */
    private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();

    // Keeps track of taskId's with visible locusIds. Used to notify any {@link LocusIdListener}s
    // that might be set.
    private final SparseArray<LocusId> mVisibleTasksWithLocusId = new SparseArray<>();

    /** @see #addLocusIdListener */
    private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>();

    private final Object mLock = new Object();
    private StartingSurface mStartingSurface;

@@ -257,6 +279,28 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        }
    }

    /**
     * Adds a listener to be notified for {@link LocusId} visibility changes.
     */
    public void addLocusIdListener(LocusIdListener listener) {
        synchronized (mLock) {
            mLocusIdListeners.add(listener);
            for (int i = 0; i < mVisibleTasksWithLocusId.size(); i++) {
                listener.onVisibilityChanged(mVisibleTasksWithLocusId.keyAt(i),
                        mVisibleTasksWithLocusId.valueAt(i), true /* visible */);
            }
        }
    }

    /**
     * Removes listener.
     */
    public void removeLocusIdListener(LocusIdListener listener) {
        synchronized (mLock) {
            mLocusIdListeners.remove(listener);
        }
    }

    @Override
    public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
        if (mStartingSurface != null) {
@@ -294,6 +338,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        if (listener != null) {
            listener.onTaskAppeared(info.getTaskInfo(), info.getLeash());
        }
        notifyLocusVisibilityIfNeeded(info.getTaskInfo());
        notifySizeCompatUI(info.getTaskInfo(), listener);
    }

@@ -310,6 +355,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            if (!updated && newListener != null) {
                newListener.onTaskInfoChanged(taskInfo);
            }
            notifyLocusVisibilityIfNeeded(taskInfo);
            if (updated || !taskInfo.equalsForSizeCompat(data.getTaskInfo())) {
                // Notify the size compat UI if the listener or task info changed.
                notifySizeCompatUI(taskInfo, newListener);
@@ -338,6 +384,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            if (listener != null) {
                listener.onTaskVanished(taskInfo);
            }
            notifyLocusVisibilityIfNeeded(taskInfo);
            // Pass null for listener to remove the size compat UI on this task if there is any.
            notifySizeCompatUI(taskInfo, null /* taskListener */);
        }
@@ -366,6 +413,39 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        return true;
    }

    private void notifyLocusVisibilityIfNeeded(TaskInfo taskInfo) {
        final int taskId = taskInfo.taskId;
        final LocusId prevLocus = mVisibleTasksWithLocusId.get(taskId);
        final boolean sameLocus = Objects.equals(prevLocus, taskInfo.mTopActivityLocusId);
        if (prevLocus == null) {
            // New visible locus
            if (taskInfo.mTopActivityLocusId != null && taskInfo.isVisible) {
                mVisibleTasksWithLocusId.put(taskId, taskInfo.mTopActivityLocusId);
                notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, true /* visible */);
            }
        } else if (sameLocus && !taskInfo.isVisible) {
            // Hidden locus
            mVisibleTasksWithLocusId.remove(taskId);
            notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, false /* visible */);
        } else if (!sameLocus) {
            // Changed locus
            if (taskInfo.isVisible) {
                mVisibleTasksWithLocusId.put(taskId, taskInfo.mTopActivityLocusId);
                notifyLocusIdChange(taskId, prevLocus, false /* visible */);
                notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, true /* visible */);
            } else {
                mVisibleTasksWithLocusId.remove(taskInfo.taskId);
                notifyLocusIdChange(taskId, prevLocus, false /* visible */);
            }
        }
    }

    private void notifyLocusIdChange(int taskId, LocusId locus, boolean visible) {
        for (int i = 0; i < mLocusIdListeners.size(); i++) {
            mLocusIdListeners.valueAt(i).onVisibilityChanged(taskId, locus, visible);
        }
    }

    /**
     * Notifies {@link SizeCompatUIController} about the size compat info changed on the give Task
     * to update the UI accordingly.
Loading