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

Commit 2e39d7c5 authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes If0fee1fa,I53754d6d into main

* changes:
  Notify listeners when syncing group expansion mgr with the pipeline.
  Make GroupMembershipManager implementation match docs.
parents fcd600c1 2460f6c4
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -39,10 +39,7 @@ class StackCoordinator @Inject internal constructor(

    override fun attach(pipeline: NotifPipeline) {
        pipeline.addOnAfterRenderListListener(::onAfterRenderList)
        // TODO(b/282865576): This has an issue where it makes changes to some groups without
        // notifying listeners. To be fixed in QPR, but for now let's comment it out to avoid the
        // group expansion bug.
        // groupExpansionManagerImpl.attach(pipeline)
        groupExpansionManagerImpl.attach(pipeline)
    }

    fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) =
+37 −3
Original line number Diff line number Diff line
@@ -67,19 +67,30 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl
     * Cleanup entries from mExpandedGroups that no longer exist in the pipeline.
     */
    private final OnBeforeRenderListListener mNotifTracker = (entries) -> {
        if (mExpandedGroups.isEmpty()) {
            return; // nothing to do
        }

        final Set<NotificationEntry> renderingSummaries = new HashSet<>();
        for (ListEntry entry : entries) {
            if (entry instanceof GroupEntry) {
                renderingSummaries.add(entry.getRepresentativeEntry());
            }
        }
        mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup));

        // If a group is in mExpandedGroups but not in the pipeline entries, collapse it.
        final var groupsToRemove = setDifference(mExpandedGroups, renderingSummaries);
        for (NotificationEntry entry : groupsToRemove) {
            setGroupExpanded(entry, false);
        }
    };

    public void attach(NotifPipeline pipeline) {
        if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
            mDumpManager.registerDumpable(this);
            pipeline.addOnBeforeRenderListListener(mNotifTracker);
        }
    }

    @Override
    public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) {
@@ -134,4 +145,27 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl
            listener.onGroupExpansionChange(entry.getRow(), expanded);
        }
    }

    /**
     * Utility method to compute the difference between two sets of NotificationEntry. Unfortunately
     * {@code Sets.difference} from Guava is not available in this codebase.
     */
    @NonNull
    private Set<NotificationEntry> setDifference(Set<NotificationEntry> set1,
            Set<NotificationEntry> set2) {
        if (set1 == null || set1.isEmpty()) {
            return new HashSet<>();
        }
        if (set2 == null || set2.isEmpty()) {
            return new HashSet<>(set1);
        }

        final Set<NotificationEntry> difference = new HashSet<>();
        for (NotificationEntry e : set1) {
            if (!set2.contains(e)) {
                difference.add(e);
            }
        }
        return difference;
    }
}
+9 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar.notification.collection.render;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -31,13 +32,14 @@ public interface GroupMembershipManager {
     * @return whether a given notification is a top level entry or is the summary in a group which
     * has children
     */
    boolean isGroupSummary(NotificationEntry entry);
    boolean isGroupSummary(@NonNull NotificationEntry entry);

    /**
     * Get the summary of a specified status bar notification. For an isolated notification this
     * returns itself.
     */
    NotificationEntry getGroupSummary(NotificationEntry entry);
    @Nullable
    NotificationEntry getGroupSummary(@NonNull NotificationEntry entry);

    /**
     * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary
@@ -46,19 +48,20 @@ public interface GroupMembershipManager {
     * TODO: remove this when migrating to the new pipeline, this is taken care of in the
     * dismissal logic built into NotifCollection
     */
    default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
    @Nullable
    default NotificationEntry getLogicalGroupSummary(@NonNull NotificationEntry entry) {
        return getGroupSummary(entry);
    }

    /**
     * @return whether a given notification is a child in a group
     */
    boolean isChildInGroup(NotificationEntry entry);
    boolean isChildInGroup(@NonNull NotificationEntry entry);

    /**
     * Whether this is the only child in a group
     */
    boolean isOnlyChildInGroup(NotificationEntry entry);
    boolean isOnlyChildInGroup(@NonNull NotificationEntry entry);

    /**
     * Get the children that are in the summary's group, not including those isolated.
@@ -67,5 +70,5 @@ public interface GroupMembershipManager {
     * @return list of the children
     */
    @Nullable
    List<NotificationEntry> getChildren(ListEntry summary);
    List<NotificationEntry> getChildren(@NonNull ListEntry summary);
}
+40 −11
Original line number Diff line number Diff line
@@ -18,40 +18,65 @@ package com.android.systemui.statusbar.notification.collection.render;

