Merge changes from topic "AudioProductStrategies-API" into qt-dev

* changes:
  Replacing AudioVolumeGroups with List
  Cleaning up SeekBarVolumizer
  Removing name getter from AudioProductStrategy
  Replacing AudioProductStrategies with List
diff --git a/api/system-current.txt b/api/system-current.txt
index 026ce09..efbb079 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3498,8 +3498,8 @@
     method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
     method public void clearAudioServerStateCallback();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
-    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioProductStrategies getAudioProductStrategies();
-    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioVolumeGroups getAudioVolumeGroups();
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
@@ -3678,27 +3678,10 @@
     method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
   }
 
-  public final class AudioProductStrategies implements java.lang.Iterable<android.media.audiopolicy.AudioProductStrategy> android.os.Parcelable {
-    ctor public AudioProductStrategies();
-    method public int describeContents();
-    method @NonNull public android.media.AudioAttributes getAudioAttributesForLegacyStreamType(int);
-    method @NonNull public android.media.AudioAttributes getAudioAttributesForProductStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
-    method @Nullable public android.media.audiopolicy.AudioProductStrategy getById(int);
-    method public int getLegacyStreamTypeForAudioAttributes(@NonNull android.media.AudioAttributes);
-    method @Nullable public android.media.audiopolicy.AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes);
-    method public int getVolumeGroupIdForAttributes(@NonNull android.media.AudioAttributes);
-    method public int getVolumeGroupIdForLegacyStreamType(int);
-    method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
-    method public int size();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategies> CREATOR;
-  }
-
   public final class AudioProductStrategy implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.media.AudioAttributes getAudioAttributes();
     method public int getId();
-    method @NonNull public String name();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR;
   }
@@ -3711,16 +3694,6 @@
     method @NonNull public String name();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroup> CREATOR;
-  }
-
-  public final class AudioVolumeGroups implements java.lang.Iterable<android.media.audiopolicy.AudioVolumeGroup> android.os.Parcelable {
-    ctor public AudioVolumeGroups();
-    method public int describeContents();
-    method @Nullable public android.media.audiopolicy.AudioVolumeGroup getById(int);
-    method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioVolumeGroup> iterator();
-    method public int size();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroups> CREATOR;
     field public static final int DEFAULT_VOLUME_GROUP = -1; // 0xffffffff
   }
 
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 847b8e4..02f9925 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
@@ -27,8 +28,8 @@
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
-import android.media.audiopolicy.AudioProductStrategies;
-import android.media.audiopolicy.AudioVolumeGroups;
+import android.media.audiopolicy.AudioProductStrategy;
+import android.media.audiopolicy.AudioVolumeGroup;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -67,7 +68,6 @@
 
     private static final int MSG_GROUP_VOLUME_CHANGED = 1;
     private final Handler mVolumeHandler = new VolumeHandler();
-    private final AudioProductStrategies mAudioProductStrategies;
     private AudioAttributes mAttributes;
     private int mVolumeGroupId;
 
@@ -161,11 +161,9 @@
         }
         mZenMode = mNotificationManager.getZenMode();
 
-        mAudioProductStrategies = mAudioManager.getAudioProductStrategies();
-        if (mAudioProductStrategies.size() > 0) {
-            mVolumeGroupId = mAudioProductStrategies.getVolumeGroupIdForLegacyStreamType(
-                    mStreamType);
-            mAttributes = mAudioProductStrategies.getAudioAttributesForLegacyStreamType(
+        if (hasAudioProductStrategies()) {
+            mVolumeGroupId = getVolumeGroupIdForLegacyStreamType(mStreamType);
+            mAttributes = getAudioAttributesForLegacyStreamType(
                     mStreamType);
         }
 
@@ -190,6 +188,40 @@
         mDefaultUri = defaultUri;
     }
 
+    private boolean hasAudioProductStrategies() {
+        return AudioManager.getAudioProductStrategies().size() > 0;
+    }
+
+    private int getVolumeGroupIdForLegacyStreamType(int streamType) {
+        for (final AudioProductStrategy productStrategy :
+                AudioManager.getAudioProductStrategies()) {
+            int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType);
+            if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
+                return volumeGroupId;
+            }
+        }
+
+        return AudioManager.getAudioProductStrategies().stream()
+                .map(strategy -> strategy.getVolumeGroupIdForAudioAttributes(
+                        AudioProductStrategy.sDefaultAttributes))
+                .filter(volumeGroupId -> volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP)
+                .findFirst()
+                .orElse(AudioVolumeGroup.DEFAULT_VOLUME_GROUP);
+    }
+
+    private @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) {
+        for (final AudioProductStrategy productStrategy :
+                AudioManager.getAudioProductStrategies()) {
+            AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType);
+            if (aa != null) {
+                return aa;
+            }
+        }
+        return new AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
+    }
+
     private static boolean isNotificationOrRing(int stream) {
         return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
     }
