diff options
Diffstat (limited to 'apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestRouteDuringCallbackActivity.java')
-rw-r--r-- | apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestRouteDuringCallbackActivity.java | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestRouteDuringCallbackActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestRouteDuringCallbackActivity.java new file mode 100644 index 00000000..4dfce073 --- /dev/null +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestRouteDuringCallbackActivity.java @@ -0,0 +1,177 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mobileer.oboetester; + +import static com.mobileer.oboetester.TestAudioActivity.TAG; + +import android.app.Activity; +import android.content.Context; +import android.media.AudioManager; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.RadioButton; +import android.widget.TextView; + +import java.util.Random; + +/** + * Try to crash in the native AAudio code by causing a routing change + * while playing audio. The buffer may get deleted while we are writing to it! + * See b/274815060 + */ +public class TestRouteDuringCallbackActivity extends Activity { + + private TextView mStatusView; + private MyStreamSniffer mStreamSniffer; + private AudioManager mAudioManager; + private RadioButton mOutputButton; + private RadioButton mInputButton; + private Button mStartButton; + private Button mStopButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_routing_crash); + mStatusView = (TextView) findViewById(R.id.text_callback_status); + mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + + mStartButton = (Button) findViewById(R.id.button_start_test); + mStopButton = (Button) findViewById(R.id.button_stop_test); + mOutputButton = (RadioButton) findViewById(R.id.direction_output); + mInputButton = (RadioButton) findViewById(R.id.direction_input); + setButtonsEnabled(false); + } + + public void onStartRoutingTest(View view) { + startRoutingTest(); + } + + public void onStopRoutingTest(View view) { + stopRoutingTest(); + } + + private void setButtonsEnabled(boolean running) { + mStartButton.setEnabled(!running); + mStopButton.setEnabled(running); + mOutputButton.setEnabled(!running); + mInputButton.setEnabled(!running); + } + + // Change routing while the stream is playing. + // Keep trying until we crash. + protected class MyStreamSniffer extends Thread { + boolean enabled = true; + int routingOption = 0; + StringBuffer statusBuffer = new StringBuffer(); + int loopCount; + + @Override + public void run() { + routingOption = 0; + changeRoute(routingOption); + int result; + Random random = new Random(); + while (enabled) { + loopCount++; + if (routingOption == 0) { + statusBuffer = new StringBuffer(); + } + try { + sleep(100); + boolean useInput = mInputButton.isChecked(); + result = startStream(useInput); + sleep(100); + log("-------#" + loopCount + ", " + (useInput ? "IN" : "OUT") + + "\nstartStream() returned " + result); + int sleepTimeMillis = 500 + random.nextInt(500); + sleep(sleepTimeMillis); + routingOption = (routingOption == 0) ? 1 : 0; + log( "changeRoute " + routingOption); + changeRoute(routingOption); + sleep(50); + } catch (InterruptedException e) { + } finally { + result = stopStream(); + log("stopStream() returned " + result); + } + } + changeRoute(0); + } + + // Log to screen and logcat. + private void log(String text) { + Log.d(TAG, "RoutingCrash: " + text); + statusBuffer.append(text + ", sleep " + getSleepTimeMicros() + " us\n"); + showStatus(statusBuffer.toString()); + } + + // Stop the test thread. + void finish() { + enabled = false; + interrupt(); + try { + join(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + protected void showStatus(final String message) { + runOnUiThread(new Runnable() { + @Override + public void run() { + mStatusView.setText(message); + } + }); + } + + private void changeRoute(int option) { + mAudioManager.setSpeakerphoneOn(option > 0); + } + + private native int startStream(boolean useInput); + private native int getSleepTimeMicros(); + private native int stopStream(); + + @Override + public void onPause() { + super.onPause(); + stopRoutingTest(); + } + + private void startRoutingTest() { + stopRoutingTest(); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + setButtonsEnabled(true); + mStreamSniffer = new MyStreamSniffer(); + mStreamSniffer.start(); + } + + private void stopRoutingTest() { + if (mStreamSniffer != null) { + mStreamSniffer.finish(); + mStreamSniffer = null; + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + setButtonsEnabled(false); + } + } +} |