1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.audio; 18 19 import com.android.cts.verifier.PassFailButtons; 20 import com.android.cts.verifier.R; 21 import com.android.cts.verifier.audio.wavelib.*; 22 import com.android.compatibility.common.util.ReportLog; 23 import com.android.compatibility.common.util.ResultType; 24 import com.android.compatibility.common.util.ResultUnit; 25 26 import android.app.AlertDialog; 27 import android.content.Context; 28 import android.media.AudioDeviceCallback; 29 import android.media.AudioDeviceInfo; 30 import android.media.AudioManager; 31 import android.os.Bundle; 32 import android.os.Handler; 33 import android.util.Log; 34 import android.view.View; 35 import android.view.View.OnClickListener; 36 import android.view.ViewGroup; 37 import android.widget.LinearLayout; 38 39 /** 40 * Audio Frequency Test base activity 41 */ 42 public class AudioFrequencyActivity extends PassFailButtons.Activity { 43 private static final String TAG = "AudioFrequencyActivity"; 44 private static final boolean DEBUG = true; 45 46 protected Context mContext; 47 protected AudioManager mAudioManager; 48 49 protected AudioDeviceInfo mOutputDevInfo; 50 protected AudioDeviceInfo mInputDevInfo; 51 52 public int mMaxLevel = 0; 53 54 // 55 // TODO - These should be refactored into a RefMicActivity class 56 // i.e. AudioFrequencyActivity <- RefMicActivity 57 private OnBtnClickListener mBtnClickListener = new OnBtnClickListener(); 58 59 60 @Override onCreate(Bundle savedInstanceState)61 protected void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 64 mContext = this; 65 66 mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE); 67 mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler()); 68 } 69 70 // 71 // Common UI Handling connectRefMicUI()72 protected void connectRefMicUI() { 73 findViewById(R.id.refmic_tests_yes_btn).setOnClickListener(mBtnClickListener); 74 findViewById(R.id.refmic_tests_no_btn).setOnClickListener(mBtnClickListener); 75 findViewById(R.id.refmic_test_info_btn).setOnClickListener(mBtnClickListener); 76 77 enableTestUI(false); 78 } 79 showRefMicInfoDialog()80 private void showRefMicInfoDialog() { 81 new AlertDialog.Builder(this) 82 .setTitle(R.string.ref_mic_dlg_caption) 83 .setMessage(R.string.ref_mic_dlg_text) 84 .setPositiveButton(R.string.audio_general_ok, null) 85 .show(); 86 } 87 88 private class OnBtnClickListener implements OnClickListener { 89 @Override onClick(View v)90 public void onClick(View v) { 91 switch (v.getId()) { 92 case R.id.refmic_tests_yes_btn: 93 recordRefMicStatus(true); 94 enableTestUI(true); 95 // disable test button so that they will now run the test(s) 96 getPassButton().setEnabled(false); 97 break; 98 99 case R.id.refmic_tests_no_btn: 100 recordRefMicStatus(false); 101 enableTestUI(false); 102 // Allow the user to "pass" the test. 103 getPassButton().setEnabled(true); 104 break; 105 106 case R.id.refmic_test_info_btn: 107 showRefMicInfoDialog(); 108 break; 109 } 110 } 111 } 112 recordRefMicStatus(boolean has)113 private void recordRefMicStatus(boolean has) { 114 getReportLog().addValue( 115 "User reported ref mic availability: ", 116 has ? 1.0 : 0, 117 ResultType.NEUTRAL, 118 ResultUnit.NONE); 119 } 120 121 // 122 // Overrides 123 // enableTestUI(boolean enable)124 void enableTestUI(boolean enable) { 125 126 } 127 enableLayout(int layoutId, boolean enable)128 void enableLayout(int layoutId, boolean enable) { 129 ViewGroup group = (ViewGroup)findViewById(layoutId); 130 for (int i = 0; i < group.getChildCount(); i++) { 131 group.getChildAt(i).setEnabled(enable); 132 } 133 } 134 setMaxLevel()135 public void setMaxLevel() { 136 mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 137 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(mMaxLevel), 0); 138 } 139 setMinLevel()140 public void setMinLevel() { 141 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0); 142 } 143 testMaxLevel()144 public void testMaxLevel() { 145 int currentLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 146 Log.i(TAG, String.format("Max level: %d curLevel: %d", mMaxLevel, currentLevel)); 147 if (currentLevel != mMaxLevel) { 148 new AlertDialog.Builder(this) 149 .setTitle(R.string.audio_general_warning) 150 .setMessage(R.string.audio_general_level_not_max) 151 .setPositiveButton(R.string.audio_general_ok, null) 152 .show(); 153 } 154 } 155 getMaxLevelForStream(int streamType)156 public int getMaxLevelForStream(int streamType) { 157 return mAudioManager.getStreamMaxVolume(streamType); 158 } 159 setLevelForStream(int streamType, int level)160 public void setLevelForStream(int streamType, int level) { 161 try { 162 mAudioManager.setStreamVolume(streamType, level, 0); 163 } catch (Exception e) { 164 Log.e(TAG, "Error setting stream volume: ", e); 165 } 166 } 167 getLevelForStream(int streamType)168 public int getLevelForStream(int streamType) { 169 return mAudioManager.getStreamVolume(streamType); 170 } 171 enableUILayout(LinearLayout layout, boolean enable)172 public void enableUILayout(LinearLayout layout, boolean enable) { 173 for (int i = 0; i < layout.getChildCount(); i++) { 174 View view = layout.getChildAt(i); 175 view.setEnabled(enable); 176 } 177 } 178 scanPeripheralList(AudioDeviceInfo[] devices)179 private void scanPeripheralList(AudioDeviceInfo[] devices) { 180 // Can't just use the first record because then we will only get 181 // Source OR sink, not both even on devices that are both. 182 mOutputDevInfo = null; 183 mInputDevInfo = null; 184 185 // Any valid peripherals 186 for(AudioDeviceInfo devInfo : devices) { 187 if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || 188 devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) { 189 if (devInfo.isSink()) { 190 mOutputDevInfo = devInfo; 191 } 192 if (devInfo.isSource()) { 193 mInputDevInfo = devInfo; 194 } 195 } 196 } 197 198 } 199 200 private class ConnectListener extends AudioDeviceCallback { ConnectListener()201 /*package*/ ConnectListener() {} 202 203 // 204 // AudioDevicesManager.OnDeviceConnectionListener 205 // 206 @Override onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)207 public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { 208 // Log.i(TAG, "onAudioDevicesAdded() num:" + addedDevices.length); 209 210 scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL)); 211 } 212 213 @Override onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)214 public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { 215 // Log.i(TAG, "onAudioDevicesRemoved() num:" + removedDevices.length); 216 217 scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL)); 218 } 219 } 220 221 // abstract public void updateConnectStatus(); 222 } 223