Merge "Add audio attributes to notificationchannel"
diff --git a/api/current.txt b/api/current.txt
index c7fcc26..805586e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5423,6 +5423,7 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
     method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
@@ -5436,7 +5437,7 @@
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
diff --git a/api/system-current.txt b/api/system-current.txt
index 02432f0..64e9571 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5599,6 +5599,7 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
     method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
@@ -5617,7 +5618,7 @@
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5628,6 +5629,7 @@
     field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
     field public static final int[] LOCKABLE_FIELDS;
     field public static final int USER_LOCKED_ALLOWED = 64; // 0x40
+    field public static final int USER_LOCKED_AUDIO_ATTRIBUTES = 256; // 0x100
     field public static final int USER_LOCKED_IMPORTANCE = 4; // 0x4
     field public static final int USER_LOCKED_LIGHTS = 8; // 0x8
     field public static final int USER_LOCKED_PRIORITY = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index b599c1c2..a32300e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5433,6 +5433,7 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
     method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
@@ -5446,7 +5447,7 @@
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 26ec418..58ff496 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -22,6 +22,7 @@
 
 import android.annotation.SystemApi;
 import android.app.NotificationManager;
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -55,8 +56,9 @@
     private static final String ATT_VIBRATION = "vibration";
     private static final String ATT_VIBRATION_ENABLED = "vibration_enabled";
     private static final String ATT_SOUND = "sound";
-    //TODO: add audio attributes support
-    private static final String ATT_AUDIO_ATTRIBUTES = "audio_attributes";
+    private static final String ATT_USAGE = "usage";
+    private static final String ATT_FLAGS = "flags";
+    private static final String ATT_CONTENT_TYPE = "content_type";
     private static final String ATT_SHOW_BADGE = "show_badge";
     private static final String ATT_USER_LOCKED = "locked";
     private static final String ATT_GROUP = "group";
@@ -109,6 +111,12 @@
      * @hide
      */
     @SystemApi
+    public static final int USER_LOCKED_AUDIO_ATTRIBUTES = 0x00000100;
+
+    /**
+     * @hide
+     */
+    @SystemApi
     public static final int[] LOCKABLE_FIELDS = new int[] {
             USER_LOCKED_PRIORITY,
             USER_LOCKED_VISIBILITY,
@@ -117,7 +125,8 @@
             USER_LOCKED_VIBRATION,
             USER_LOCKED_SOUND,
             USER_LOCKED_ALLOWED,
-            USER_LOCKED_SHOW_BADGE
+            USER_LOCKED_SHOW_BADGE,
+            USER_LOCKED_AUDIO_ATTRIBUTES
     };
 
 
@@ -141,6 +150,7 @@
     private boolean mShowBadge = DEFAULT_SHOW_BADGE;
     private boolean mDeleted = DEFAULT_DELETED;
     private String mGroup;
+    private AudioAttributes mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
 
     /**
      * Creates a notification channel.
@@ -183,6 +193,7 @@
         } else {
             mGroup = null;
         }
+        mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null;
     }
 
     @Override
@@ -215,6 +226,12 @@
         } else {
             dest.writeByte((byte) 0);
         }
+        if (mAudioAttributes != null) {
+            dest.writeInt(1);
+            mAudioAttributes.writeToParcel(dest, 0);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     /**
@@ -275,6 +292,9 @@
      *
      * Group information is only used for presentation, not for behavior.
      *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
+     *
      * @param groupId the id of a group created by
      * {@link NotificationManager#createNotificationChannelGroup(NotificationChannelGroup)}.
      */
