summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt1
-rw-r--r--media/java/android/media/AudioManager.java22
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java60
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java23
5 files changed, 107 insertions, 1 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 681147a536c2..03a3a55c50c8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3487,6 +3487,7 @@ package android.media {
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
method public void unregisterVolumeGroupCallback(@NonNull android.media.AudioManager.VolumeGroupCallback);
field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7783a4d6c869..c11f44600be4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3308,6 +3308,7 @@ public class AudioManager {
/**
* @hide
+ * Unregisters an {@link AudioPolicy} asynchronously.
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
@SystemApi
@@ -3329,6 +3330,27 @@ public class AudioManager {
}
}
+ /**
+ * @hide
+ * Unregisters an {@link AudioPolicy} synchronously.
+ * This method also invalidates all {@link AudioRecord} and {@link AudioTrack} objects
+ * associated with mixes of this policy.
+ * @param policy the non-null {@link AudioPolicy} to unregister.
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
+ Preconditions.checkNotNull(policy, "Illegal null AudioPolicy argument");
+ final IAudioService service = getService();
+ try {
+ policy.invalidateCaptorsAndInjectors();
+ service.unregisterAudioPolicy(policy.cb());
+ policy.setRegistration(null);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
//====================================================================
// Notification of playback activity & playback configuration
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 02856678879e..95d89bb75b34 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -199,6 +199,8 @@ interface IAudioService {
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
+ void unregisterAudioPolicy(in IAudioPolicyCallback pcb);
+
int addMixForPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb);
int removeMixForPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 5f65d586b730..978583e99971 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -43,8 +43,11 @@ import android.os.ServiceManager;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -74,6 +77,19 @@ public class AudioPolicy {
private boolean mIsFocusPolicy;
/**
+ * The list of AudioTrack instances created to inject audio into the associated mixes
+ * Lazy initialization in {@link #createAudioTrackSource(AudioMix)}
+ */
+ @GuardedBy("mLock")
+ @Nullable private ArrayList<WeakReference<AudioTrack>> mInjectors;
+ /**
+ * The list AudioRecord instances created to capture audio from the associated mixes
+ * Lazy initialization in {@link #createAudioRecordSink(AudioMix)}
+ */
+ @GuardedBy("mLock")
+ @Nullable private ArrayList<WeakReference<AudioRecord>> mCaptors;
+
+ /**
* The behavior of a policy with regards to audio focus where it relies on the application
* to do the ducking, the is the legacy and default behavior.
*/
@@ -606,6 +622,12 @@ public class AudioPolicy {
AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
AudioManager.AUDIO_SESSION_ID_GENERATE
);
+ synchronized (mLock) {
+ if (mCaptors == null) {
+ mCaptors = new ArrayList<>(1);
+ }
+ mCaptors.add(new WeakReference<AudioRecord>(ar));
+ }
return ar;
}
@@ -638,9 +660,47 @@ public class AudioPolicy {
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE
);
+ synchronized (mLock) {
+ if (mInjectors == null) {
+ mInjectors = new ArrayList<>(1);
+ }
+ mInjectors.add(new WeakReference<AudioTrack>(at));
+ }
return at;
}
+ /**
+ * @hide
+ */
+ public void invalidateCaptorsAndInjectors() {
+ if (!policyReadyToUse()) {
+ return;
+ }
+ synchronized (mLock) {
+ if (mInjectors != null) {
+ for (final WeakReference<AudioTrack> weakTrack : mInjectors) {
+ final AudioTrack track = weakTrack.get();
+ if (track == null) {
+ break;
+ }
+ // TODO: add synchronous versions
+ track.stop();
+ track.flush();
+ }
+ }
+ if (mCaptors != null) {
+ for (final WeakReference<AudioRecord> weakRecord : mCaptors) {
+ final AudioRecord record = weakRecord.get();
+ if (record == null) {
+ break;
+ }
+ // TODO: if needed: implement an invalidate method
+ record.stop();
+ }
+ }
+ }
+ }
+
public int getStatus() {
return mStatus;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 91d19def1766..100113cbb5a5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6387,7 +6387,28 @@ public class AudioService extends IAudioService.Stub
return mProjectionService;
}
- public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
+ /**
+ * See {@link AudioManager#unregisterAudioPolicyAsync(AudioPolicy)}
+ * Declared oneway
+ * @param pcb nullable because on service interface
+ */
+ public void unregisterAudioPolicyAsync(@Nullable IAudioPolicyCallback pcb) {
+ unregisterAudioPolicy(pcb);
+ }
+
+ /**
+ * See {@link AudioManager#unregisterAudioPolicy(AudioPolicy)}
+ * @param pcb nullable because on service interface
+ */
+ public void unregisterAudioPolicy(@Nullable IAudioPolicyCallback pcb) {
+ if (pcb == null) {
+ return;
+ }
+ unregisterAudioPolicyInt(pcb);
+ }
+
+
+ private void unregisterAudioPolicyInt(@NonNull IAudioPolicyCallback pcb) {
mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
+ pcb.asBinder()).printLog(TAG)));
synchronized (mAudioPolicies) {