From 55f9db2f0ea5647f1abe7dcddf4b8c78f21b5fd4 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 5 Dec 2022 13:54:14 -0800 Subject: Add setCommunicationsDevice menu (#1668) Also move setSpeakerphoneOn into test activities. --- apps/OboeTester/app/build.gradle | 4 +- .../audio_device/CommunicationDeviceSpinner.java | 126 +++++++++++++++++++ .../oboetester/CommunicationDeviceView.java | 135 +++++++++++++++++++++ .../java/com/mobileer/oboetester/EchoActivity.java | 10 ++ .../java/com/mobileer/oboetester/MainActivity.java | 7 -- .../com/mobileer/oboetester/TestInputActivity.java | 11 ++ .../mobileer/oboetester/TestOutputActivity.java | 17 ++- .../app/src/main/res/layout/activity_echo.xml | 9 +- .../app/src/main/res/layout/activity_main.xml | 16 +-- .../src/main/res/layout/activity_test_input.xml | 7 ++ .../src/main/res/layout/activity_test_output.xml | 8 ++ .../app/src/main/res/layout/comm_device_view.xml | 43 +++++++ .../OboeTester/app/src/main/res/values/strings.xml | 1 + 13 files changed, 368 insertions(+), 26 deletions(-) create mode 100644 apps/OboeTester/app/src/main/java/com/mobileer/audio_device/CommunicationDeviceSpinner.java create mode 100644 apps/OboeTester/app/src/main/java/com/mobileer/oboetester/CommunicationDeviceView.java create mode 100644 apps/OboeTester/app/src/main/res/layout/comm_device_view.xml diff --git a/apps/OboeTester/app/build.gradle b/apps/OboeTester/app/build.gradle index 7e6efd81..43e30b1f 100644 --- a/apps/OboeTester/app/build.gradle +++ b/apps/OboeTester/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId = "com.mobileer.oboetester" minSdkVersion 23 targetSdkVersion 33 - versionCode 60 - versionName "2.3.1" + versionCode 63 + versionName "2.3.4" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/audio_device/CommunicationDeviceSpinner.java b/apps/OboeTester/app/src/main/java/com/mobileer/audio_device/CommunicationDeviceSpinner.java new file mode 100644 index 00000000..fcdcf412 --- /dev/null +++ b/apps/OboeTester/app/src/main/java/com/mobileer/audio_device/CommunicationDeviceSpinner.java @@ -0,0 +1,126 @@ +package com.mobileer.audio_device; +/* + * Copyright 2022 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. + */ + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.Resources.Theme; +import android.media.AudioDeviceCallback; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; +import android.util.AttributeSet; +import android.widget.Spinner; + +import com.mobileer.oboetester.R; + +import java.util.List; + +public class CommunicationDeviceSpinner extends Spinner { + private static final int CLEAR_DEVICE_ID = 0; + private static final String TAG = CommunicationDeviceSpinner.class.getName(); + private AudioDeviceAdapter mDeviceAdapter; + private AudioManager mAudioManager; + private Context mContext; + AudioDeviceInfo[] mCommDeviceArray = null; + + public CommunicationDeviceSpinner(Context context){ + super(context); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, int mode){ + super(context, mode); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, AttributeSet attrs){ + super(context, attrs); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, AttributeSet attrs, int defStyleAttr){ + super(context, attrs, defStyleAttr); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode){ + super(context, attrs, defStyleAttr, mode); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes, int mode){ + super(context, attrs, defStyleAttr, defStyleRes, mode); + setup(context); + } + + public CommunicationDeviceSpinner(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes, int mode, Theme popupTheme){ + super(context, attrs, defStyleAttr, defStyleRes, mode, popupTheme); + setup(context); + } + + public AudioDeviceInfo[] getCommunicationsDevices() { + return mCommDeviceArray; + } + + private void setup(Context context){ + mContext = context; + + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + + mDeviceAdapter = new AudioDeviceAdapter(context); + setAdapter(mDeviceAdapter); + + // Add a default entry to the list and select it + mDeviceAdapter.add(new AudioDeviceListEntry(CLEAR_DEVICE_ID, + mContext.getString(R.string.auto_select))); + setSelection(0); + setupCommunicationDeviceListener(); + } + + @TargetApi(31) + private void setupCommunicationDeviceListener(){ + // Note that we will immediately receive a call to onDevicesAdded with the list of + // devices which are currently connected. + mAudioManager.registerAudioDeviceCallback(new AudioDeviceCallback() { + @Override + public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { + updateDeviceList(); + } + + public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { + updateDeviceList(); + } + + private void updateDeviceList() { + mDeviceAdapter.clear(); + mDeviceAdapter.add(new AudioDeviceListEntry(CLEAR_DEVICE_ID, + mContext.getString(R.string.clear))); + setSelection(0); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + List commDeviceList = mAudioManager.getAvailableCommunicationDevices(); + mCommDeviceArray = commDeviceList.toArray(new AudioDeviceInfo[0]); + // Communications Devices are always OUTPUTS. + List deviceList = + AudioDeviceListEntry.createListFrom( + mCommDeviceArray, AudioManager.GET_DEVICES_OUTPUTS); + mDeviceAdapter.addAll(deviceList); + } + } + }, null); + } +} diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/CommunicationDeviceView.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/CommunicationDeviceView.java new file mode 100644 index 00000000..4e8df135 --- /dev/null +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/CommunicationDeviceView.java @@ -0,0 +1,135 @@ +/* + * Copyright 2022 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 android.content.Context; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.mobileer.audio_device.CommunicationDeviceSpinner; + +public class CommunicationDeviceView extends LinearLayout { + private CheckBox mSpeakerphoneCheckbox; + private TextView mIsSpeakerphoneText; + private AudioManager mAudioManager; + private CommunicationDeviceSpinner mDeviceSpinner; + + public CommunicationDeviceView(Context context) { + super(context); + initializeViews(context); + } + + public CommunicationDeviceView(Context context, AttributeSet attrs) { + super(context, attrs); + initializeViews(context); + } + + public CommunicationDeviceView(Context context, + AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + initializeViews(context); + } + + /** + * Inflates the views in the layout. + * + * @param context the current context for the view. + */ + private void initializeViews(Context context) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.comm_device_view, this); + + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + mSpeakerphoneCheckbox = (CheckBox) findViewById(R.id.setSpeakerphoneOn); + + mDeviceSpinner = (CommunicationDeviceSpinner) findViewById(R.id.comm_devices_spinner); + mDeviceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int position, long id) + { + AudioDeviceInfo[] commDeviceArray = mDeviceSpinner.getCommunicationsDevices(); + if (commDeviceArray != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (position == 0) { + mAudioManager.clearCommunicationDevice(); + } else { + AudioDeviceInfo selectedDevice = commDeviceArray[position - 1]; // skip "Clear" + mAudioManager.setCommunicationDevice(selectedDevice); + } + showCommDeviceStatus(); + } + } + } + public void onNothingSelected(AdapterView parent) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + mAudioManager.clearCommunicationDevice(); + } + showCommDeviceStatus(); + } + }); + + mSpeakerphoneCheckbox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onSetSpeakerphoneOn(view); + } + }); + mIsSpeakerphoneText = (TextView) findViewById(R.id.isSpeakerphoneOn); + showCommDeviceStatus(); + } + + public void cleanup() { + mSpeakerphoneCheckbox.setChecked(false); + setSpeakerPhoneOn(false); + } + + public void onSetSpeakerphoneOn(View view) { + Log.d(TestAudioActivity.TAG, "onSetSpeakerphoneOn() called from Checkbox"); + CheckBox checkBox = (CheckBox) view; + boolean enabled = checkBox.isChecked(); + setSpeakerPhoneOn(enabled); + showCommDeviceStatus(); + } + + private void setSpeakerPhoneOn(boolean enabled) { + Log.d(TestAudioActivity.TAG, "call setSpeakerphoneOn(" + enabled + ")"); + mAudioManager.setSpeakerphoneOn(enabled); + } + + private void showCommDeviceStatus() { + boolean enabled = mAudioManager.isSpeakerphoneOn(); + String text = (enabled ? "ON" : "OFF"); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + AudioDeviceInfo commDeviceInfo = mAudioManager.getCommunicationDevice(); + if (commDeviceInfo != null) { + text += ", CommDev=" + commDeviceInfo.getId(); + } + } + mIsSpeakerphoneText.setText(" => " + text); + } + +} diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/EchoActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/EchoActivity.java index 69fb7617..1d8e4dcc 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/EchoActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/EchoActivity.java @@ -42,6 +42,7 @@ public class EchoActivity extends TestInputActivity { private Button mStartButton; private Button mStopButton; private TextView mStatusTextView; + private CommunicationDeviceView mCommunicationDeviceView; private ColdStartSniffer mNativeSniffer = new ColdStartSniffer(this); @@ -158,9 +159,18 @@ public class EchoActivity extends TestInputActivity { 100.0); mFaderDelayTime.setProgress(MAX_DELAY_TIME_PROGRESS / 2); + mCommunicationDeviceView = (CommunicationDeviceView) findViewById(R.id.comm_device_view); hideSettingsViews(); } + @Override + protected void onStop() { + if (mCommunicationDeviceView != null) { + mCommunicationDeviceView.cleanup(); + } + super.onStop(); + } + private void setDelayTimeByPosition(int progress) { mDelayTime = mTaperDelayTime.linearToExponential( ((double)progress)/MAX_DELAY_TIME_PROGRESS); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/MainActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/MainActivity.java index b8cd43b2..70eca907 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/MainActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/MainActivity.java @@ -312,13 +312,6 @@ public class MainActivity extends BaseOboeTesterActivity { OboeAudioStream.setCallbackSize(callbackSize); } - public void onSetSpeakerphoneOn(View view) { - CheckBox checkBox = (CheckBox) view; - boolean enabled = checkBox.isChecked(); - AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - myAudioMgr.setSpeakerphoneOn(enabled); - } - public void onStartStopBluetoothSco(View view) { CheckBox checkBox = (CheckBox) view; AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestInputActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestInputActivity.java index 578ed050..7f33d803 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestInputActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestInputActivity.java @@ -44,6 +44,7 @@ public class TestInputActivity extends TestAudioActivity { private InputMarginView mInputMarginView; private int mInputMarginBursts = 0; private WorkloadView mWorkloadView; + private CommunicationDeviceView mCommunicationDeviceView; public native void setMinimumFramesBeforeRead(int frames); public native int saveWaveFile(String absolutePath); @@ -77,6 +78,16 @@ public class TestInputActivity extends TestAudioActivity { if (mWorkloadView != null) { mWorkloadView.setAudioStreamTester(mAudioInputTester); } + + mCommunicationDeviceView = (CommunicationDeviceView) findViewById(R.id.comm_device_view); + } + + @Override + protected void onStop() { + if (mCommunicationDeviceView != null) { + mCommunicationDeviceView.cleanup(); + } + super.onStop(); } @Override diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestOutputActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestOutputActivity.java index 39f30506..0d5d0ce3 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestOutputActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestOutputActivity.java @@ -16,15 +16,17 @@ package com.mobileer.oboetester; -import static com.mobileer.oboetester.IntentBasedTestSupport.configureStreamsFromBundle; - +import android.content.Context; +import android.media.AudioManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.CheckBox; import android.widget.Spinner; +import android.widget.TextView; import java.io.IOException; @@ -36,6 +38,7 @@ public final class TestOutputActivity extends TestOutputActivityBase { public static final int MAX_CHANNEL_BOXES = 16; private CheckBox[] mChannelBoxes; private Spinner mOutputSignalSpinner; + protected CommunicationDeviceView mCommunicationDeviceView; private class OutputSignalSpinnerListener implements android.widget.AdapterView.OnItemSelectedListener { @Override @@ -85,6 +88,8 @@ public final class TestOutputActivity extends TestOutputActivityBase { mOutputSignalSpinner = (Spinner) findViewById(R.id.spinnerOutputSignal); mOutputSignalSpinner.setOnItemSelectedListener(new OutputSignalSpinnerListener()); mOutputSignalSpinner.setSelection(StreamConfiguration.NATIVE_API_UNSPECIFIED); + + mCommunicationDeviceView = (CommunicationDeviceView) findViewById(R.id.comm_device_view); } @Override @@ -92,6 +97,14 @@ public final class TestOutputActivity extends TestOutputActivityBase { return ACTIVITY_TEST_OUTPUT; } + @Override + protected void onStop() { + if (mCommunicationDeviceView != null) { + mCommunicationDeviceView.cleanup(); + } + super.onStop(); + } + public void openAudio() throws IOException { super.openAudio(); } diff --git a/apps/OboeTester/app/src/main/res/layout/activity_echo.xml b/apps/OboeTester/app/src/main/res/layout/activity_echo.xml index 03ad1a84..128a2160 100644 --- a/apps/OboeTester/app/src/main/res/layout/activity_echo.xml +++ b/apps/OboeTester/app/src/main/res/layout/activity_echo.xml @@ -76,6 +76,12 @@ android:progress="1000" /> + - +≈ + diff --git a/apps/OboeTester/app/src/main/res/layout/activity_main.xml b/apps/OboeTester/app/src/main/res/layout/activity_main.xml index 0f2d930d..e216c926 100644 --- a/apps/OboeTester/app/src/main/res/layout/activity_main.xml +++ b/apps/OboeTester/app/src/main/res/layout/activity_main.xml @@ -182,25 +182,13 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView" /> - - - + + + + + diff --git a/apps/OboeTester/app/src/main/res/layout/comm_device_view.xml b/apps/OboeTester/app/src/main/res/layout/comm_device_view.xml new file mode 100644 index 00000000..6144f8cd --- /dev/null +++ b/apps/OboeTester/app/src/main/res/layout/comm_device_view.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/OboeTester/app/src/main/res/values/strings.xml b/apps/OboeTester/app/src/main/res/values/strings.xml index 44411d16..a89ed940 100644 --- a/apps/OboeTester/app/src/main/res/values/strings.xml +++ b/apps/OboeTester/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ Play Measure Cancel + Clear Get Param Device Name -- cgit v1.2.3