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

Commit 328e26ea authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Restrict AudioAttribute usages for notifications

Only calls can use USAGE_NOTIFICATION_RINGTONE. Only alarms can
use USAGE_ALARMS. No notifications can play on the media stream.

If an app specifies and incorrect usage we will use USAGE_NOTIFICATION
instead.

Test: NotificationChannelExtractorTest
Flag: com.android.server.notification.restrict_audio_attributes_call DEV
Flag: com.android.server.notification.restrict_audio_attributes_alarm
DEV
Flag: com.android.server.notification.restrict_audio_attributes_media
DEV
Bug: 331793339

Change-Id: Iefb5b7225ee0a8a1da694dc76841990a13a34572
parent 167eeea9
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -431,6 +431,40 @@ public final class NotificationChannel implements Parcelable {
        dest.writeBoolean(mImportanceLockedDefaultApp);
    }

    /**
     * @hide
     */
    public NotificationChannel copy() {
        NotificationChannel copy = new NotificationChannel(mId, mName, mImportance);
        copy.setDescription(mDesc);
        copy.setBypassDnd(mBypassDnd);
        copy.setLockscreenVisibility(mLockscreenVisibility);
        copy.setSound(mSound, mAudioAttributes);
        copy.setLightColor(mLightColor);
        copy.enableLights(mLights);
        copy.setVibrationPattern(mVibrationPattern);
        if (Flags.notificationChannelVibrationEffectApi()) {
            copy.setVibrationEffect(mVibrationEffect);
        }
        copy.lockFields(mUserLockedFields);
        copy.setUserVisibleTaskShown(mUserVisibleTaskShown);
        copy.enableVibration(mVibrationEnabled);
        copy.setShowBadge(mShowBadge);
        copy.setDeleted(mDeleted);
        copy.setGroup(mGroup);
        copy.setBlockable(mBlockableSystem);
        copy.setAllowBubbles(mAllowBubbles);
        copy.setOriginalImportance(mOriginalImportance);
        copy.setConversationId(mParentId, mConversationId);
        copy.setDemoted(mDemoted);
        copy.setImportantConversation(mImportantConvo);
        copy.setDeletedTimeMs(mDeletedTime);
        copy.setImportanceLockedByCriticalDeviceFunction(mImportanceLockedDefaultApp);
        copy.setLastNotificationUpdateTimeMs(mLastNotificationUpdateTimeMs);

        return copy;
    }

    /**
     * @hide
     */
+21 −0
Original line number Diff line number Diff line
@@ -89,3 +89,24 @@ flag {
  description: "Changes notification sort order to be by time within a section"
  bug: "330193582"
}

flag {
  name: "restrict_audio_attributes_call"
  namespace: "systemui"
  description: "Only CallStyle notifs can use USAGE_NOTIFICATION_RINGTONE"
  bug: "331793339"
}

flag {
  name: "restrict_audio_attributes_alarm"
  namespace: "systemui"
  description: "Only alarm category notifs can use USAGE_ALARM"
  bug: "331793339"
}

flag {
  name: "restrict_audio_attributes_media"
  namespace: "systemui"
  description: "No notifs can use USAGE_UNKNOWN or USAGE_MEDIA"
  bug: "331793339"
}
 No newline at end of file