@@ -329,7 +361,7 @@
         postStopSample();
         mContext.getContentResolver().unregisterContentObserver(mVolumeObserver);
         mReceiver.setListening(false);
-        if (mAudioProductStrategies.size() > 0) {
+        if (hasAudioProductStrategies()) {
             unregisterVolumeGroupCb();
         }
         mSeekBar.setOnSeekBarChangeListener(null);
@@ -349,7 +381,7 @@
                 System.getUriFor(System.VOLUME_SETTINGS_INT[mStreamType]),
                 false, mVolumeObserver);
         mReceiver.setListening(true);
-        if (mAudioProductStrategies.size() > 0) {
+        if (hasAudioProductStrategies()) {
             registerVolumeGroupCb();
         }
     }
@@ -507,7 +539,7 @@
             if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
                 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                 int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
-                if (mAudioProductStrategies.size() == 0) {
+                if (hasAudioProductStrategies()) {
                     updateVolumeSlider(streamType, streamValue);
                 }
             } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
@@ -519,13 +551,12 @@
                 }
             } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) {
                 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
-                if (mAudioProductStrategies.size() == 0) {
+                if (hasAudioProductStrategies()) {
                     int streamVolume = mAudioManager.getStreamVolume(streamType);
                     updateVolumeSlider(streamType, streamVolume);
                 } else {
-                    int volumeGroup = mAudioProductStrategies.getVolumeGroupIdForLegacyStreamType(
-                            streamType);
-                    if (volumeGroup != AudioVolumeGroups.DEFAULT_VOLUME_GROUP
+                    int volumeGroup = getVolumeGroupIdForLegacyStreamType(streamType);
+                    if (volumeGroup != AudioVolumeGroup.DEFAULT_VOLUME_GROUP
                             && volumeGroup == mVolumeGroupId) {
                         int streamVolume = mAudioManager.getStreamVolume(streamType);
                         updateVolumeSlider(streamType, streamVolume);
@@ -558,14 +589,14 @@
     }
 
     private void registerVolumeGroupCb() {
-        if (mVolumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+        if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
             mAudioManager.registerVolumeGroupCallback(Runnable::run, mVolumeGroupCallback);
             mLastProgress = mAudioManager.getVolumeIndexForAttributes(mAttributes);
         }
     }
 
     private void unregisterVolumeGroupCb() {
-        if (mVolumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+        if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
             mAudioManager.unregisterVolumeGroupCallback(mVolumeGroupCallback);
         }
     }
@@ -578,7 +609,7 @@
                 case MSG_GROUP_VOLUME_CHANGED:
                     int group = (int) args.arg1;
                     if (mVolumeGroupId != group
-                            || mVolumeGroupId == AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+                            || mVolumeGroupId == AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
                         return;
                     }
                     updateSlider();
diff --git a/core/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp
index 822b74a..17a02b2 100644
--- a/core/jni/android_media_AudioProductStrategies.cpp
+++ b/core/jni/android_media_AudioProductStrategies.cpp
@@ -39,7 +39,7 @@
 using namespace android;
 
 // ----------------------------------------------------------------------------
-static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategies";
+static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategy";
 static const char* const kAudioProductStrategyClassPathName =
         "android/media/audiopolicy/AudioProductStrategy";
 
@@ -194,34 +194,12 @@
     return jStatus;
 }
 
-static jint
-android_media_AudioSystem_getProductStrategyFromAudioAttributes(JNIEnv *env, jobject clazz,
-                                                                jobject jAudioAttributes)
-{
-    JNIAudioAttributeHelper::UniqueAaPtr attributes = JNIAudioAttributeHelper::makeUnique();
-    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env,
-                                                           jAudioAttributes,
-                                                           attributes.get());
-    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
-        return jStatus;
-    }
-    product_strategy_t psId;
-    status_t status = AudioSystem::getProductStrategyFromAudioAttributes(
-                AudioAttributes(*attributes.get()), psId);
-    if (status != NO_ERROR) {
-        return nativeToJavaStatus(status);
-    }
-    return psId;
-}
-
 /*
  * JNI registration.
  */
 static const JNINativeMethod gMethods[] = {
     {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I",
                         (void *)android_media_AudioSystem_listAudioProductStrategies},
-    {"native_get_product_strategies_from_audio_attributes", "(Landroid/media/AudioAttributes;)I",
-                        (void *)android_media_AudioSystem_getProductStrategyFromAudioAttributes},
 };
 
 int register_android_media_AudioProductStrategies(JNIEnv *env)
diff --git a/core/jni/android_media_AudioVolumeGroups.cpp b/core/jni/android_media_AudioVolumeGroups.cpp
index 64f0c1e..7098451 100644
--- a/core/jni/android_media_AudioVolumeGroups.cpp
+++ b/core/jni/android_media_AudioVolumeGroups.cpp
@@ -39,7 +39,7 @@
 using namespace android;
 
 // ----------------------------------------------------------------------------
-static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroups";
+static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroup";
 static const char* const kAudioVolumeGroupClassPathName =
         "android/media/audiopolicy/AudioVolumeGroup";
 
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 9d4bce7..d864096 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -20,7 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
-import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioProductStrategy;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -783,9 +783,10 @@
          */
         @UnsupportedAppUsage
         public Builder setInternalLegacyStreamType(int streamType) {
-            final AudioProductStrategies ps = new AudioProductStrategies();
-            if (ps.size() > 0) {
-                AudioAttributes attributes = ps.getAudioAttributesForLegacyStreamType(streamType);
+            if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
+                AudioAttributes attributes =
+                        AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
+                                streamType);
                 if (attributes != null) {
                     return new Builder(attributes);
                 }
@@ -1165,9 +1166,8 @@
                     AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
         }
 
-        final AudioProductStrategies ps = new AudioProductStrategies();
-        if (ps.size() > 0) {
-            return ps.getLegacyStreamTypeForAudioAttributes(aa);
+        if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
+            return AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(aa);
         }
         // usage to stream type mapping
         switch (aa.getUsage()) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a5a4092..d5eee63 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -37,9 +37,9 @@
 import android.content.Intent;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
-import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioProductStrategy;
+import android.media.audiopolicy.AudioVolumeGroup;
 import android.media.audiopolicy.AudioVolumeGroupChangeHandler;
-import android.media.audiopolicy.AudioVolumeGroups;
 import android.media.projection.MediaProjection;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
@@ -5406,8 +5406,9 @@
      *         {@see android.media.audiopolicy.AudioProductStrategy} objects.
      */
     @SystemApi
+    @NonNull
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
-    public @NonNull AudioProductStrategies getAudioProductStrategies() {
+    public static List<AudioProductStrategy> getAudioProductStrategies() {
         final IAudioService service = getService();
         try {
             return service.getAudioProductStrategies();
@@ -5421,15 +5422,16 @@
      * Introspection API to retrieve audio volume groups.
      * When implementing {Car|Oem}AudioManager, use this method  to retrieve the collection of
      * audio volume groups.
-     * @return a (possibly zero-length) array of
-     *         {@see android.media.audiopolicy.AudioVolumeGroups} objects.
+     * @return a (possibly zero-length) List of
+     *         {@see android.media.audiopolicy.AudioVolumeGroup} objects.
      */
     @SystemApi
+    @NonNull
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
-    public @NonNull AudioVolumeGroups getAudioVolumeGroups() {
+    public static List<AudioVolumeGroup> getAudioVolumeGroups() {
         final IAudioService service = getService();
         try {
-            return service.listAudioVolumeGroups();
+            return service.getAudioVolumeGroups();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 980cb04..eddbee4 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -33,8 +33,8 @@
 import android.media.PlayerBase;
 import android.media.VolumePolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
-import android.media.audiopolicy.AudioProductStrategies;
-import android.media.audiopolicy.AudioVolumeGroups;
+import android.media.audiopolicy.AudioProductStrategy;
+import android.media.audiopolicy.AudioVolumeGroup;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 import android.net.Uri;
@@ -86,7 +86,7 @@
     @UnsupportedAppUsage
     int getStreamMaxVolume(int streamType);
 
-    AudioVolumeGroups listAudioVolumeGroups();
+    List<AudioVolumeGroup> getAudioVolumeGroups();
 
     void setVolumeIndexForAttributes(in AudioAttributes aa, int index, int flags, String callingPackage);
 
@@ -98,7 +98,7 @@
 
     int getLastAudibleStreamVolume(int streamType);
 
-    AudioProductStrategies getAudioProductStrategies();
+    List<AudioProductStrategy> getAudioProductStrategies();
 
     void setMicrophoneMute(boolean on, String callingPackage, int userId);
 
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.aidl b/media/java/android/media/audiopolicy/AudioProductStrategies.aidl
deleted file mode 100644
index bec11bc..0000000
--- a/media/java/android/media/audiopolicy/AudioProductStrategies.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2018, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.audiopolicy;
-
-parcelable AudioProductStrategies;
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java
deleted file mode 100644
index c305b68..0000000
--- a/media/java/android/media/audiopolicy/AudioProductStrategies.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.audiopolicy;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.media.AudioAttributes;
-import android.media.AudioSystem;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * @hide
- * A class to encapsulate a collection of {@link AudioProductStrategy}.
- * Provides helper functions to easily retrieve the {@link AudioAttributes} for a given product
- * strategy or legacy stream type.
- */
-@SystemApi
-public final class AudioProductStrategies implements Iterable<AudioProductStrategy>, Parcelable {
-
-    private final ArrayList<AudioProductStrategy> mAudioProductStrategyList;
-
-    private static final String TAG = "AudioProductStrategies";
-
-    public AudioProductStrategies() {
-        ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
-        int status = native_list_audio_product_strategies(apsList);
-        if (status != AudioSystem.SUCCESS) {
-            Log.w(TAG, ": createAudioProductStrategies failed");
-        }
-        mAudioProductStrategyList = apsList;
-    }
-
-    private AudioProductStrategies(ArrayList<AudioProductStrategy> audioProductStrategy) {
-        mAudioProductStrategyList = audioProductStrategy;
-    }
-
-    /**
-     * @hide
-     * @return number of {@link AudioProductStrategy} objects
-     */
-    @SystemApi
-    public int size() {
-        return mAudioProductStrategyList.size();
-    }
-
-    /**
-     * @hide
-     * @return the matching {@link AudioProductStrategy} objects with the given id,
-     *         null object if not found.
-     */
-    @SystemApi
-    public @Nullable AudioProductStrategy getById(int productStrategyId) {
-        for (final AudioProductStrategy avg : this) {
-            if (avg.getId() == productStrategyId) {
-                return avg;
-            }
-        }
-        Log.e(TAG, ": invalid product strategy id: " + productStrategyId + " requested");
-        return null;
-    }
-
-    /**
-     * Returns an {@link Iterator}
-     */
-    @Override
-    public @NonNull Iterator<AudioProductStrategy> iterator() {
-        return mAudioProductStrategyList.iterator();
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        AudioProductStrategies that = (AudioProductStrategies) o;
-
-        return mAudioProductStrategyList.equals(that.mAudioProductStrategyList);
-    }
-
-    /**
-     * @hide
-     * @param aps {@link AudioProductStrategy} (which is the generalisation of Car Audio Usage /
-     *                        legacy routing_strategy linked to {@link AudioAttributes#getUsage()} )
-     * @return the {@link AudioAttributes} relevant for the given product strategy.
-     *         If none is found, it builds the default attributes.
-     *         TODO: shall the helper collection be able to identify the platform default?
-     */
-    @SystemApi
-    @NonNull
-    public AudioAttributes getAudioAttributesForProductStrategy(@NonNull AudioProductStrategy aps) {
-        Preconditions.checkNotNull(aps, "AudioProductStrategy must not be null");
-        for (final AudioProductStrategy audioProductStrategy : this) {
-            if (audioProductStrategy.equals(aps)) {
-                return audioProductStrategy.getAudioAttributes();
-            }
-        }
-        return new AudioAttributes.Builder()
-                                  .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
-                                  .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
-    }
-
-    /**
-     * @hide
-     * @param streamType legacy stream type used for volume operation only
-     * @return the {@link AudioAttributes} relevant for the given streamType.
-     *         If none is found, it builds the default attributes.
-     */
-    @SystemApi
-    public @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) {
-        for (final AudioProductStrategy productStrategy : this) {
-            AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType);
-            if (aa != null) {
-                return aa;
-            }
-        }
-        return new AudioAttributes.Builder()
-                                  .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
-                                  .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
-    }
-
-    /**
-     * @hide
-     * @param aa the {@link AudioAttributes} for which stream type is requested
-     * @return the legacy stream type relevant for the given {@link AudioAttributes}.
-     *         If the product strategy is not associated to any stream, it returns
-     *         {@link AudioSystem#STREAM_MUSIC}.
-     *         If no product strategy supports the stream type, it returns
-     *         {@link AudioSystem#STREAM_MUSIC}.
-     */
-    @SystemApi
-    public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) {
-        Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
-        for (final AudioProductStrategy productStrategy : this) {
-            if (productStrategy.supportsAudioAttributes(aa)) {
-                int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes(aa);
-                if (streamType == AudioSystem.STREAM_DEFAULT) {
-                    Log.w(TAG, "Attributes " + aa.toString() + " ported by strategy "
-                            + productStrategy.name() + " has no stream type associated, "
-                            + "DO NOT USE STREAM TO CONTROL THE VOLUME");
-                    return AudioSystem.STREAM_MUSIC;
-                }
-                return streamType;
-            }
-        }
-        return AudioSystem.STREAM_MUSIC;
-    }
-
-    /**
-     * @hide
-     * @param aa the {@link AudioAttributes} to be considered
-     * @return {@link AudioProductStrategy} supporting the given {@link AudioAttributes}.
-     *         null is returned if no match with given attributes.
-     */
-    @SystemApi
-    @Nullable
-    public AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull AudioAttributes aa) {
-        Preconditions.checkNotNull(aa, "attributes must not be null");
-        int productStrategyId =  native_get_product_strategies_from_audio_attributes(aa);
-        if (productStrategyId < 0) {
-            Log.w(TAG, "no strategy found for Attributes " + aa.toString());
-            return null;
-        }
-        return getById(productStrategyId);
-    }
-
-   /**
-    * @hide
-    * @param attributes the {@link AudioAttributes} to be considered
-    * @return volume group associated to the given {@link AudioAttributes}.
-    *         If no group supports the given {@link AudioAttributes}, it returns the volume group
-    *         for the default attributes.
-    *         If no group supports the default attributes, it returns {@link #DEFAULT_VOLUME_GROUP}
-    */
-    @SystemApi
-    public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
-        Preconditions.checkNotNull(attributes, "attributes must not be null");
-        int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
-        if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
-            return volumeGroupId;
-        }
-        // The default volume group is the one hosted by default product strategy, i.e.
-        // supporting Default Attributes
-        return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
-    }
-
-   /**
-    * @hide
-    * @param streamType to be considered
-    * @return volume group associated to the given stream type.
-    */
-    @SystemApi
-    public int getVolumeGroupIdForLegacyStreamType(int streamType) {
-        for (final AudioProductStrategy productStrategy : this) {
-            int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType);
-            if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
-                return volumeGroupId;
-            }
-        }
-        // The default volume group is the one hosted by default product strategy, i.e.
-        // supporting Default Attributes
-        return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(size());
-        for (final AudioProductStrategy productStrategy : this) {
-            productStrategy.writeToParcel(dest, flags);
-        }
-    }
-
-    /**
-     * @param attributes to be considered
-     * @return volume group associated to the given {@link AudioAttributes}.
-     */
-    private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
-        Preconditions.checkNotNull(attributes, "attributes must not be null");
-        for (final AudioProductStrategy productStrategy : this) {
-            int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
-            if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
-                return volumeGroupId;
-            }
-        }
-        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<AudioProductStrategies> CREATOR =
-            new Parcelable.Creator<AudioProductStrategies>() {
-                @Override
-                public AudioProductStrategies createFromParcel(@NonNull Parcel in) {
-                    ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
-                    int size = in.readInt();
-                    for (int index = 0; index < size; index++) {
-                        apsList.add(AudioProductStrategy.CREATOR.createFromParcel(in));
-                    }
-                    return new AudioProductStrategies(apsList);
-                }
-
-                @Override
-                public @NonNull AudioProductStrategies[] newArray(int size) {
-                    return new AudioProductStrategies[size];
-                }
-            };
-
-    private static native int native_list_audio_product_strategies(
-            ArrayList<AudioProductStrategy> strategies);
-
-    private static native int native_get_product_strategies_from_audio_attributes(
-            AudioAttributes attributes);
-}
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index c1c255f..9ac9411 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -25,9 +25,14 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @hide
  * A class to encapsulate a collection of attributes associated to a given product strategy