@@ -293,18 +313,23 @@
     }
 
     /**
-     * Sets the sound that should be played for notifications posted to this channel if
-     * the notifications don't supply a sound. Only modifiable before the channel is submitted
-     * to the NotificationManager.
+     * Sets the sound that should be played for notifications posted to this channel and its
+     * audio attributes.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
-    public void setSound(Uri sound) {
+    public void setSound(Uri sound, AudioAttributes audioAttributes) {
         this.mSound = sound;
+        this.mAudioAttributes = audioAttributes;
     }
 
     /**
      * Sets whether notifications posted to this channel should display notification lights,
-     * on devices that support that feature. Only modifiable before the channel is submitted to
-     * the NotificationManager.
+     * on devices that support that feature.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void setLights(boolean lights) {
         this.mLights = lights;
@@ -312,16 +337,20 @@
 
     /**
      * Sets whether notification posted to this channel should vibrate. The vibration pattern can
-     * be set with {@link #setVibrationPattern(long[])}. Only modifiable before the channel is
-     * submitted to the NotificationManager.
+     * be set with {@link #setVibrationPattern(long[])}.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void enableVibration(boolean vibration) {
         this.mVibrationEnabled = vibration;
     }
 
     /**
-     * Sets whether notification posted to this channel should vibrate. Only modifiable before the
-     * channel is submitted to the NotificationManager.
+     * Sets whether notification posted to this channel should vibrate.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void setVibrationPattern(long[] vibrationPattern) {
         this.mVibration = vibrationPattern;
@@ -365,6 +394,13 @@
     }
 
     /**
+     * Returns the audio attributes for sound played by notifications posted to this channel.
+     */
+    public AudioAttributes getAudioAttributes() {
+        return mAudioAttributes;
+    }
+
+    /**
      * Returns whether notifications posted to this channel trigger notification lights.
      */
     public boolean shouldShowLights() {
@@ -438,7 +474,7 @@
         setBypassDnd(Notification.PRIORITY_DEFAULT
                 != safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT));
         setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
-        setSound(safeUri(parser, ATT_SOUND));
+        setSound(safeUri(parser, ATT_SOUND), safeAudioAttributes(parser));
         setLights(safeBool(parser, ATT_LIGHTS, false));
         enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
         setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
@@ -471,6 +507,12 @@
         if (getSound() != null) {
             out.attribute(null, ATT_SOUND, getSound().toString());
         }
+        if (getAudioAttributes() != null) {
+            out.attribute(null, ATT_USAGE, Integer.toString(getAudioAttributes().getUsage()));
+            out.attribute(null, ATT_CONTENT_TYPE,
+                    Integer.toString(getAudioAttributes().getContentType()));
+            out.attribute(null, ATT_FLAGS, Integer.toString(getAudioAttributes().getFlags()));
+        }
         if (shouldShowLights()) {
             out.attribute(null, ATT_LIGHTS, Boolean.toString(shouldShowLights()));
         }
@@ -517,6 +559,12 @@
         if (getSound() != null) {
             record.put(ATT_SOUND, getSound().toString());
         }
+        if (getAudioAttributes() != null) {
+            record.put(ATT_USAGE, Integer.toString(getAudioAttributes().getUsage()));
+            record.put(ATT_CONTENT_TYPE,
+                    Integer.toString(getAudioAttributes().getContentType()));
+            record.put(ATT_FLAGS, Integer.toString(getAudioAttributes().getFlags()));
+        }
         record.put(ATT_LIGHTS, Boolean.toString(shouldShowLights()));
         record.put(ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
         record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
@@ -527,6 +575,18 @@
         return record;
     }
 
+    private static AudioAttributes safeAudioAttributes(XmlPullParser parser) {
+        int usage = safeInt(parser, ATT_USAGE, AudioAttributes.USAGE_NOTIFICATION);
+        int contentType = safeInt(parser, ATT_CONTENT_TYPE,
+                AudioAttributes.CONTENT_TYPE_SONIFICATION);
+        int flags = safeInt(parser, ATT_FLAGS, 0);
+        return new AudioAttributes.Builder()
+                .setUsage(usage)
+                .setContentType(contentType)
+                .setFlags(flags)
+                .build();
+    }
+
     private static Uri safeUri(XmlPullParser parser, String att) {
         final String val = parser.getAttributeValue(null, att);
         return val == null ? null : Uri.parse(val);
@@ -618,7 +678,11 @@
             return false;
         }
         if (!Arrays.equals(mVibration, that.mVibration)) return false;
-        return getGroup() != null ? getGroup().equals(that.getGroup()) : that.getGroup() == null;
+        if (getGroup() != null ? !getGroup().equals(that.getGroup()) : that.getGroup() != null) {
+            return false;
+        }
+        return getAudioAttributes() != null ? getAudioAttributes().equals(that.getAudioAttributes())
+                : that.getAudioAttributes() == null;
 
     }
 
@@ -637,6 +701,7 @@
         result = 31 * result + (mShowBadge ? 1 : 0);
         result = 31 * result + (isDeleted() ? 1 : 0);
         result = 31 * result + (getGroup() != null ? getGroup().hashCode() : 0);
+        result = 31 * result + (getAudioAttributes() != null ? getAudioAttributes().hashCode() : 0);
         return result;
     }
 
