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

Commit 43d432da authored by Matías Hernández's avatar Matías Hernández Committed by Android (Google) Code Review
Browse files

Merge "Propagate channel updates to their conversation children" into udc-qpr-dev

parents 4eea1e37 5c8c7cbc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -89,6 +89,9 @@ public class SystemUiSystemPropertiesFlags {
        /** Gating storing NotificationRankingUpdate ranking map in shared memory. */
        public static final Flag RANKING_UPDATE_ASHMEM = devFlag(
                "persist.sysui.notification.ranking_update_ashmem");

        public static final Flag PROPAGATE_CHANNEL_UPDATES_TO_CONVERSATIONS = devFlag(
                "persist.sysui.notification.propagate_channel_updates_to_conversations");
    }

    //// == End of flags.  Everything below this line is the implementation. == ////
+111 −5
Original line number Diff line number Diff line
@@ -30,9 +30,9 @@ import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;

import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -164,6 +164,9 @@ public class PreferencesHelper implements RankingConfig {
    static final int DEFAULT_BUBBLE_PREFERENCE = BUBBLE_PREFERENCE_NONE;
    static final boolean DEFAULT_MEDIA_NOTIFICATION_FILTERING = true;

    private static final int NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_APP = 0;
    private static final int NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_USER = 1;

    /**
     * Default value for what fields are user locked. See {@link LockableAppFields} for all lockable
     * fields.
@@ -1110,12 +1113,20 @@ public class PreferencesHelper implements RankingConfig {
            if (!channel.equals(updatedChannel)) {
                // only log if there are real changes
                MetricsLogger.action(getChannelLog(updatedChannel, pkg)
                        .setSubtype(fromUser ? 1 : 0));
                        .setSubtype(fromUser ? NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_USER
                                : NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_APP));
                mNotificationChannelLogger.logNotificationChannelModified(updatedChannel, uid, pkg,
                        NotificationChannelLogger.getLoggingImportance(channel), fromUser);
                changed = true;
            }

            if (fromUser && SystemUiSystemPropertiesFlags.getResolver().isEnabled(
                    NotificationFlags.PROPAGATE_CHANNEL_UPDATES_TO_CONVERSATIONS)) {
                updateChildrenConversationChannels(r, channel, updatedChannel);
                // No need to update changed or needsDndChanged as the child channel(s) cannot be
                // relevantly affected without the parent channel already having been.
            }

            if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
                    || channel.getImportance() != updatedChannel.getImportance()) {
                needsDndChange = true;
@@ -1130,6 +1141,101 @@ public class PreferencesHelper implements RankingConfig {
        }
    }

    /**
     * Updates conversation channels after user changes to their parent channel. See
     * {@link #maybeUpdateChildConversationChannel}.
     */
    @GuardedBy("mPackagePreferences")
    private void updateChildrenConversationChannels(@NonNull PackagePreferences packagePreferences,
            @NonNull NotificationChannel oldParent, @NonNull NotificationChannel updatedParent) {
        if (oldParent.equals(updatedParent)) {
            return;
        }
        if (oldParent.isConversation()) {
            return; // Can't have children.
        }
        for (NotificationChannel channel : packagePreferences.channels.values()) {
            // Include deleted -- otherwise they will have old settings if later resurrected.
            // Include demoted -- still attached to their parents.
            if (channel.isConversation()
                    && oldParent.getId().equals(channel.getParentChannelId())) {
                maybeUpdateChildConversationChannel(packagePreferences.pkg, packagePreferences.uid,
                        channel, oldParent, updatedParent);
            }
        }
    }

    /**
     * Apply the diff between {@code oldParent} and {@code updatedParent} to the child
     * {@code conversation} channel. Only fields that are not locked on the conversation channel
     * (see {@link NotificationChannel#LOCKABLE_FIELDS }) will be updated (so that we don't override
     * previous explicit user choices).
     *
     * <p>This will also log the change as if it was {@code fromUser=true}.
     */
    @GuardedBy("mPackagePreferences")
    private void maybeUpdateChildConversationChannel(String pkg, int uid,
            @NonNull NotificationChannel conversation, @NonNull NotificationChannel oldParent,
            @NonNull NotificationChannel updatedParent) {
        boolean changed = false;
        int oldLoggingImportance = NotificationChannelLogger.getLoggingImportance(conversation);

        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_PRIORITY) == 0
                && oldParent.canBypassDnd() != updatedParent.canBypassDnd()) {
            conversation.setBypassDnd(updatedParent.canBypassDnd());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_VISIBILITY) == 0
                && oldParent.getLockscreenVisibility()
                != updatedParent.getLockscreenVisibility()) {
            conversation.setLockscreenVisibility(updatedParent.getLockscreenVisibility());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
                && oldParent.getImportance() != updatedParent.getImportance()) {
            conversation.setImportance(updatedParent.getImportance());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_LIGHTS) == 0
                && (oldParent.shouldShowLights() != updatedParent.shouldShowLights()
                || oldParent.getLightColor() != updatedParent.getLightColor())) {
            conversation.enableLights(updatedParent.shouldShowLights());
            conversation.setLightColor(updatedParent.getLightColor());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) == 0
                && !Objects.equals(oldParent.getSound(), updatedParent.getSound())) {
            conversation.setSound(updatedParent.getSound(), updatedParent.getAudioAttributes());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_VIBRATION) == 0
                && (!Arrays.equals(oldParent.getVibrationPattern(),
                updatedParent.getVibrationPattern())
                || oldParent.shouldVibrate() != updatedParent.shouldVibrate())) {
            // enableVibration must be 2nd because setVibrationPattern may toggle it.
            conversation.setVibrationPattern(updatedParent.getVibrationPattern());
            conversation.enableVibration(updatedParent.shouldVibrate());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_SHOW_BADGE) == 0
                && oldParent.canShowBadge() != updatedParent.canShowBadge()) {
            conversation.setShowBadge(updatedParent.canShowBadge());
            changed = true;
        }
        if ((conversation.getUserLockedFields() & NotificationChannel.USER_LOCKED_ALLOW_BUBBLE) == 0
                && oldParent.getAllowBubbles() != updatedParent.getAllowBubbles()) {
            conversation.setAllowBubbles(updatedParent.getAllowBubbles());
            changed = true;
        }

        if (changed) {
            MetricsLogger.action(getChannelLog(conversation, pkg).setSubtype(
                    NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_USER));
            mNotificationChannelLogger.logNotificationChannelModified(conversation, uid, pkg,
                    oldLoggingImportance, /* fromUser= */ true);
        }
    }

    @Override
    public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
            boolean includeDeleted) {
@@ -1838,8 +1944,8 @@ public class PreferencesHelper implements RankingConfig {
        }
    }

    @VisibleForTesting
    void lockFieldsForUpdateLocked(NotificationChannel original, NotificationChannel update) {
    private void lockFieldsForUpdateLocked(NotificationChannel original,
            NotificationChannel update) {
        if (original.canBypassDnd() != update.canBypassDnd()) {
            update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
        }
+32 −8
Original line number Diff line number Diff line
@@ -16,24 +16,44 @@

package com.android.server.notification;

import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;

import com.google.common.base.MoreObjects;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class NotificationChannelLoggerFake implements NotificationChannelLogger {
    static class CallRecord {
        public NotificationChannelEvent event;
        CallRecord(NotificationChannelEvent event) {
        public final NotificationChannelEvent event;
        @Nullable public final String channelId;

        CallRecord(NotificationChannelEvent event, @Nullable String channelId) {
            this.event = event;
            this.channelId = channelId;
        }

        @Override
        public String toString() {
            return "CallRecord{" +
                    "event=" + event +
                    '}';
            return MoreObjects.toStringHelper(this)
                    .add("event", event)
                    .add(channelId, channelId)
                    .toString();
        }

        @Override
        public boolean equals(Object obj) {
            return (obj instanceof CallRecord other)
                    && Objects.equals(this.event, other.event)
                    && Objects.equals(this.channelId, other.channelId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(event, channelId);
        }
    }

@@ -47,20 +67,24 @@ public class NotificationChannelLoggerFake implements NotificationChannelLogger
        return mCalls.get(index);
    }

    void clear() {
        mCalls.clear();
    }

    @Override
    public void logNotificationChannel(NotificationChannelEvent event, NotificationChannel channel,
            int uid, String pkg, int oldImportance, int newImportance) {
        mCalls.add(new CallRecord(event));
        mCalls.add(new CallRecord(event, channel.getId()));
    }

    @Override
    public void logNotificationChannelGroup(NotificationChannelEvent event,
            NotificationChannelGroup channelGroup, int uid, String pkg, boolean wasBlocked) {
        mCalls.add(new CallRecord(event));
        mCalls.add(new CallRecord(event, channelGroup.getId()));
    }

    @Override
    public void logAppEvent(NotificationChannelEvent event, int uid, String pkg) {
        mCalls.add(new CallRecord(event));
        mCalls.add(new CallRecord(event, null));
    }
}
+313 −55

File changed.

Preview size limit exceeded, changes collapsed.

+3 −1
Original line number Diff line number Diff line
@@ -27,7 +27,9 @@ public class TestableFlagResolver implements SystemUiSystemPropertiesFlags.FlagR
        return mOverrides.getOrDefault(flag.mSysPropKey, flag.mDefaultValue);
    }

    public void setFlagOverride(SystemUiSystemPropertiesFlags.Flag flag, boolean isEnabled) {
    public TestableFlagResolver setFlagOverride(SystemUiSystemPropertiesFlags.Flag flag,
            boolean isEnabled) {
        mOverrides.put(flag.mSysPropKey, isEnabled);
        return this;
    }
}