diff options
| author | 2023-01-11 10:17:36 +0000 | |
|---|---|---|
| committer | 2023-01-11 10:17:36 +0000 | |
| commit | 340dbdabf31ebc5f454b35e53bd564798d88bfbd (patch) | |
| tree | a93bc3207681d28d6ba01bfa08421f0ceb8a65a8 | |
| parent | 07fc894c9bc551b003fbd49862a157beeebeceed (diff) | |
| parent | 39adc8aa6d93b36beb3aa7bfc814462e62f1c083 (diff) | |
Merge "AudioPolicyDeathTest: fix flakiness"
3 files changed, 109 insertions, 38 deletions
diff --git a/media/tests/AudioPolicyTest/res/values/strings.xml b/media/tests/AudioPolicyTest/res/values/strings.xml index 036592770450..128c3c52aaff 100644 --- a/media/tests/AudioPolicyTest/res/values/strings.xml +++ b/media/tests/AudioPolicyTest/res/values/strings.xml @@ -2,4 +2,7 @@ <resources> <!-- name of the app [CHAR LIMIT=25]--> <string name="app_name">Audio Policy APIs Tests</string> + <string name="capture_duration_key">captureDurationMs</string> + <string name="callback_key">callback</string> + <string name="status_key">result</string> </resources> diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java index 841804b02354..48c51af26d3a 100644 --- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java +++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java @@ -20,6 +20,8 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeNoException; +import static org.junit.Assume.assumeTrue; import android.content.BroadcastReceiver; import android.content.Context; @@ -30,6 +32,8 @@ import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; +import android.os.Bundle; +import android.os.RemoteCallback; import android.platform.test.annotations.Presubmit; import android.util.Log; @@ -39,33 +43,62 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + @Presubmit @RunWith(AndroidJUnit4.class) public class AudioPolicyDeathTest { private static final String TAG = "AudioPolicyDeathTest"; private static final int SAMPLE_RATE = 48000; - private static final int PLAYBACK_TIME_MS = 2000; + private static final int PLAYBACK_TIME_MS = 4000; + private static final int RECORD_TIME_MS = 1000; + private static final int ACTIVITY_TIMEOUT_SEC = 5; + private static final int BROADCAST_TIMEOUT_SEC = 10; + private static final int MAX_ATTEMPTS = 5; + private static final int DELAY_BETWEEN_ATTEMPTS_MS = 2000; private static final IntentFilter AUDIO_NOISY_INTENT_FILTER = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); private class MyBroadcastReceiver extends BroadcastReceiver { - private boolean mReceived = false; + private CountDownLatch mLatch = new CountDownLatch(1); + @Override public void onReceive(Context context, Intent intent) { if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { - synchronized (this) { - mReceived = true; - notify(); - } + mLatch.countDown(); } } - public synchronized boolean received() { - return mReceived; + public void reset() { + mLatch = new CountDownLatch(1); + } + + public boolean waitForBroadcast() { + boolean received = false; + long startTimeMs = System.currentTimeMillis(); + long elapsedTimeMs = 0; + + Log.i(TAG, "waiting for broadcast"); + + while (elapsedTimeMs < BROADCAST_TIMEOUT_SEC && !received) { + try { + received = mLatch.await(BROADCAST_TIMEOUT_SEC, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.w(TAG, "wait interrupted"); + } + elapsedTimeMs = System.currentTimeMillis() - startTimeMs; + } + Log.i(TAG, "broadcast " + (received ? "" : "NOT ") + "received"); + return received; } } + private final MyBroadcastReceiver mReceiver = new MyBroadcastReceiver(); private Context mContext; @@ -85,31 +118,55 @@ public class AudioPolicyDeathTest { public void testPolicyClientDeathSendBecomingNoisyIntent() { mContext.registerReceiver(mReceiver, AUDIO_NOISY_INTENT_FILTER); - // Launch process registering a dynamic auido policy and dying after PLAYBACK_TIME_MS/2 ms - Intent intent = new Intent(mContext, AudioPolicyDeathTestActivity.class); - intent.putExtra("captureDurationMs", PLAYBACK_TIME_MS / 2); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - mContext.startActivity(intent); - - AudioTrack track = createAudioTrack(); - track.play(); - synchronized (mReceiver) { - long startTimeMs = System.currentTimeMillis(); - long elapsedTimeMs = 0; - while (elapsedTimeMs < PLAYBACK_TIME_MS && !mReceiver.received()) { + boolean result = false; + for (int numAttempts = 1; numAttempts <= MAX_ATTEMPTS && !result; numAttempts++) { + mReceiver.reset(); + + CompletableFuture<Integer> callbackReturn = new CompletableFuture<>(); + RemoteCallback cb = new RemoteCallback((Bundle res) -> { + callbackReturn.complete( + res.getInt(mContext.getResources().getString(R.string.status_key))); + }); + + // Launch process registering a dynamic auido policy and dying after RECORD_TIME_MS ms + // RECORD_TIME_MS must be shorter than PLAYBACK_TIME_MS + Intent intent = new Intent(mContext, AudioPolicyDeathTestActivity.class); + intent.putExtra(mContext.getResources().getString(R.string.capture_duration_key), + RECORD_TIME_MS); + intent.putExtra(mContext.getResources().getString(R.string.callback_key), cb); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + + mContext.startActivity(intent); + + Integer status = AudioManager.ERROR; + try { + status = callbackReturn.get(ACTIVITY_TIMEOUT_SEC, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + assumeNoException(e); + } + assumeTrue(status != null && status == AudioManager.SUCCESS); + + Log.i(TAG, "Activity started"); + AudioTrack track = null; + try { + track = createAudioTrack(); + track.play(); + result = mReceiver.waitForBroadcast(); + } finally { + if (track != null) { + track.stop(); + track.release(); + } + } + if (!result) { try { - mReceiver.wait(PLAYBACK_TIME_MS - elapsedTimeMs); + Log.i(TAG, "Retrying after attempt: " + numAttempts); + Thread.sleep(DELAY_BETWEEN_ATTEMPTS_MS); } catch (InterruptedException e) { - Log.w(TAG, "wait interrupted"); } - elapsedTimeMs = System.currentTimeMillis() - startTimeMs; } } - - track.stop(); - track.release(); - - assertTrue(mReceiver.received()); + assertTrue(result); } private AudioTrack createAudioTrack() { diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java index 957e719ab71f..ce5f56c9e556 100644 --- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java +++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java @@ -26,6 +26,7 @@ import android.media.audiopolicy.AudioMixingRule; import android.media.audiopolicy.AudioPolicy; import android.os.Bundle; import android.os.Looper; +import android.os.RemoteCallback; import android.util.Log; // This activity will register a dynamic audio policy to intercept media playback and launch @@ -71,19 +72,29 @@ public class AudioPolicyDeathTestActivity extends Activity { mAudioPolicy = audioPolicyBuilder.build(); int result = mAudioManager.registerAudioPolicy(mAudioPolicy); - if (result != AudioManager.SUCCESS) { + if (result == AudioManager.SUCCESS) { + AudioRecord audioRecord = mAudioPolicy.createAudioRecordSink(audioMix); + if (audioRecord != null && audioRecord.getState() != AudioRecord.STATE_UNINITIALIZED) { + int captureDurationMs = getIntent().getIntExtra( + getString(R.string.capture_duration_key), RECORD_TIME_MS); + AudioCapturingThread thread = + new AudioCapturingThread(audioRecord, captureDurationMs); + thread.start(); + } else { + Log.w(TAG, "AudioRecord creation failed"); + result = AudioManager.ERROR_NO_INIT; + } + } else { Log.w(TAG, "registerAudioPolicy failed, status: " + result); - return; - } - AudioRecord audioRecord = mAudioPolicy.createAudioRecordSink(audioMix); - if (audioRecord == null) { - Log.w(TAG, "AudioRecord creation failed"); - return; } - int captureDurationMs = getIntent().getIntExtra("captureDurationMs", RECORD_TIME_MS); - AudioCapturingThread thread = new AudioCapturingThread(audioRecord, captureDurationMs); - thread.start(); + RemoteCallback cb = + (RemoteCallback) getIntent().getExtras().get(getString(R.string.callback_key)); + Bundle res = new Bundle(); + res.putInt(getString(R.string.status_key), result); + Log.i(TAG, "policy " + (result == AudioManager.SUCCESS ? "" : "un") + + "successfully registered"); + cb.sendResult(res); } @Override |