Merge "AudioPolicy: add synchronous unregister method"

This commit is contained in:
TreeHugger Robot
2019-03-12 18:30:27 +00:00
committed by Android (Google) Code Review
5 changed files with 107 additions and 1 deletions

View File

@@ -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

View File

@@ -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
/**

View File

@@ -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);

View File

@@ -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;
@@ -73,6 +76,19 @@ public class AudioPolicy {
private AudioPolicyStatusListener mStatusListener;
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;
}

View File

@@ -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) {