@@ -41,6 +46,9 @@
      */
     public static final int DEFAULT_GROUP = -1;
 
+
+    private static final String TAG = "AudioProductStrategy";
+
     private final AudioAttributesGroup[] mAudioAttributesGroups;
     private final String mName;
     /**
@@ -51,6 +59,86 @@
      */
     private int mId;
 
+    private static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static List<AudioProductStrategy> sAudioProductStrategies;
+
+    /**
+     * @hide
+     * @return the list of AudioProductStrategy discovered from platform configuration file.
+     */
+    @NonNull
+    public static List<AudioProductStrategy> getAudioProductStrategies() {
+        if (sAudioProductStrategies == null) {
+            synchronized (sLock) {
+                if (sAudioProductStrategies == null) {
+                    sAudioProductStrategies = initializeAudioProductStrategies();
+                }
+            }
+        }
+        return sAudioProductStrategies;
+    }
+
+    /**
+     * @hide
+     * @param streamType to match against AudioProductStrategy
+     * @return the AudioAttributes for the first strategy found with the associated stream type
+     *          If no match is found, returns AudioAttributes with unknown content_type and usage
+     */
+    @NonNull
+    public static AudioAttributes getAudioAttributesForStrategyWithLegacyStreamType(
+            int streamType) {
+        for (final AudioProductStrategy productStrategy :
+                AudioProductStrategy.getAudioProductStrategies()) {
+            AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType);
+            if (aa != null) {
+                return aa;
+            }
+        }
+        return new AudioAttributes.Builder()
+            .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+            .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
+    }
+
+    /**
+     * @hide
+     * @param audioAttributes to identify AudioProductStrategy with
+     * @return legacy stream type associated with matched AudioProductStrategy
+     *              Defaults to STREAM_MUSIC if no match is found, or if matches is STREAM_DEFAULT
+     */
+    public static int getLegacyStreamTypeForStrategyWithAudioAttributes(
+            @NonNull AudioAttributes audioAttributes) {
+        Preconditions.checkNotNull(audioAttributes, "AudioAttributes must not be null");
+        for (final AudioProductStrategy productStrategy :
+                AudioProductStrategy.getAudioProductStrategies()) {
+            if (productStrategy.supportsAudioAttributes(audioAttributes)) {
+                int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes(
+                        audioAttributes);
+                if (streamType == AudioSystem.STREAM_DEFAULT) {
+                    Log.w(TAG, "Attributes " + audioAttributes.toString() + " ported by strategy "
+                            + productStrategy.getId() + " has no stream type associated, "
+                            + "DO NOT USE STREAM TO CONTROL THE VOLUME");
+                    return AudioSystem.STREAM_MUSIC;
+                }
+                return streamType;
+            }
+        }
+        return AudioSystem.STREAM_MUSIC;
+    }
+
+    private static List<AudioProductStrategy> initializeAudioProductStrategies() {
+        ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
+        int status = native_list_audio_product_strategies(apsList);
+        if (status != AudioSystem.SUCCESS) {
+            Log.w(TAG, ": initializeAudioProductStrategies failed");
+        }
+        return apsList;
+    }
+
+    private static native int native_list_audio_product_strategies(
+            ArrayList<AudioProductStrategy> strategies);
+
     @Override
     public boolean equals(@Nullable Object o) {
         if (this == o) return true;
@@ -65,8 +153,7 @@
     /**
      * @param name of the product strategy
      * @param id of the product strategy
-     * @param audioAttributes {@link AudioAttributes} associated to the given product strategy
-     * @param legacyStreamTypes associated to the given product strategy.
+     * @param aag {@link AudioAttributesGroup} associated to the given product strategy
      */
     private AudioProductStrategy(@NonNull String name, int id,
             @NonNull AudioAttributesGroup[] aag) {
@@ -79,15 +166,6 @@
 
     /**
      * @hide
-     * @return human-readable name of this product strategy, which is similar to a usage
-     */
-    @SystemApi
-    public @NonNull String name() {
-        return mName;
-    }
-
-    /**
-     * @hide
      * @return the product strategy ID (which is the generalisation of Car Audio Usage / legacy
      *         routing_strategy linked to {@link AudioAttributes#getUsage()}).
      */
@@ -158,7 +236,7 @@
      * @hide
      * @param streamType legacy stream type used for volume operation only
      * @return the volume group id relevant for the given streamType.
-     *         If none is found, {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} is returned.
+     *         If none is found, {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} is returned.
      */
     public int getVolumeGroupIdForLegacyStreamType(int streamType) {
         for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
@@ -166,14 +244,14 @@
                 return aag.getVolumeGroupId();
             }
         }
-        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
+        return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
     }
 
     /**
      * @hide
      * @param aa the {@link AudioAttributes} to be considered
      * @return the volume group id associated with the given audio attributes if found,
-     *         {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} otherwise.
+     *         {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} otherwise.
      */
     public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) {
         Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
@@ -182,7 +260,7 @@
                 return aag.getVolumeGroupId();
             }
         }