@@ -656,6 +721,7 @@
                 ", mShowBadge=" + mShowBadge +
                 ", mDeleted=" + mDeleted +
                 ", mGroup='" + mGroup + '\'' +
+                ", mAudioAttributes=" + mAudioAttributes +
                 '}';
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 5739693..ed2da68 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -205,18 +205,26 @@
 
     private AudioAttributes calculateAttributes() {
         final Notification n = sbn.getNotification();
-        AudioAttributes attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+        AudioAttributes attributes = getChannel().getAudioAttributes();
+        if (attributes == null) {
+            attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+        }
 
-        if (n.audioAttributes != null) {
-            // prefer audio attributes to stream type
-            attributes = n.audioAttributes;
-        } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
-            // the stream type is valid, use it
-            attributes = new AudioAttributes.Builder()
-                    .setInternalLegacyStreamType(n.audioStreamType)
-                    .build();
-        } else if (n.audioStreamType != AudioSystem.STREAM_DEFAULT) {
-            Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+        if (mPreChannelsNotification
+                && (getChannel().getUserLockedFields()
+                & NotificationChannel.USER_LOCKED_SOUND) == 0) {
+            if (n.audioAttributes != null) {
+                // prefer audio attributes to stream type
+                attributes = n.audioAttributes;
+            } else if (n.audioStreamType >= 0
+                    && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
+                // the stream type is valid, use it
+                attributes = new AudioAttributes.Builder()
+                        .setInternalLegacyStreamType(n.audioStreamType)
+                        .build();
+            } else if (n.audioStreamType != AudioSystem.STREAM_DEFAULT) {
+                Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+            }
         }
         return attributes;
     }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 5b6ac69..8176e5d 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -569,7 +569,7 @@
             channel.setBypassDnd(updatedChannel.canBypassDnd());
         }
         if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) == 0) {
-            channel.setSound(updatedChannel.getSound());
+            channel.setSound(updatedChannel.getSound(), updatedChannel.getAudioAttributes());
         }
         if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
             channel.enableVibration(updatedChannel.shouldVibrate());
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 468a26b..b8655607 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -85,6 +85,10 @@
             300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
             300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
     private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI;
+    private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder()
+            .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+            .build();
     private static final int CUSTOM_LIGHT_COLOR = Color.BLACK;
     private static final int CUSTOM_LIGHT_ON = 10000;
     private static final int CUSTOM_LIGHT_OFF = 10000;
@@ -200,10 +204,11 @@
         if (noisy) {
             if (defaultSound) {
                 defaults |= Notification.DEFAULT_SOUND;
-                channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
+                channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                        Notification.AUDIO_ATTRIBUTES_DEFAULT);
             } else {
                 builder.setSound(CUSTOM_SOUND);
-                channel.setSound(CUSTOM_SOUND);
+                channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
         }
         if (buzzy) {
@@ -521,6 +526,8 @@
 
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(FALLBACK_VIBRATION),
                 eq(-1), (AudioAttributes) anyObject());