import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

import java.util.List;

import javax.inject.Inject;

/**
 * ShadeListBuilder groups notifications from system server. This manager translates
 * ShadeListBuilder's method of grouping to be used within SystemUI.
 */
@SysUISingleton
public class GroupMembershipManagerImpl implements GroupMembershipManager {
    FeatureFlags mFeatureFlags;

    @Inject
    public GroupMembershipManagerImpl(FeatureFlags featureFlags) {
        mFeatureFlags = featureFlags;
    }

    @Override
    public boolean isGroupSummary(NotificationEntry entry) {
    public boolean isGroupSummary(@NonNull NotificationEntry entry) {
        return getGroupSummary(entry) == entry;
    }

    @Nullable
    @Override
    public NotificationEntry getGroupSummary(NotificationEntry entry) {
    public NotificationEntry getGroupSummary(@NonNull NotificationEntry entry) {
        if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
            if (!isChildInGroup(entry)) {
                return entry.getRepresentativeEntry();
            }
        } else {
            if (isEntryTopLevel(entry) || entry.getParent() == null) {
                return null;
            }
        }

        return entry.getParent().getRepresentativeEntry();
    }

    @Override
    public boolean isChildInGroup(NotificationEntry entry) {
    public boolean isChildInGroup(@NonNull NotificationEntry entry) {
        if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
            return !isEntryTopLevel(entry) && entry.getParent() != null;
        } else {
            return !isEntryTopLevel(entry);
        }
    }

    @Override
    public boolean isOnlyChildInGroup(NotificationEntry entry) {
    public boolean isOnlyChildInGroup(@NonNull NotificationEntry entry) {
        if (entry.getParent() == null) {
            return false;
        }
@@ -61,20 +86,24 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager {

    @Nullable
    @Override
    public List<NotificationEntry> getChildren(ListEntry entry) {
    public List<NotificationEntry> getChildren(@NonNull ListEntry entry) {
        if (entry instanceof GroupEntry) {
            return ((GroupEntry) entry).getChildren();
        }

        if (isGroupSummary(entry.getRepresentativeEntry())) {
        NotificationEntry representativeEntry = entry.getRepresentativeEntry();
        if (representativeEntry != null && isGroupSummary(representativeEntry)) {
            // maybe we were actually passed the summary
            return entry.getRepresentativeEntry().getParent().getChildren();
            GroupEntry parent = representativeEntry.getParent();
            if (parent != null) {
                return parent.getChildren();
            }
        }

        return null;
    }

    private boolean isEntryTopLevel(NotificationEntry entry) {
    private boolean isEntryTopLevel(@NonNull NotificationEntry entry) {
        return entry.getParent() == ROOT_ENTRY;
    }
}
+2 −5
Original line number Diff line number Diff line
@@ -167,11 +167,8 @@ public interface NotificationsModule {
    }

    /** Provides an instance of {@link GroupMembershipManager} */
    @SysUISingleton
    @Provides
    static GroupMembershipManager provideGroupMembershipManager() {
        return new GroupMembershipManagerImpl();
    }
    @Binds
    GroupMembershipManager provideGroupMembershipManager(GroupMembershipManagerImpl impl);

    /** Provides an instance of {@link GroupExpansionManager} */
    @Binds
Loading