-        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
+        return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
     }
 
     @Override
@@ -200,7 +278,8 @@
         }
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<AudioProductStrategy> CREATOR =
+    @NonNull
+    public static final Parcelable.Creator<AudioProductStrategy> CREATOR =
             new Parcelable.Creator<AudioProductStrategy>() {
                 @Override
                 public AudioProductStrategy createFromParcel(@NonNull Parcel in) {
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
index b60947f..79be922 100644
--- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
@@ -19,11 +19,15 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.media.AudioAttributes;
+import android.media.AudioSystem;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -34,6 +38,12 @@
  */
 @SystemApi
 public final class AudioVolumeGroup implements Parcelable {
+    private static final String TAG = "AudioVolumeGroup";
+    /**
+     * Volume group value to use when introspection API fails.
+     */
+    public static final int DEFAULT_VOLUME_GROUP = -1;
+
     /**
      * Unique identifier of a volume group.
      */
@@ -46,10 +56,43 @@
     private final AudioAttributes[] mAudioAttributes;
     private int[] mLegacyStreamTypes;
 
+    private static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static List<AudioVolumeGroup> sAudioVolumeGroups;
+
+    /**
+     * @hide
+     * @return the List of AudioVolumeGroup discovered from platform configuration file.
+     */
+    @NonNull
+    public static List<AudioVolumeGroup> getAudioVolumeGroups() {
+        if (sAudioVolumeGroups == null) {
+            synchronized (sLock) {
+                if (sAudioVolumeGroups == null) {
+                    sAudioVolumeGroups = initializeAudioVolumeGroups();
+                }
+            }
+        }
+        return sAudioVolumeGroups;
+    }
+
+    private static List<AudioVolumeGroup> initializeAudioVolumeGroups() {
+        ArrayList<AudioVolumeGroup> avgList = new ArrayList<>();
+        int status = native_list_audio_volume_groups(avgList);
+        if (status != AudioSystem.SUCCESS) {
+            Log.w(TAG, ": listAudioVolumeGroups failed");
+        }
+        return avgList;
+    }
+
+    private static native int native_list_audio_volume_groups(
+            ArrayList<AudioVolumeGroup> groups);
+
     /**
      * @param name of the volume group
      * @param id of the volume group
-     * @param followers {@link AudioProductStrategies} strategy following this volume group
+     * @param legacyStreamTypes of volume group
      */
     AudioVolumeGroup(@NonNull String name, int id,
                      @NonNull AudioAttributes[] audioAttributes,
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl b/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl
deleted file mode 100644
index 918cac3..0000000
--- a/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2018, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.audiopolicy;
-
-parcelable AudioVolumeGroups;
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.java b/media/java/android/media/audiopolicy/AudioVolumeGroups.java
deleted file mode 100644
index 2e56f84..0000000
--- a/media/java/android/media/audiopolicy/AudioVolumeGroups.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.audiopolicy;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.media.AudioSystem;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * @hide
- * A class to encapsulate a collection of {@link AudioVolumeGroup}.
- */
-@SystemApi
-public final class AudioVolumeGroups implements Iterable<AudioVolumeGroup>, Parcelable {
-
-    private final ArrayList<AudioVolumeGroup> mAudioVolumeGroupList;
-
-    private static final String TAG = "AudioVolumeGroups";
-
-    /**
-     * Volume group value to use when introspection API fails.
-     */
-    public static final int DEFAULT_VOLUME_GROUP = -1;
-
-    public AudioVolumeGroups() {
-        ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>();
-        int status = native_list_audio_volume_groups(avgList);
-        if (status != AudioSystem.SUCCESS) {
-            Log.w(TAG, ": listAudioVolumeGroups failed");
-        }
-        mAudioVolumeGroupList = avgList;
-    }
-
-    private AudioVolumeGroups(@NonNull ArrayList<AudioVolumeGroup> audioVolumeGroupList) {
-        Preconditions.checkNotNull(audioVolumeGroupList, "audioVolumeGroupList must not be null");
-        mAudioVolumeGroupList = audioVolumeGroupList;
-    }
-
-    /**
-     * @return number of {@link AudioProductStrategy} objects
-     */
-    public int size() {
-        return mAudioVolumeGroupList.size();
-    }
-
-    /**
-     * Returns an {@link Iterator}
-     */
-    @Override
-    public @NonNull Iterator<AudioVolumeGroup> iterator() {
-        return mAudioVolumeGroupList.iterator();
-    }
-
-    @Override
-    public boolean equals(@NonNull Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        AudioVolumeGroups that = (AudioVolumeGroups) o;
-
-        return mAudioVolumeGroupList.equals(that.mAudioVolumeGroupList);
-    }
-
-    /**
-     * @return the matching {@link AudioVolumeGroup} objects with the given id,
-     *         null object if not found.
-     */
-    public @Nullable AudioVolumeGroup getById(int volumeGroupId) {
-        for (final AudioVolumeGroup avg : this) {
-            if (avg.getId() == volumeGroupId) {
-                return avg;
-            }
-        }
-        Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested");
-        return null;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(size());
-        for (final AudioVolumeGroup volumeGroup : this) {
-            volumeGroup.writeToParcel(dest, flags);
-        }
-    }
-
-    private static native int native_list_audio_volume_groups(
-            ArrayList<AudioVolumeGroup> groups);
-
-    public static final Parcelable.Creator<AudioVolumeGroups> CREATOR =
-            new Parcelable.Creator<AudioVolumeGroups>() {
-                @Override
-                public @NonNull AudioVolumeGroups createFromParcel(@NonNull Parcel in) {
-                    Preconditions.checkNotNull(in, "in Parcel must not be null");
-                    ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>();
-                    int size = in.readInt();
-                    for (int index = 0; index < size; index++) {
-                        avgList.add(AudioVolumeGroup.CREATOR.createFromParcel(in));
-                    }
-                    return new AudioVolumeGroups(avgList);
-                }
-
-                @Override
-                public @NonNull AudioVolumeGroups[] newArray(int size) {
-                    return new AudioVolumeGroups[size];
-                }
-            };
-}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d58888a..77472ed 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -90,9 +90,8 @@
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
-import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioProductStrategy;
 import android.media.audiopolicy.AudioVolumeGroup;
-import android.media.audiopolicy.AudioVolumeGroups;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionManager;
@@ -281,11 +280,6 @@
 
     private SettingsObserver mSettingsObserver;
 
-    /** @see AudioProductStrategies */
-    private static AudioProductStrategies sAudioProductStrategies;
-    /** @see AudioVolumeGroups */
-    private static AudioVolumeGroups sAudioVolumeGroups;
-
     private int mMode = AudioSystem.MODE_NORMAL;
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
@@ -636,19 +630,17 @@
         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
 
-        sAudioProductStrategies = new AudioProductStrategies();
-        sAudioVolumeGroups = new AudioVolumeGroups();
-
         // Initialize volume
         // Priority 1 - Android Property
         // Priority 2 - Audio Policy Service
         // Priority 3 - Default Value
-        if (sAudioProductStrategies.size() > 0) {
+        if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
             int numStreamTypes = AudioSystem.getNumStreamTypes();
 
             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
                 AudioAttributes attr =
-                        sAudioProductStrategies.getAudioAttributesForLegacyStreamType(streamType);
+                        AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
+                                streamType);
                 int maxVolume = AudioSystem.getMaxVolumeIndexForAttributes(attr);
                 if (maxVolume != -1) {
                     MAX_STREAM_VOLUME[streamType] = maxVolume;
@@ -1023,19 +1015,21 @@
     }
 
     /**
-     * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the
+     * @return the {@link android.media.audiopolicy.AudioProductStrategy} discovered from the
      * platform configuration file.
      */
-    public @NonNull AudioProductStrategies getAudioProductStrategies() {
-        return sAudioProductStrategies;
+    @NonNull
+    public List<AudioProductStrategy> getAudioProductStrategies() {
+        return AudioProductStrategy.getAudioProductStrategies();
     }
 
     /**
-     * @return the {@link android.media.audiopolicy.AudioVolumeGroups} discovered from the
+     * @return the List of {@link android.media.audiopolicy.AudioVolumeGroup} discovered from the
      * platform configuration file.
      */
-    public @NonNull AudioVolumeGroups listAudioVolumeGroups() {
-        return sAudioVolumeGroups;
+    @NonNull
+    public List<AudioVolumeGroup> getAudioVolumeGroups() {
+        return AudioVolumeGroup.getAudioVolumeGroups();
     }
 
     private void checkAllAliasStreamVolumes() {
@@ -1947,15 +1941,15 @@
         enforceModifyAudioRoutingPermission();
         Preconditions.checkNotNull(attr, "attr must not be null");
         // @todo not hold the caller context, post message
-        int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
+        int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
         final int device = getDeviceForStream(stream);
 
         int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device);
 
         AudioSystem.setVolumeIndexForAttributes(attr, index, device);
 
-        final int volumeGroup = sAudioProductStrategies.getVolumeGroupIdForAttributes(attr);
-        final AudioVolumeGroup avg = sAudioVolumeGroups.getById(volumeGroup);
+        final int volumeGroup = getVolumeGroupIdForAttributes(attr);
+        final AudioVolumeGroup avg = getAudioVolumeGroupById(volumeGroup);
         if (avg == null) {
             return;
         }
@@ -1965,11 +1959,23 @@
         }
     }
 
+    @Nullable
+    private AudioVolumeGroup getAudioVolumeGroupById(int volumeGroupId) {
+        for (final AudioVolumeGroup avg : AudioVolumeGroup.getAudioVolumeGroups()) {
+            if (avg.getId() == volumeGroupId) {
+                return avg;
+            }
+        }
+
+        Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested");
+        return null;
+    }
+
     /** @see AudioManager#getVolumeIndexForAttributes(attr) */
     public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
         enforceModifyAudioRoutingPermission();
         Preconditions.checkNotNull(attr, "attr must not be null");
-        int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
+        int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
         final int device = getDeviceForStream(stream);
 
         return AudioSystem.getVolumeIndexForAttributes(attr, device);
@@ -2144,6 +2150,32 @@
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
+
+
+    private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
+        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
+        if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
+            return volumeGroupId;
+        }
+        // The default volume group is the one hosted by default product strategy, i.e.
+        // supporting Default Attributes
+        return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
+    }
+
+    private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
+        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        for (final AudioProductStrategy productStrategy :
+                AudioProductStrategy.getAudioProductStrategies()) {
+            int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
+            if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
+                return volumeGroupId;
+            }
+        }
+        return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
+    }
+
+
     // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
     private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
         switch (mNm.getZenMode()) {