Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java

Issue 99033003: Enable platform echo cancellation through the AudioRecord path. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.media; 5 package org.chromium.media;
6 6
7 import android.bluetooth.BluetoothAdapter; 7 import android.bluetooth.BluetoothAdapter;
8 import android.bluetooth.BluetoothManager; 8 import android.bluetooth.BluetoothManager;
9 import android.content.BroadcastReceiver; 9 import android.content.BroadcastReceiver;
10 import android.content.ContentResolver; 10 import android.content.ContentResolver;
11 import android.content.Context; 11 import android.content.Context;
12 import android.content.Intent; 12 import android.content.Intent;
13 import android.content.IntentFilter; 13 import android.content.IntentFilter;
14 import android.content.pm.PackageManager; 14 import android.content.pm.PackageManager;
15 import android.database.ContentObserver; 15 import android.database.ContentObserver;
16 import android.media.audiofx.AcousticEchoCanceler;
16 import android.media.AudioFormat; 17 import android.media.AudioFormat;
17 import android.media.AudioManager; 18 import android.media.AudioManager;
18 import android.media.AudioRecord; 19 import android.media.AudioRecord;
19 import android.media.AudioTrack; 20 import android.media.AudioTrack;
20 import android.net.Uri; 21 import android.net.Uri;
21 import android.os.Build; 22 import android.os.Build;
22 import android.os.Handler; 23 import android.os.Handler;
23 import android.os.Looper; 24 import android.os.Looper;
24 import android.os.Process; 25 import android.os.Process;
25 import android.provider.Settings; 26 import android.provider.Settings;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 static final int STATE_BLUETOOTH_TURNING_OFF = 6; 105 static final int STATE_BLUETOOTH_TURNING_OFF = 6;
105 // TODO(henrika): document the valid state transitions. 106 // TODO(henrika): document the valid state transitions.
106 107
107 // Use 44.1kHz as the default sampling rate. 108 // Use 44.1kHz as the default sampling rate.
108 private static final int DEFAULT_SAMPLING_RATE = 44100; 109 private static final int DEFAULT_SAMPLING_RATE = 44100;
109 // Randomly picked up frame size which is close to return value on N4. 110 // Randomly picked up frame size which is close to return value on N4.
110 // Return this value when getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER) 111 // Return this value when getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
111 // fails. 112 // fails.
112 private static final int DEFAULT_FRAME_PER_BUFFER = 256; 113 private static final int DEFAULT_FRAME_PER_BUFFER = 256;
113 114
115 // List of device models which have been vetted for good quality platform
116 // echo cancellation.
117 private static final Set<String> PLATFORM_AEC_MODEL_WHITELIST =
henrika (OOO until Aug 14) 2013/12/06 12:52:21 Guess you can follow this example instead of using
ajm 2013/12/10 06:37:16 Done.
118 new HashSet<String>(Arrays.asList(new String[] {
119 "Nexus 5",
120 "Nexus 7"
121 }));
122
114 private final AudioManager mAudioManager; 123 private final AudioManager mAudioManager;
115 private final Context mContext; 124 private final Context mContext;
116 private final long mNativeAudioManagerAndroid; 125 private final long mNativeAudioManagerAndroid;
117 126
118 private boolean mHasBluetoothPermission = false; 127 private boolean mHasBluetoothPermission = false;
119 private boolean mIsInitialized = false; 128 private boolean mIsInitialized = false;
120 private boolean mSavedIsSpeakerphoneOn; 129 private boolean mSavedIsSpeakerphoneOn;
121 private boolean mSavedIsMicrophoneMute; 130 private boolean mSavedIsMicrophoneMute;
122 131
123 private Integer mAudioDeviceState = STATE_NO_DEVICE_SELECTED; 132 private Integer mAudioDeviceState = STATE_NO_DEVICE_SELECTED;
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 i++; 316 i++;
308 } 317 }
309 } 318 }
310 logd("getAudioInputDeviceNames: " + devices); 319 logd("getAudioInputDeviceNames: " + devices);
311 return array; 320 return array;
312 } 321 }
313 } 322 }
314 323
315 @CalledByNative 324 @CalledByNative
316 private int getNativeOutputSampleRate() { 325 private int getNativeOutputSampleRate() {
317 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.J ELLY_BEAN_MR1) { 326 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
318 String sampleRateString = mAudioManager.getProperty( 327 String sampleRateString = mAudioManager.getProperty(
319 AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); 328 AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
320 return (sampleRateString == null ? 329 return (sampleRateString == null ?
321 DEFAULT_SAMPLING_RATE : Integer.parseInt(sampleRateString)); 330 DEFAULT_SAMPLING_RATE : Integer.parseInt(sampleRateString));
322 } else { 331 } else {
323 return DEFAULT_SAMPLING_RATE; 332 return DEFAULT_SAMPLING_RATE;
324 } 333 }
325 } 334 }
326 335
327 /** 336 /**
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 380 }
372 381
373 @CalledByNative 382 @CalledByNative
374 private int getAudioLowLatencyOutputFrameSize() { 383 private int getAudioLowLatencyOutputFrameSize() {
375 String framesPerBuffer = 384 String framesPerBuffer =
376 mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PE R_BUFFER); 385 mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PE R_BUFFER);
377 return (framesPerBuffer == null ? 386 return (framesPerBuffer == null ?
378 DEFAULT_FRAME_PER_BUFFER : Integer.parseInt(framesPerBuffer)); 387 DEFAULT_FRAME_PER_BUFFER : Integer.parseInt(framesPerBuffer));
379 } 388 }
380 389
390 @CalledByNative
391 public static boolean isPlatformAECSupported() {
henrika (OOO until Aug 14) 2013/12/06 12:52:21 Would it make sense to name this API to something
ajm 2013/12/06 19:06:43 Except that most (all?) devices will actually repo
Ami GONE FROM CHROMIUM 2013/12/06 19:22:53 hasAcousticEchoCanceler fails to connote that this
ajm 2013/12/10 06:37:16 Sounds good.
392 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
393 // AcousticEchoCanceler was added in API level 16 (Jelly Bean).
Ami GONE FROM CHROMIUM 2013/12/06 19:22:53 Wouldn't this be accounted for by l.397?
ajm 2013/12/10 06:37:16 As I understand it, we'll get a crash if we try to
394 return false;
395 }
396
397 boolean isAvailable = AcousticEchoCanceler.isAvailable();
398 boolean isWhitelisted = PLATFORM_AEC_MODEL_WHITELIST.contains(Build.MODE L);
tommi (sloooow) - chröme 2013/12/06 12:11:34 nit: Since the list contains only two items, you p
ajm 2013/12/06 19:06:43 My initial implementation had all conditions in th
ajm 2013/12/10 06:37:16 Changed as recommended now.
399 logd("AcousticEchoCanceler.isAvailable: " + isAvailable);
400 logd("Build.MODEL: " + Build.MODEL + " isWhitelisted: " + isWhitelisted) ;
Ami GONE FROM CHROMIUM 2013/12/06 19:22:53 I don't think these are worth spamming logcat for.
ajm 2013/12/10 06:37:16 Done.
401 return isAvailable && isWhitelisted;
402 }
403
381 /** Sets the speaker phone mode. */ 404 /** Sets the speaker phone mode. */
382 public void setSpeakerphoneOn(boolean on) { 405 public void setSpeakerphoneOn(boolean on) {
383 boolean wasOn = mAudioManager.isSpeakerphoneOn(); 406 boolean wasOn = mAudioManager.isSpeakerphoneOn();
384 if (wasOn == on) { 407 if (wasOn == on) {
385 return; 408 return;
386 } 409 }
387 mAudioManager.setSpeakerphoneOn(on); 410 mAudioManager.setSpeakerphoneOn(on);
388 } 411 }
389 412
390 /** Sets the microphone mute state. */ 413 /** Sets the microphone mute state. */
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 } 619 }
597 } 620 }
598 621
599 private void logDeviceInfo() { 622 private void logDeviceInfo() {
600 Log.i(TAG, "Manufacturer:" + Build.MANUFACTURER + 623 Log.i(TAG, "Manufacturer:" + Build.MANUFACTURER +
601 " Board: " + Build.BOARD + " Device: " + Build.DEVICE + 624 " Board: " + Build.BOARD + " Device: " + Build.DEVICE +
602 " Model: " + Build.MODEL + " PRODUCT: " + Build.PRODUCT); 625 " Model: " + Build.MODEL + " PRODUCT: " + Build.PRODUCT);
603 } 626 }
604 627
605 /** Trivial helper method for debug logging */ 628 /** Trivial helper method for debug logging */
606 private void logd(String msg) { 629 private static void logd(String msg) {
607 Log.d(TAG, msg); 630 Log.d(TAG, msg);
608 } 631 }
609 632
610 /** Trivial helper method for error logging */ 633 /** Trivial helper method for error logging */
611 private void loge(String msg) { 634 private static void loge(String msg) {
612 Log.e(TAG, msg); 635 Log.e(TAG, msg);
613 } 636 }
614 637
615 private class SettingsObserver extends ContentObserver { 638 private class SettingsObserver extends ContentObserver {
616 SettingsObserver() { 639 SettingsObserver() {
617 super(new Handler()); 640 super(new Handler());
618 mContentResolver.registerContentObserver(Settings.System.CONTENT_URI , true, this); 641 mContentResolver.registerContentObserver(Settings.System.CONTENT_URI , true, this);
619 } 642 }
620 643
621 @Override 644 @Override
(...skipping 19 matching lines...) Expand all
641 synchronized(mSettingsObserverLock) { 664 synchronized(mSettingsObserverLock) {
642 mSettingsObserver = new SettingsObserver(); 665 mSettingsObserver = new SettingsObserver();
643 mSettingsObserverLock.notify(); 666 mSettingsObserverLock.notify();
644 } 667 }
645 668
646 // Listen for volume change. 669 // Listen for volume change.
647 Looper.loop(); 670 Looper.loop();
648 } 671 }
649 } 672 }
650 } 673 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698