Loading media/tests/AudioPolicyTest/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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> media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java +85 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 void reset() { mLatch = new CountDownLatch(1); } public synchronized boolean received() { return mReceived; 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; Loading @@ -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 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("captureDurationMs", PLAYBACK_TIME_MS / 2); 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); AudioTrack track = createAudioTrack(); 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(); synchronized (mReceiver) { long startTimeMs = System.currentTimeMillis(); long elapsedTimeMs = 0; while (elapsedTimeMs < PLAYBACK_TIME_MS && !mReceiver.received()) { 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() { Loading media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java +21 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -71,19 +72,29 @@ public class AudioPolicyDeathTestActivity extends Activity { mAudioPolicy = audioPolicyBuilder.build(); int result = mAudioManager.registerAudioPolicy(mAudioPolicy); if (result != AudioManager.SUCCESS) { Log.w(TAG, "registerAudioPolicy failed, status: " + result); return; } if (result == AudioManager.SUCCESS) { AudioRecord audioRecord = mAudioPolicy.createAudioRecordSink(audioMix); if (audioRecord == null) { 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"); return; result = AudioManager.ERROR_NO_INIT; } } else { Log.w(TAG, "registerAudioPolicy failed, status: " + result); } 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 Loading Loading
media/tests/AudioPolicyTest/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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>
media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTest.java +85 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 void reset() { mLatch = new CountDownLatch(1); } public synchronized boolean received() { return mReceived; 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; Loading @@ -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 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("captureDurationMs", PLAYBACK_TIME_MS / 2); 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); AudioTrack track = createAudioTrack(); 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(); synchronized (mReceiver) { long startTimeMs = System.currentTimeMillis(); long elapsedTimeMs = 0; while (elapsedTimeMs < PLAYBACK_TIME_MS && !mReceiver.received()) { 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() { Loading
media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioPolicyDeathTestActivity.java +21 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -71,19 +72,29 @@ public class AudioPolicyDeathTestActivity extends Activity { mAudioPolicy = audioPolicyBuilder.build(); int result = mAudioManager.registerAudioPolicy(mAudioPolicy); if (result != AudioManager.SUCCESS) { Log.w(TAG, "registerAudioPolicy failed, status: " + result); return; } if (result == AudioManager.SUCCESS) { AudioRecord audioRecord = mAudioPolicy.createAudioRecordSink(audioMix); if (audioRecord == null) { 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"); return; result = AudioManager.ERROR_NO_INIT; } } else { Log.w(TAG, "registerAudioPolicy failed, status: " + result); } 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 Loading