+        verify(mRingtonePlayer, never()).playAsync
+                (anyObject(), anyObject(), anyBoolean(), anyObject());
     }
 
     @Test
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 15dcc26..2ab1f30 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -118,6 +118,7 @@
                 defaults |= Notification.DEFAULT_SOUND;
             } else {
                 builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
+                channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
         }
         if (buzzy) {
@@ -150,29 +151,31 @@
 
     @Test
     public void testSound_default_preUpgradeUsesNotification() throws Exception {
-        defaultChannel.setSound(null);
+        defaultChannel.setSound(null, null);
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
+        assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_custom_preUpgradeUsesNotification() throws Exception {
-        defaultChannel.setSound(null);
+        defaultChannel.setSound(null, null);
         // pre upgrade, custom sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_default_userLocked_preUpgrade() throws Exception {
-        defaultChannel.setSound(CUSTOM_SOUND);
+        defaultChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
@@ -180,17 +183,19 @@
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_default_upgradeUsesChannel() throws Exception {
-        channel.setSound(CUSTOM_SOUND);
+        channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         // post upgrade, default sound.
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
@@ -239,28 +244,6 @@
     }
 
     @Test
-    public void testAudioAttributes_preUpgrade() throws Exception {
-        defaultChannel.setSound(null);
-        // pre upgrade, default sound.
-        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
-                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
-
-        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
-        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
-    }
-
-    @Test
-    public void testAudioAttributes_upgrade() throws Exception {
-        channel.setSound(null);
-        // post upgrade, default sound.
-        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
-                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
-
-        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
-        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
-    }
-
-    @Test
     public void testImportance_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index b53ec45..9fa46d1 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -36,6 +36,7 @@
 import android.app.NotificationManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -66,9 +67,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RankingHelperTest {
-    @Mock NotificationUsageStats mUsageStats;
-    @Mock RankingHandler handler;
-    @Mock PackageManager mPm;
+    @Mock
+    NotificationUsageStats mUsageStats;
+    @Mock
+    RankingHandler handler;
+    @Mock
+    PackageManager mPm;
 
     private Notification mNotiGroupGSortA;
     private Notification mNotiGroupGSortB;
@@ -85,6 +89,7 @@
     private final int uid = 0;
     private final String pkg2 = "pkg2";
     private final int uid2 = 1111111;
+    private AudioAttributes mAudioAttributes;
 
     private Context getContext() {
         return InstrumentationRegistry.getTargetContext();
@@ -96,7 +101,7 @@
         UserHandle user = UserHandle.ALL;
 
         mHelper = new RankingHelper(getContext(), mPm, handler, mUsageStats,
-                new String[] {ImportanceExtractor.class.getName()});
+                new String[]{ImportanceExtractor.class.getName()});
 
         mNotiGroupGSortA = new Notification.Builder(getContext())
                 .setContentTitle("A")
@@ -143,6 +148,12 @@
                 "package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
+        mAudioAttributes = new AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+                .build();
+
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         final ApplicationInfo upgrade = new ApplicationInfo();
@@ -150,7 +161,8 @@
         try {
             when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
             when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
-        } catch (PackageManager.NameNotFoundException e) {}
+        } catch (PackageManager.NameNotFoundException e) {
+        }
     }
 
     private NotificationChannel getDefaultChannel() {
@@ -187,6 +199,7 @@
         assertEquals(expected.canBypassDnd(), actual.canBypassDnd());
         assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
         assertEquals(expected.getGroup(), actual.getGroup());
+        assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
     }
 
     @Test
@@ -246,13 +259,13 @@
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         NotificationChannel channel2 =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel2.setSound(new Uri.Builder().scheme("test").build());
+        channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel2.setLights(true);
         channel2.setBypassDnd(true);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel2.enableVibration(true);
         channel2.setGroup(ncg.getId());
-        channel2.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
 
         mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
@@ -304,13 +317,13 @@
                 pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
         assertFalse(updated.canBypassDnd());
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility());
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility());
         assertEquals(0, updated.getUserLockedFields());
     }
 
     @Test
     public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
-         NotificationChannel channel1 =
+        NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
 
@@ -335,15 +348,16 @@
     @Test
     public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
         final String preupgradeXml = "<ranking version=\"1\">\n"
-             + "<package name=\"" + pkg + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
-            + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
-            + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + uid + "\" />\n"
-            + "<package name=\"" + pkg2 + "\" uid=\"" + uid2 + "\" visibility=\""
-            + Notification.VISIBILITY_PRIVATE + "\" />\n"
-            + "</ranking>";
+                + "<package name=\"" + pkg + "\" importance=\""
+                + NotificationManager.IMPORTANCE_HIGH
+                + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
+                + Notification.VISIBILITY_SECRET + "\"" + " uid=\"" + uid + "\" />\n"
+                + "<package name=\"" + pkg2 + "\" uid=\"" + uid2 + "\" visibility=\""
+                + Notification.VISIBILITY_PRIVATE + "\" />\n"
+                + "</ranking>";
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
-            null);
+                null);
         parser.nextTag();
         mHelper.readXml(parser, false);
 
@@ -353,8 +367,8 @@
         assertTrue(updated1.canBypassDnd());
         assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
         assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
-            | NotificationChannel.USER_LOCKED_PRIORITY
-            | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
+                | NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
 
         final NotificationChannel updated2 = mHelper.getNotificationChannel(
                 pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false);
@@ -382,14 +396,14 @@
     public void testUpdate_userLockedImportance() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
 
         mHelper.createNotificationChannel(pkg, uid, channel, false);
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -401,7 +415,7 @@
     public void testUpdate_userLockedVisibility() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
 
