Add echo tester in the audio settings

This commit is contained in:
Erwan Croze 2016-08-08 12:08:53 +02:00
parent 338a6c730c
commit fc269d9b01
7 changed files with 116 additions and 10 deletions

View file

@ -107,6 +107,7 @@
<string name="pref_background_mode_key">pref_background_mode_key</string> <string name="pref_background_mode_key">pref_background_mode_key</string>
<string name="pref_codec_bitrate_limit_key">pref_codec_bitrate_limit_key</string> <string name="pref_codec_bitrate_limit_key">pref_codec_bitrate_limit_key</string>
<string name="pref_adaptive_rate_control_key">pref_adaptive_rate_control_key</string> <string name="pref_adaptive_rate_control_key">pref_adaptive_rate_control_key</string>
<string name="pref_echo_tester_key">pref_echo_tester_key</string>
<string name="push_reg_id_key">push_reg_id_key</string> <string name="push_reg_id_key">push_reg_id_key</string>
<string name="push_sender_id_key">push_sender_id_key</string> <string name="push_sender_id_key">push_sender_id_key</string>

View file

@ -245,6 +245,7 @@
<string name="pref_echo_cancellation">Echo cancellation</string> <string name="pref_echo_cancellation">Echo cancellation</string>
<string name="pref_echo_cancellation_summary">Removes the echo heard by other end</string> <string name="pref_echo_cancellation_summary">Removes the echo heard by other end</string>
<string name="pref_echo_canceller_calibration">Echo canceler calibration</string> <string name="pref_echo_canceller_calibration">Echo canceler calibration</string>
<string name="pref_echo_tester">Test echo</string>
<string name="ec_calibrating">Calibrating…</string> <string name="ec_calibrating">Calibrating…</string>
<string name="ec_calibrated">Calibrated in %s ms</string> <string name="ec_calibrated">Calibrated in %s ms</string>
<string name="no_echo">No echo</string> <string name="no_echo">No echo</string>

View file

@ -69,6 +69,11 @@
android:title="@string/pref_echo_canceller_calibration" android:title="@string/pref_echo_canceller_calibration"
android:key="@string/pref_echo_canceller_calibration_key" android:key="@string/pref_echo_canceller_calibration_key"
android:persistent="false"/> android:persistent="false"/>
<Preference
android:title="@string/pref_echo_tester"
android:key="@string/pref_echo_tester_key"
android:persistent="false"/>
<CheckBoxPreference <CheckBoxPreference
android:title="@string/pref_adaptive_rate_control" android:title="@string/pref_adaptive_rate_control"

View file

@ -106,6 +106,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
private static final int PERMISSIONS_REQUEST_CONTACTS = 208; private static final int PERMISSIONS_REQUEST_CONTACTS = 208;
private static final int PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER = 209; private static final int PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER = 209;
private static final int PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE = 210; private static final int PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE = 210;
private static final int PERMISSIONS_RECORD_AUDIO_ECHO_TESTER = 211;
private static LinphoneActivity instance; private static LinphoneActivity instance;
@ -1172,6 +1173,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
public void checkAndRequestRecordAudioPermissionForEchoCanceller() { public void checkAndRequestRecordAudioPermissionForEchoCanceller() {
checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER); checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER);
} }
public void checkAndRequestRecordAudioPermissionsForEchoTester() {
checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_RECORD_AUDIO_ECHO_TESTER);
}
public void checkAndRequestReadExternalStoragePermissionForDeviceRingtone() { public void checkAndRequestReadExternalStoragePermissionForDeviceRingtone() {
checkAndRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE); checkAndRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE);
@ -1251,6 +1256,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
case PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE: case PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE:
((SettingsFragment) fragment).enableDeviceRingtone(grantResults[0] == PackageManager.PERMISSION_GRANTED); ((SettingsFragment) fragment).enableDeviceRingtone(grantResults[0] == PackageManager.PERMISSION_GRANTED);
break; break;
case PERMISSIONS_RECORD_AUDIO_ECHO_TESTER:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
((SettingsFragment) fragment).startEchoTester();
break;
} }
} }

View file