+36 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.annotation.FlaggedApi;
import android.content.AttributionSource;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -46,6 +47,7 @@ import android.os.Parcel;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.VibrationEffect;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.MediaStore.Audio.AudioColumns;
@@ -577,6 +579,40 @@ public class NotificationChannelTest {
        assertNull(channel.getVibrationEffect());
    }

    @Test
    @EnableFlags({Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_MEDIA,
            Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_CALL, Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_ALARM})
    public void testCopy() {
        NotificationChannel original = new NotificationChannel("id", "name", 2);
        original.setDescription("desc");
        original.setBypassDnd(true);
        original.setLockscreenVisibility(7);
        original.setSound(Uri.EMPTY, new AudioAttributes.Builder().build());
        original.setLightColor(5);
        original.enableLights(false);
        original.setVibrationPattern(new long[] {1, 9, 3});
        if (Flags.notificationChannelVibrationEffectApi()) {
            original.setVibrationEffect(VibrationEffect.createOneShot(100, 5));
        }
        original.lockFields(9999);
        original.setUserVisibleTaskShown(true);
        original.enableVibration(false);
        original.setShowBadge(true);
        original.setDeleted(false);
        original.setGroup("group");
        original.setBlockable(false);
        original.setAllowBubbles(true);
        original.setOriginalImportance(6);
        original.setConversationId("parent", "convo");
        original.setDemoted(false);
        original.setImportantConversation(true);
        original.setDeletedTimeMs(100);
        original.setImportanceLockedByCriticalDeviceFunction(false);

        NotificationChannel parcelCopy = writeToAndReadFromParcel(original);
        assertThat(original.copy()).isEqualTo(parcelCopy);
    }

    /** Backs up a given channel to an XML, and returns the channel read from the XML. */
    private NotificationChannel backUpAndRestore(NotificationChannel channel) throws Exception {
        TypedXmlSerializer serializer = Xml.newFastSerializer();
+38 −0
Original line number Diff line number Diff line
@@ -15,8 +15,16 @@
*/
package com.android.server.notification;

import static android.app.Flags.restrictAudioAttributesAlarm;
import static android.app.Flags.restrictAudioAttributesCall;
import static android.app.Flags.restrictAudioAttributesMedia;
import static android.app.Notification.CATEGORY_ALARM;
import static android.media.AudioAttributes.USAGE_NOTIFICATION;

import android.app.Notification;
import android.app.NotificationChannel;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Slog;

/**
@@ -50,6 +58,36 @@ public class NotificationChannelExtractor implements NotificationSignalExtractor
                record.getSbn().getShortcutId(), true, false);
        record.updateNotificationChannel(updatedChannel);

        if (restrictAudioAttributesCall() || restrictAudioAttributesAlarm()
                || restrictAudioAttributesMedia()) {
            AudioAttributes attributes = record.getChannel().getAudioAttributes();
            boolean updateAttributes =  false;
            if (restrictAudioAttributesCall()
                    && !record.getNotification().isStyle(Notification.CallStyle.class)
                    && attributes.getUsage() == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
                updateAttributes = true;
            }
            if (restrictAudioAttributesAlarm()
                    && record.getNotification().category != CATEGORY_ALARM
                    && attributes.getUsage() == AudioAttributes.USAGE_ALARM) {
                updateAttributes = true;
            }

            if (restrictAudioAttributesMedia()
                    && (attributes.getUsage() == AudioAttributes.USAGE_UNKNOWN
                    || attributes.getUsage() == AudioAttributes.USAGE_MEDIA)) {
                updateAttributes = true;
            }

            if (updateAttributes) {
                NotificationChannel clone = record.getChannel().copy();
                clone.setSound(clone.getSound(), new AudioAttributes.Builder(attributes)
                        .setUsage(USAGE_NOTIFICATION)
                        .build());
                record.updateNotificationChannel(clone);
            }
        }

        return null;
    }

+8 −0
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.server.notification;

import static android.app.Flags.restrictAudioAttributesAlarm;
import static android.app.Flags.restrictAudioAttributesCall;
import static android.app.Flags.restrictAudioAttributesMedia;
import static android.app.Flags.updateRankingTime;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
@@ -1159,6 +1162,11 @@ public final class NotificationRecord {
            mChannel = channel;
            calculateImportance();
            calculateUserSentiment();
            mVibration = calculateVibration();
            if (restrictAudioAttributesCall() || restrictAudioAttributesAlarm()
                    || restrictAudioAttributesMedia()) {
                mAttributes = channel.getAudioAttributes();
            }
        }
    }

Loading