@@ -409,7 +423,7 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -422,7 +436,7 @@
     public void testUpdate_userLockedVibration() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLights(false);
         channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
 
@@ -430,9 +444,9 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.enableVibration(true);
-        channel2.setVibrationPattern(new long[] {100});
+        channel2.setVibrationPattern(new long[]{100});
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -444,7 +458,7 @@
     public void testUpdate_userLockedLights() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLights(false);
         channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
 
@@ -452,7 +466,7 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setLights(true);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -465,7 +479,7 @@
     public void testUpdate_userLockedPriority() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setBypassDnd(true);
         channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
 
@@ -473,7 +487,7 @@
 
         // same id, try to update all fields
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setBypassDnd(false);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -486,16 +500,16 @@
     public void testUpdate_userLockedRingtone() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
 
         mHelper.createNotificationChannel(pkg, uid, channel, false);
 
         // same id, try to update all fields
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setSound(new Uri.Builder().scheme("test2").build());
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -527,7 +541,7 @@
         // no fields locked by user
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -537,7 +551,7 @@
         // same id, try to update all fields
         final NotificationChannel channel2 =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setSound(new Uri.Builder().scheme("test2").build());
+        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
         channel2.setLights(false);
         channel2.setBypassDnd(false);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
@@ -559,7 +573,7 @@
     public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -586,7 +600,7 @@
     public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -613,12 +627,12 @@
     public void testGetDeletedChannel() throws Exception {
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.enableVibration(true);
-        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
 
         mHelper.createNotificationChannel(pkg, uid, channel, true);
         mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
@@ -639,12 +653,12 @@
         Map<String, NotificationChannel> channelMap = new HashMap<>();
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
         channel.enableVibration(true);
-        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
         channelMap.put(channel.getId(), channel);
         NotificationChannel channel2 =
                 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
@@ -665,7 +679,7 @@
         }
 
         // Returns deleted channels too
-        channels =  mHelper.getNotificationChannels(pkg, uid, true).getList();
+        channels = mHelper.getNotificationChannels(pkg, uid, true).getList();
         assertEquals(3, channels.size());               // Includes default channel
         for (NotificationChannel nc : channels) {
             if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
@@ -682,7 +696,7 @@
 
         mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
 
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         try {
             mHelper.updateNotificationChannel(pkg, uid, channel);
             fail("Updated deleted channel");
@@ -700,7 +714,7 @@
 
     @Test
     public void testCreateDeletedChannel() throws Exception {
-        long[] vibration = new long[] {100, 67, 145, 156};
+        long[] vibration = new long[]{100, 67, 145, 156};
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setVibrationPattern(vibration);
@@ -710,7 +724,7 @@
 
         NotificationChannel newChannel = new NotificationChannel(
                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[] {100});
+        newChannel.setVibrationPattern(new long[]{100});
 
         mHelper.createNotificationChannel(pkg, uid, newChannel, true);
 
@@ -721,7 +735,7 @@
 
     @Test
     public void testCreateChannel_alreadyExists() throws Exception {
-        long[] vibration = new long[] {100, 67, 145, 156};
+        long[] vibration = new long[]{100, 67, 145, 156};
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setVibrationPattern(vibration);
@@ -730,7 +744,7 @@
 
         NotificationChannel newChannel = new NotificationChannel(
                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[] {100});
+        newChannel.setVibrationPattern(new long[]{100});
 
         mHelper.createNotificationChannel(pkg, uid, newChannel, true);
 
@@ -816,7 +830,8 @@
         try {
             mHelper.createNotificationChannel(pkg, uid, channel1, true);
             fail("Created a channel with a bad group");
-        } catch (IllegalArgumentException e) {}
+        } catch (IllegalArgumentException e) {
+        }
     }
 
     @Test
@@ -862,11 +877,11 @@
         List<NotificationChannelGroup> actual =
                 mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
         assertEquals(3, actual.size());
-        for (NotificationChannelGroup group: actual) {
+        for (NotificationChannelGroup group : actual) {
             if (group.getId() == null) {
                 assertEquals(2, group.getChannels().size()); // misc channel too
                 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
-                || channel3.getId().equals(group.getChannels().get(1).getId()));
+                        || channel3.getId().equals(group.getChannels().get(1).getId()));
             } else if (group.getId().equals(ncg.getId())) {
                 assertEquals(2, group.getChannels().size());
                 if (group.getChannels().get(0).getId().equals(channel1.getId())) {