@ -114,6 +114,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.Toast; import android.widget.Toast;
/** /**
@ -146,6 +147,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
private String basePath; private String basePath;
private static boolean sExited; private static boolean sExited;
private boolean mAudioFocused; private boolean mAudioFocused;
private boolean echoTesterIsRunning;
private int mLastNetworkType=-1; private int mLastNetworkType=-1;
private ConnectivityManager mConnectivityManager; private ConnectivityManager mConnectivityManager;
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
@ -167,6 +169,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
protected LinphoneManager(final Context c) { protected LinphoneManager(final Context c) {
sExited = false; sExited = false;
echoTesterIsRunning = false;
mServiceContext = c; mServiceContext = c;
basePath = c.getFilesDir().getAbsolutePath(); basePath = c.getFilesDir().getAbsolutePath();
mLPConfigXsd = basePath + "/lpconfig.xsd"; mLPConfigXsd = basePath + "/lpconfig.xsd";
@ -223,8 +226,8 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
mCodecDownloader = LinphoneCoreFactory.instance().createOpenH264DownloadHelper(); mCodecDownloader = LinphoneCoreFactory.instance().createOpenH264DownloadHelper();
mCodecListener = new OpenH264DownloadHelperListener() { mCodecListener = new OpenH264DownloadHelperListener() {
ProgressDialog progress; ProgressDialog progress;
int box = 1;
int ctxt = 0; int ctxt = 0;
int box = 1;
@Override @Override
public void OnProgress(final int current, final int max) { public void OnProgress(final int current, final int max) {
@ -246,8 +249,10 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
progress.dismiss(); progress.dismiss();
progress = null; progress = null;
LinphoneManager.getLc().reloadMsPlugins(null); LinphoneManager.getLc().reloadMsPlugins(null);
if (ohcodec.getUserDataSize() > box && ohcodec.getUserData(box) != null) if (ohcodec.getUserDataSize() > box && ohcodec.getUserData(box) != null) {
((CheckBoxPreference)ohcodec.getUserData(box)).setSummary(mCodecDownloader.getLicenseMessage()); ((CheckBoxPreference) ohcodec.getUserData(box)).setSummary(mCodecDownloader.getLicenseMessage());
((CheckBoxPreference) ohcodec.getUserData(box)).setTitle("OpenH264");
}
} }
} }
}); });
@ -1154,6 +1159,42 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0); mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
} }
public int startEchoTester() throws LinphoneCoreException {
routeAudioToSpeaker();
Compatibility.setAudioManagerInCallMode((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE));
Log.i("Set audio mode on 'Voice Communication'");
int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);
int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);
int sampleRate = 0;
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0);
String sampleRateProperty = mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
sampleRate = Integer.parseInt(sampleRateProperty);
int status = mLc.startEchoTester(sampleRate);
if (status > 0)
echoTesterIsRunning = true;
else {
echoTesterIsRunning = false;
routeAudioToReceiver();
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE)).setMode(AudioManager.MODE_NORMAL);
Log.i("Set audio mode on 'Normal'");
}
return status;
}
public int stopEchoTester() throws LinphoneCoreException {
echoTesterIsRunning = false;
int status = mLc.stopEchoTester();
routeAudioToReceiver();
((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE)).setMode(AudioManager.MODE_NORMAL);
Log.i("Set audio mode on 'Normal'");
return status;
}
public boolean getEchoTesterStatus() {
return echoTesterIsRunning;
}
private boolean isRinging; private boolean isRinging;
private void requestAudioFocus(){ private void requestAudioFocus(){

View file

@ -41,6 +41,7 @@ import org.linphone.ui.LedPreference;
import org.linphone.ui.PreferencesListFragment; import org.linphone.ui.PreferencesListFragment;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.FragmentManager;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.Manifest; import android.Manifest;
import android.content.Context; import android.content.Context;
@ -611,6 +612,46 @@ public class SettingsFragment extends PreferencesListFragment {
return true; return true;
} }
}); });
findPreference(getString(R.string.pref_echo_tester_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
synchronized (SettingsFragment.this) {
int recordAudio = getActivity().getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getActivity().getPackageName());
if (recordAudio == PackageManager.PERMISSION_GRANTED) {
if (LinphoneManager.getInstance().getEchoTesterStatus())
stopEchoTester();
else
startEchoTester();
} else {
LinphoneActivity.instance().checkAndRequestRecordAudioPermissionsForEchoTester();
}
}
return true;
}
});
}
public void startEchoTester() {
Preference preference = findPreference(getString(R.string.pref_echo_tester_key));
try {
if (LinphoneManager.getInstance().startEchoTester() > 0) {
preference.setSummary("Is running");
}
} catch (LinphoneCoreException e) {
e.printStackTrace();
}
}
public void stopEchoTester() {
Preference preference = findPreference(getString(R.string.pref_echo_tester_key));
try {
if (LinphoneManager.getInstance().stopEchoTester() > 0) {
preference.setSummary("Is stopped");
}
} catch (LinphoneCoreException e) {
e.printStackTrace();
}
} }
public void startEchoCancellerCalibration() { public void startEchoCancellerCalibration() {
@ -642,7 +683,9 @@ public class SettingsFragment extends PreferencesListFragment {
codecs.removeAll(); codecs.removeAll();
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
final OpenH264DownloadHelper mCodecDownloader = LinphoneManager.getInstance().getOpenH264DownloadHelper(); final OpenH264DownloadHelper mCodecDownloader = LinphoneManager.getInstance().getOpenH264DownloadHelper();
for (final PayloadType pt : lc.getVideoCodecs()) { for (final PayloadType pt : lc.getVideoCodecs()) {
final CheckBoxPreference codec = new CheckBoxPreference(getActivity()); final CheckBoxPreference codec = new CheckBoxPreference(getActivity());
codec.setTitle(pt.getMime()); codec.setTitle(pt.getMime());
@ -659,8 +702,10 @@ public class SettingsFragment extends PreferencesListFragment {
} }
} }
} }
if (pt.getMime().equals("H264") && mCodecDownloader.isCodecFound()) if (pt.getMime().equals("H264") && mCodecDownloader.isCodecFound()) {
codec.setSummary(mCodecDownloader.getLicenseMessage()); codec.setSummary(mCodecDownloader.getLicenseMessage());
codec.setTitle("OpenH264");
}
codec.setChecked(lc.isPayloadTypeEnabled(pt)); codec.setChecked(lc.isPayloadTypeEnabled(pt));
codec.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { codec.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@ -670,9 +715,9 @@ public class SettingsFragment extends PreferencesListFragment {
try { try {
if (enable && Version.getCpuAbis().contains("armeabi-v7a") && !Version.getCpuAbis().contains("x86") if (enable && Version.getCpuAbis().contains("armeabi-v7a") && !Version.getCpuAbis().contains("x86")
&& pt.getMime().equals("H264") && !mCodecDownloader.isCodecFound()) { && pt.getMime().equals("H264") && !mCodecDownloader.isCodecFound()) {
LinphoneManager.getInstance().getOpenH264DownloadHelper().setOpenH264HelperListener(LinphoneManager.getInstance().getOpenH264HelperListener()); mCodecDownloader.setOpenH264HelperListener(LinphoneManager.getInstance().getOpenH264HelperListener());
LinphoneManager.getInstance().getOpenH264DownloadHelper().setUserData(0,LinphoneManager.getInstance().getContext()); mCodecDownloader.setUserData(0,LinphoneManager.getInstance().getContext());
LinphoneManager.getInstance().getOpenH264DownloadHelper().setUserData(1,codec); mCodecDownloader.setUserData(1,codec);
AlertDialog.Builder builder = new AlertDialog.Builder(LinphoneManager.getInstance().getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(LinphoneManager.getInstance().getContext());
builder.setCancelable(false); builder.setCancelable(false);
@ -703,7 +748,6 @@ public class SettingsFragment extends PreferencesListFragment {
codecs.addPreference(codec); codecs.addPreference(codec);
} }
((CheckBoxPreference) findPreference(getString(R.string.pref_video_enable_key))).setChecked(mPrefs.isVideoEnabled()); ((CheckBoxPreference) findPreference(getString(R.string.pref_video_enable_key))).setChecked(mPrefs.isVideoEnabled());
((CheckBoxPreference) findPreference(getString(R.string.pref_video_use_front_camera_key))).setChecked(mPrefs.useFrontCam()); ((CheckBoxPreference) findPreference(getString(R.string.pref_video_use_front_camera_key))).setChecked(mPrefs.useFrontCam());
((CheckBoxPreference) findPreference(getString(R.string.pref_video_initiate_call_with_video_key))).setChecked(mPrefs.shouldInitiateVideoCall()); ((CheckBoxPreference) findPreference(getString(R.string.pref_video_initiate_call_with_video_key))).setChecked(mPrefs.shouldInitiateVideoCall());
@ -1189,9 +1233,11 @@ public class SettingsFragment extends PreferencesListFragment {
} }
} }
@Override @Override
public void onPause() { public void onPause() {
if (LinphoneManager.getInstance().getEchoTesterStatus())
stopEchoTester();
LinphoneActivity.instance().hideTopBar(); LinphoneActivity.instance().hideTopBar();
super.onPause(); super.onPause();
} }

View file

@ -478,7 +478,10 @@ public class StatusFragment extends Fragment {
PayloadType payloadAudio = params.getUsedAudioCodec(); PayloadType payloadAudio = params.getUsedAudioCodec();
PayloadType payloadVideo = params.getUsedVideoCodec(); PayloadType payloadVideo = params.getUsedVideoCodec();
if (payloadVideo != null && payloadAudio != null) { if (payloadVideo != null && payloadAudio != null) {
codec.setText(payloadVideo.getMime() + " / " + payloadAudio.getMime() + (payloadAudio.getRate() / 1000)); String videoMime = payloadVideo.getMime();
if (payloadVideo.getMime().equals("H264") && LinphoneManager.getInstance().getOpenH264DownloadHelper().isCodecFound())
videoMime = "OpenH264";
codec.setText(videoMime + " / " + payloadAudio.getMime() + (payloadAudio.getRate() / 1000));
} }
dl.setText(String.valueOf((int) videoStats.getDownloadBandwidth()) + " / " + (int) audioStats.getDownloadBandwidth() + " kbits/s"); dl.setText(String.valueOf((int) videoStats.getDownloadBandwidth()) + " / " + (int) audioStats.getDownloadBandwidth() + " kbits/s");
ul.setText(String.valueOf((int) videoStats.getUploadBandwidth()) + " / " + (int) audioStats.getUploadBandwidth() + " kbits/s"); ul.setText(String.valueOf((int) videoStats.getUploadBandwidth()) + " / " + (int) audioStats.getUploadBandwidth() + " kbits/s");