Merge "AudioPolicy: fix test API for focus policy" into qt-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d8b092..5d0c1d9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3672,7 +3672,6 @@
     method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
     method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
     method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
-    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
     method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 6fb4a92..d37b45e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1074,6 +1074,19 @@
 
 package android.media {
 
+  public final class AudioFocusInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.media.AudioAttributes getAttributes();
+    method @NonNull public String getClientId();
+    method public int getClientUid();
+    method public int getFlags();
+    method public int getGainRequest();
+    method public int getLossReceived();
+    method @NonNull public String getPackageName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
+  }
+
   public final class AudioFocusRequest {
     method @Nullable public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
   }
@@ -1085,6 +1098,14 @@
     method public static boolean isEncodingLinearPcm(int);
   }
 
+  public class AudioManager {
+    method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+  }
+
   public static final class AudioRecord.MetricsConstants {
     field public static final String ATTRIBUTES = "android.media.audiorecord.attributes";
     field public static final String CHANNEL_MASK = "android.media.audiorecord.channelMask";
@@ -1178,6 +1199,91 @@
 
 }
 
+package android.media.audiopolicy {
+
+  public class AudioMix {
+    method public int getMixState();
+    field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff
+    field public static final int MIX_STATE_IDLE = 0; // 0x0
+    field public static final int MIX_STATE_MIXING = 1; // 0x1
+    field public static final int ROUTE_FLAG_LOOP_BACK = 2; // 0x2
+    field public static final int ROUTE_FLAG_RENDER = 1; // 0x1
+  }
+
+  public static class AudioMix.Builder {
+    ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
+  }
+
+  public class AudioMixingRule {
+    field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
+    field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
+    field public static final int RULE_MATCH_UID = 4; // 0x4
+  }
+
+  public static class AudioMixingRule.Builder {
+    ctor public AudioMixingRule.Builder();
+    method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, Object) throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
+    method @NonNull public android.media.audiopolicy.AudioMixingRule.Builder allowPrivilegedPlaybackCapture(boolean);
+    method public android.media.audiopolicy.AudioMixingRule build();
+    method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, Object) throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
+  }
+
+  public class AudioPolicy {
+    method public int attachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
+    method public android.media.AudioRecord createAudioRecordSink(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack createAudioTrackSource(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+    method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
+    method public int getFocusDuckingBehavior();
+    method public int getStatus();
+    method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void setRegistration(String);
+    method public String toLogFriendlyString();
+    field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
+    field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
+    field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
+    field public static final int POLICY_STATUS_REGISTERED = 2; // 0x2
+    field public static final int POLICY_STATUS_UNREGISTERED = 1; // 0x1
+  }
+
+  public abstract static class AudioPolicy.AudioPolicyFocusListener {
+    ctor public AudioPolicy.AudioPolicyFocusListener();
+    method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
+    method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
+    method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
+    method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
+  }
+
+  public abstract static class AudioPolicy.AudioPolicyStatusListener {
+    ctor public AudioPolicy.AudioPolicyStatusListener();
+    method public void onMixStateUpdate(android.media.audiopolicy.AudioMix);
+    method public void onStatusChange();
+  }
+
+  public abstract static class AudioPolicy.AudioPolicyVolumeCallback {
+    ctor public AudioPolicy.AudioPolicyVolumeCallback();
+    method public void onVolumeAdjustment(int);
+  }
+
+  public static class AudioPolicy.Builder {
+    ctor public AudioPolicy.Builder(android.content.Context);
+    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+    method @NonNull public android.media.audiopolicy.AudioPolicy build();
+    method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
+    method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
+    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
+    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
+    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
+  }
+
+}
+
 package android.metrics {
 
   public class LogMaker {
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 3aaa7df..ee89509 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,6 +28,7 @@
  * @hide
  * A class to encapsulate information about an audio focus owner or request.
  */
+@TestApi
 @SystemApi
 public final class AudioFocusInfo implements Parcelable {
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4504260..8831265 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -26,6 +26,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -3050,6 +3051,7 @@
      * @param requestResult the result to the focus request to be passed to the requester
      * @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void setFocusRequestResult(@NonNull AudioFocusInfo afi,
@@ -3089,6 +3091,7 @@
      *     if there was an error sending the request.
      * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
@@ -3351,6 +3354,7 @@
      *    {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
      *    {@link #SUCCESS} otherwise.
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
@@ -3385,6 +3389,7 @@
      * Unregisters an {@link AudioPolicy} asynchronously.
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
@@ -3411,6 +3416,7 @@
      * associated with mixes of this policy.
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 09f17c0..2f03d26 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
@@ -31,6 +32,7 @@
 /**
  * @hide
  */
+@TestApi
 @SystemApi
 public class AudioMix {
 
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 5ef19db..ed2fdae 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.media.AudioAttributes;
 import android.os.Parcel;
@@ -41,6 +42,7 @@
  *         .build();
  * </pre>
  */
+@TestApi
 @SystemApi
 public class AudioMixingRule {
 
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 00f6013..1cd60f7 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -55,6 +56,7 @@
  * @hide
  * AudioPolicy provides access to the management of audio routing and audio focus.
  */
+@TestApi
 @SystemApi
 public class AudioPolicy {
 
@@ -237,6 +239,7 @@
         }
 
         /**
+         * @hide
          * Test method to declare whether this audio focus policy is for test purposes only.
          * Having a test policy registered will disable the current focus policy and replace it
          * with this test policy. When unregistered, the previous focus policy will be restored.
@@ -245,6 +248,7 @@
          * @param isTestFocusPolicy true if the focus policy to register is for testing purposes.
          * @return the same Builder instance
          */
+        @TestApi
         @NonNull
         public Builder setIsTestFocusPolicy(boolean isTestFocusPolicy) {
             mIsTestFocusPolicy = isTestFocusPolicy;