Loading android/app/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -360,6 +360,7 @@ android_app { "-Xep:OperatorPrecedence:ERROR", "-Xep:ReferenceEquality:ERROR", "-Xep:ReturnAtTheEndOfVoidFunction:ERROR", "-Xep:StaticAssignmentInConstructor:ERROR", "-Xep:StaticGuardedByInstance:ERROR", "-Xep:StringCaseLocaleUsage:ERROR", "-Xep:StringCharset:ERROR", Loading android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java +24 −22 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { @VisibleForTesting static final int AVRCP_MAX_VOL = 127; private static final int STREAM_MUSIC = AudioManager.STREAM_MUSIC; private static final int VOLUME_CHANGE_LOGGER_SIZE = 30; private static int sDeviceMaxVolume = 0; private static int sNewDeviceVolume = 0; private final int mDeviceMaxVolume; private final int mNewDeviceVolume; private final BluetoothEventLogger mVolumeEventLogger = new BluetoothEventLogger(VOLUME_CHANGE_LOGGER_SIZE, VOLUME_CHANGE_LOG_TITLE); Loading @@ -75,7 +75,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { // Absolute volume support map. HashMap<BluetoothDevice, Boolean> mDeviceMap = new HashMap(); // Volume stored is system volume (0 - {@code sDeviceMaxVolume}). // Volume stored is system volume (0 - {@code mDeviceMaxVolume}). HashMap<BluetoothDevice, Integer> mVolumeMap = new HashMap(); BluetoothDevice mCurrentDevice = null; Loading @@ -83,23 +83,25 @@ class AvrcpVolumeManager extends AudioDeviceCallback { /** * Converts given {@code avrcpVolume} (0 - 127) to equivalent in system volume (0 - {@code * sDeviceMaxVolume}). * mDeviceMaxVolume}). * * <p>Max system volume is retrieved from {@link AudioManager}. */ static int avrcpToSystemVolume(int avrcpVolume) { return (int) Math.round((double) avrcpVolume * sDeviceMaxVolume / AVRCP_MAX_VOL); @VisibleForTesting int avrcpToSystemVolume(int avrcpVolume) { return (int) Math.round((double) avrcpVolume * mDeviceMaxVolume / AVRCP_MAX_VOL); } /** * Converts given {@code deviceVolume} (0 - {@code sDeviceMaxVolume}) to equivalent in AVRCP * Converts given {@code deviceVolume} (0 - {@code mDeviceMaxVolume}) to equivalent in AVRCP * volume (0 - 127). * * <p>Max system volume is retrieved from {@link AudioManager}. */ static int systemToAvrcpVolume(int deviceVolume) { @VisibleForTesting int systemToAvrcpVolume(int deviceVolume) { int avrcpVolume = (int) Math.round((double) deviceVolume * AVRCP_MAX_VOL / sDeviceMaxVolume); (int) Math.round((double) deviceVolume * AVRCP_MAX_VOL / mDeviceMaxVolume); if (avrcpVolume > 127) avrcpVolume = 127; return avrcpVolume; } Loading Loading @@ -149,7 +151,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { }); // Get the current system volume and try to get the preference volume int savedVolume = getVolume(device, sNewDeviceVolume); int savedVolume = getVolume(device, mNewDeviceVolume); d("switchVolumeDevice: savedVolume=" + savedVolume); Loading @@ -175,8 +177,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { mAdapterService = adapterService; mAudioManager = audioManager; mNativeInterface = nativeInterface; sDeviceMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); sNewDeviceVolume = sDeviceMaxVolume / 2; mDeviceMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mNewDeviceVolume = mDeviceMaxVolume / 2; mAudioManager.registerAudioDeviceCallback(this, null); Loading @@ -202,7 +204,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Stores system volume (0 - {@code sDeviceMaxVolume}) for device in {@code mVolumeMap} and * Stores system volume (0 - {@code mDeviceMaxVolume}) for device in {@code mVolumeMap} and * writes the map in the {@link SharedPreferences}. */ synchronized void storeVolumeForDevice(@NonNull BluetoothDevice device, int storeVolume) { Loading @@ -224,7 +226,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Retrieves system volume (0 - {@code sDeviceMaxVolume}) and calls {@link * Retrieves system volume (0 - {@code mDeviceMaxVolume}) and calls {@link * #storeVolumeForDevice(BluetoothDevice, int)} with {@code device}. */ synchronized void storeVolumeForDevice(@NonNull BluetoothDevice device) { Loading @@ -251,7 +253,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Returns system volume (0 - {@code sDeviceMaxVolume}) stored in {@code mVolumeMap} for * Returns system volume (0 - {@code mDeviceMaxVolume}) stored in {@code mVolumeMap} for * corresponding {@code device}. * * @param defaultValue Value to return if device is not in the map. Loading @@ -266,9 +268,9 @@ class AvrcpVolumeManager extends AudioDeviceCallback { return mVolumeMap.get(device); } /** Returns the system volume (0 - {@code sDeviceMaxVolume}) applied to a new device */ /** Returns the system volume (0 - {@code mDeviceMaxVolume}) applied to a new device */ public int getNewDeviceVolume() { return sNewDeviceVolume; return mNewDeviceVolume; } /** Loading @@ -289,8 +291,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { + avrcpVolume + " deviceVolume=" + deviceVolume + " sDeviceMaxVolume=" + sDeviceMaxVolume); + " mDeviceMaxVolume=" + mDeviceMaxVolume); mAudioManager.setStreamVolume( AudioManager.STREAM_MUSIC, deviceVolume, Loading @@ -304,7 +306,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { * * <p>See {@link #systemToAvrcpVolume}. * * @param deviceVolume in range (0 - {@code sDeviceMaxVolume}) received from system. * @param deviceVolume in range (0 - {@code mDeviceMaxVolume}) received from system. */ void sendVolumeChanged(@NonNull BluetoothDevice device, int deviceVolume) { if (deviceVolume == getVolume(device, -1)) { Loading @@ -321,8 +323,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { + avrcpVolume + " deviceVolume=" + deviceVolume + " sDeviceMaxVolume=" + sDeviceMaxVolume); + " mDeviceMaxVolume=" + mDeviceMaxVolume); mNativeInterface.sendVolumeChanged(device, avrcpVolume); storeVolumeForDevice(device); } Loading android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java +49 −3 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -67,6 +68,12 @@ import java.util.UUID; public class HeadsetClientService extends ProfileService { private static final String TAG = HeadsetClientService.class.getSimpleName(); // Maximum number of devices we can try connecting to in one session private static final int MAX_STATE_MACHINES_POSSIBLE = 100; @VisibleForTesting static final int MAX_HFP_SCO_VOICE_CALL_VOLUME = 15; // HFP 1.5 spec. @VisibleForTesting static final int MIN_HFP_SCO_VOICE_CALL_VOLUME = 1; // HFP 1.5 spec. // This is also used as a lock for shared data in {@link HeadsetClientService} @GuardedBy("mStateMachineMap") private final HashMap<BluetoothDevice, HeadsetClientStateMachine> mStateMachineMap = Loading @@ -81,8 +88,9 @@ public class HeadsetClientService extends ProfileService { private final AudioManager mAudioManager; private BatteryManager mBatteryManager = null; private int mLastBatteryLevel = -1; // Maximum number of devices we can try connecting to in one session private static final int MAX_STATE_MACHINES_POSSIBLE = 100; private final int mMaxAmVcVol; private final int mMinAmVcVol; private final Object mStartStopLock = new Object(); Loading @@ -93,6 +101,8 @@ public class HeadsetClientService extends ProfileService { mAdapterService = adapterService; mDatabaseManager = requireNonNull(adapterService.getDatabase()); mAudioManager = requireNonNull(getSystemService(AudioManager.class)); mMaxAmVcVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); mMinAmVcVol = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); } public static boolean isEnabled() { Loading Loading @@ -188,6 +198,42 @@ public class HeadsetClientService extends ProfileService { } } int hfToAmVol(int hfVol) { int amRange = mMaxAmVcVol - mMinAmVcVol; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int amVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { amVol = (int) Math.round( (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) * ((double) amRange / hfRange)) + mMinAmVcVol; } else { int amOffset = (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange; amVol = mMinAmVcVol + amOffset; } Log.d(TAG, "HF -> AM " + hfVol + " " + amVol); return amVol; } @VisibleForTesting int amToHfVol(int amVol) { int amRange = (mMaxAmVcVol > mMinAmVcVol) ? (mMaxAmVcVol - mMinAmVcVol) : 1; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int hfVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { hfVol = (int) Math.round((amVol - mMinAmVcVol) * ((double) hfRange / amRange)) + MIN_HFP_SCO_VOICE_CALL_VOLUME; } else { int hfOffset = (hfRange * (amVol - mMinAmVcVol)) / amRange; hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset; } Log.d(TAG, "AM -> HF " + amVol + " " + hfVol); return hfVol; } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override Loading @@ -210,7 +256,7 @@ public class HeadsetClientService extends ProfileService { if (streamType == AudioManager.STREAM_VOICE_CALL) { int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); int hfVol = HeadsetClientStateMachine.amToHfVol(streamValue); int hfVol = amToHfVol(streamValue); Log.d( TAG, "Setting volume to audio manager: " Loading android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +3 −48 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.HeadsetService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IState; Loading Loading @@ -118,9 +117,6 @@ public class HeadsetClientStateMachine extends StateMachine { @VisibleForTesting static final int CONNECTING_TIMEOUT_MS = 10000; // 10s private static final int ROUTING_DELAY_MS = 250; @VisibleForTesting static final int MAX_HFP_SCO_VOICE_CALL_VOLUME = 15; // HFP 1.5 spec. @VisibleForTesting static final int MIN_HFP_SCO_VOICE_CALL_VOLUME = 1; // HFP 1.5 spec. static final int HF_ORIGINATED_CALL_ID = -1; private static final long OUTGOING_TIMEOUT_MILLI = 10 * 1000; // 10 seconds private static final long QUERY_CURRENT_CALLS_WAIT_MILLIS = 2 * 1000; // 2 seconds Loading Loading @@ -154,9 +150,6 @@ public class HeadsetClientStateMachine extends StateMachine { private String mOperatorName; @VisibleForTesting String mSubscriberInfo; private static int sMaxAmVcVol; private static int sMinAmVcVol; // queue of send actions (pair action, action_data) @VisibleForTesting ArrayDeque<Pair<Integer, Object>> mQueuedActions; Loading Loading @@ -927,9 +920,6 @@ public class HeadsetClientStateMachine extends StateMachine { mIndicatorNetworkSignal = 0; mIndicatorBatteryLevel = 0; sMaxAmVcVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); sMinAmVcVol = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); mOperatorName = null; mSubscriberInfo = null; Loading Loading @@ -1010,41 +1000,6 @@ public class HeadsetClientStateMachine extends StateMachine { mAudioFocusRequest = null; } static int hfToAmVol(int hfVol) { int amRange = sMaxAmVcVol - sMinAmVcVol; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int amVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { amVol = (int) Math.round( (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) * ((double) amRange / hfRange)) + sMinAmVcVol; } else { int amOffset = (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange; amVol = sMinAmVcVol + amOffset; } Log.d(TAG, "HF -> AM " + hfVol + " " + amVol); return amVol; } static int amToHfVol(int amVol) { int amRange = (sMaxAmVcVol > sMinAmVcVol) ? (sMaxAmVcVol - sMinAmVcVol) : 1; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int hfVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { hfVol = (int) Math.round((amVol - sMinAmVcVol) * ((double) hfRange / amRange)) + MIN_HFP_SCO_VOICE_CALL_VOLUME; } else { int hfOffset = (hfRange * (amVol - sMinAmVcVol)) / amRange; hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset; } Log.d(TAG, "AM -> HF " + amVol + " " + hfVol); return hfVol; } class Disconnected extends State { @Override public void enter() { Loading Loading @@ -1528,7 +1483,7 @@ public class HeadsetClientStateMachine extends StateMachine { case SET_SPEAKER_VOLUME: // This message should always contain the volume in AudioManager max normalized. int amVol = message.arg1; int hfVol = amToHfVol(amVol); int hfVol = mService.amToHfVol(amVol); if (amVol != mCommandedSpeakerVolume) { debug("Volume" + amVol + ":" + mCommandedSpeakerVolume); // Volume was changed by a 3rd party Loading Loading @@ -1734,7 +1689,7 @@ public class HeadsetClientStateMachine extends StateMachine { break; case StackEvent.EVENT_TYPE_VOLUME_CHANGED: if (event.valueInt == HeadsetClientHalConstants.VOLUME_TYPE_SPK) { mCommandedSpeakerVolume = hfToAmVol(event.valueInt2); mCommandedSpeakerVolume = mService.hfToAmVol(event.valueInt2); debug("AM volume set to " + mCommandedSpeakerVolume); boolean show_volume = SystemProperties.getBoolean( Loading Loading @@ -1916,7 +1871,7 @@ public class HeadsetClientStateMachine extends StateMachine { // We need to set the volume after switching into HFP mode as some Audio HALs // reset the volume to a known-default on mode switch. final int amVol = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); final int hfVol = amToHfVol(amVol); final int hfVol = mService.amToHfVol(amVol); debug("hfp_enable=true mAudioSWB is " + mAudioSWB); debug("hfp_enable=true mAudioWbs is " + mAudioWbs); Loading android/app/src/com/android/bluetooth/mapclient/MnsService.java +13 −14 Original line number Diff line number Diff line Loading @@ -39,19 +39,18 @@ public class MnsService { static final int EVENT_REPORT = 1001; /* MAP version 1.4 */ private static final int MNS_VERSION = 0x0104; /* these are shared across instances */ private static SocketAcceptor sAcceptThread = null; private static ObexServerSockets sServerSockets = null; private static MapClientService sContext; private final SocketAcceptor mAcceptThread = new SocketAcceptor(); private ObexServerSockets mServerSockets; private MapClientService mContext; private volatile boolean mShutdown = false; // Used to interrupt socket accept thread private int mSdpHandle = -1; MnsService(MapClientService context) { Log.v(TAG, "MnsService()"); sContext = context; sAcceptThread = new SocketAcceptor(); sServerSockets = ObexServerSockets.create(sAcceptThread); mContext = context; mServerSockets = ObexServerSockets.create(mAcceptThread); SdpManagerNativeInterface nativeInterface = SdpManagerNativeInterface.getInstance(); if (!nativeInterface.isAvailable()) { Log.e(TAG, "SdpManagerNativeInterface is not available"); Loading @@ -60,8 +59,8 @@ public class MnsService { mSdpHandle = nativeInterface.createMapMnsRecord( "MAP Message Notification Service", sServerSockets.getRfcommChannel(), sServerSockets.getL2capPsm(), mServerSockets.getRfcommChannel(), mServerSockets.getL2capPsm(), MNS_VERSION, MasClient.MAP_SUPPORTED_FEATURES); } Loading @@ -70,9 +69,9 @@ public class MnsService { Log.v(TAG, "stop()"); mShutdown = true; cleanUpSdpRecord(); if (sServerSockets != null) { sServerSockets.shutdown(false); sServerSockets = null; if (mServerSockets != null) { mServerSockets.shutdown(false); mServerSockets = null; } } Loading Loading @@ -107,7 +106,7 @@ public class MnsService { @Override public synchronized void onAcceptFailed() { Log.e(TAG, "OnAcceptFailed"); sServerSockets = null; // Will cause a new to be created when calling start. mServerSockets = null; // Will cause a new to be created when calling start. if (mShutdown) { Log.e(TAG, "Failed to accept incoming connection - shutdown"); } Loading @@ -117,7 +116,7 @@ public class MnsService { public synchronized boolean onConnect(BluetoothDevice device, BluetoothSocket socket) { Log.d(TAG, "onConnect" + device + " SOCKET: " + socket); /* Signal to the service that we have received an incoming connection.*/ MceStateMachine stateMachine = sContext.getMceStateMachineForDevice(device); MceStateMachine stateMachine = mContext.getMceStateMachineForDevice(device); if (stateMachine == null) { Log.e( TAG, Loading Loading
android/app/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -360,6 +360,7 @@ android_app { "-Xep:OperatorPrecedence:ERROR", "-Xep:ReferenceEquality:ERROR", "-Xep:ReturnAtTheEndOfVoidFunction:ERROR", "-Xep:StaticAssignmentInConstructor:ERROR", "-Xep:StaticGuardedByInstance:ERROR", "-Xep:StringCaseLocaleUsage:ERROR", "-Xep:StringCharset:ERROR", Loading
android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java +24 −22 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { @VisibleForTesting static final int AVRCP_MAX_VOL = 127; private static final int STREAM_MUSIC = AudioManager.STREAM_MUSIC; private static final int VOLUME_CHANGE_LOGGER_SIZE = 30; private static int sDeviceMaxVolume = 0; private static int sNewDeviceVolume = 0; private final int mDeviceMaxVolume; private final int mNewDeviceVolume; private final BluetoothEventLogger mVolumeEventLogger = new BluetoothEventLogger(VOLUME_CHANGE_LOGGER_SIZE, VOLUME_CHANGE_LOG_TITLE); Loading @@ -75,7 +75,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { // Absolute volume support map. HashMap<BluetoothDevice, Boolean> mDeviceMap = new HashMap(); // Volume stored is system volume (0 - {@code sDeviceMaxVolume}). // Volume stored is system volume (0 - {@code mDeviceMaxVolume}). HashMap<BluetoothDevice, Integer> mVolumeMap = new HashMap(); BluetoothDevice mCurrentDevice = null; Loading @@ -83,23 +83,25 @@ class AvrcpVolumeManager extends AudioDeviceCallback { /** * Converts given {@code avrcpVolume} (0 - 127) to equivalent in system volume (0 - {@code * sDeviceMaxVolume}). * mDeviceMaxVolume}). * * <p>Max system volume is retrieved from {@link AudioManager}. */ static int avrcpToSystemVolume(int avrcpVolume) { return (int) Math.round((double) avrcpVolume * sDeviceMaxVolume / AVRCP_MAX_VOL); @VisibleForTesting int avrcpToSystemVolume(int avrcpVolume) { return (int) Math.round((double) avrcpVolume * mDeviceMaxVolume / AVRCP_MAX_VOL); } /** * Converts given {@code deviceVolume} (0 - {@code sDeviceMaxVolume}) to equivalent in AVRCP * Converts given {@code deviceVolume} (0 - {@code mDeviceMaxVolume}) to equivalent in AVRCP * volume (0 - 127). * * <p>Max system volume is retrieved from {@link AudioManager}. */ static int systemToAvrcpVolume(int deviceVolume) { @VisibleForTesting int systemToAvrcpVolume(int deviceVolume) { int avrcpVolume = (int) Math.round((double) deviceVolume * AVRCP_MAX_VOL / sDeviceMaxVolume); (int) Math.round((double) deviceVolume * AVRCP_MAX_VOL / mDeviceMaxVolume); if (avrcpVolume > 127) avrcpVolume = 127; return avrcpVolume; } Loading Loading @@ -149,7 +151,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { }); // Get the current system volume and try to get the preference volume int savedVolume = getVolume(device, sNewDeviceVolume); int savedVolume = getVolume(device, mNewDeviceVolume); d("switchVolumeDevice: savedVolume=" + savedVolume); Loading @@ -175,8 +177,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { mAdapterService = adapterService; mAudioManager = audioManager; mNativeInterface = nativeInterface; sDeviceMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); sNewDeviceVolume = sDeviceMaxVolume / 2; mDeviceMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mNewDeviceVolume = mDeviceMaxVolume / 2; mAudioManager.registerAudioDeviceCallback(this, null); Loading @@ -202,7 +204,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Stores system volume (0 - {@code sDeviceMaxVolume}) for device in {@code mVolumeMap} and * Stores system volume (0 - {@code mDeviceMaxVolume}) for device in {@code mVolumeMap} and * writes the map in the {@link SharedPreferences}. */ synchronized void storeVolumeForDevice(@NonNull BluetoothDevice device, int storeVolume) { Loading @@ -224,7 +226,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Retrieves system volume (0 - {@code sDeviceMaxVolume}) and calls {@link * Retrieves system volume (0 - {@code mDeviceMaxVolume}) and calls {@link * #storeVolumeForDevice(BluetoothDevice, int)} with {@code device}. */ synchronized void storeVolumeForDevice(@NonNull BluetoothDevice device) { Loading @@ -251,7 +253,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { } /** * Returns system volume (0 - {@code sDeviceMaxVolume}) stored in {@code mVolumeMap} for * Returns system volume (0 - {@code mDeviceMaxVolume}) stored in {@code mVolumeMap} for * corresponding {@code device}. * * @param defaultValue Value to return if device is not in the map. Loading @@ -266,9 +268,9 @@ class AvrcpVolumeManager extends AudioDeviceCallback { return mVolumeMap.get(device); } /** Returns the system volume (0 - {@code sDeviceMaxVolume}) applied to a new device */ /** Returns the system volume (0 - {@code mDeviceMaxVolume}) applied to a new device */ public int getNewDeviceVolume() { return sNewDeviceVolume; return mNewDeviceVolume; } /** Loading @@ -289,8 +291,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { + avrcpVolume + " deviceVolume=" + deviceVolume + " sDeviceMaxVolume=" + sDeviceMaxVolume); + " mDeviceMaxVolume=" + mDeviceMaxVolume); mAudioManager.setStreamVolume( AudioManager.STREAM_MUSIC, deviceVolume, Loading @@ -304,7 +306,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback { * * <p>See {@link #systemToAvrcpVolume}. * * @param deviceVolume in range (0 - {@code sDeviceMaxVolume}) received from system. * @param deviceVolume in range (0 - {@code mDeviceMaxVolume}) received from system. */ void sendVolumeChanged(@NonNull BluetoothDevice device, int deviceVolume) { if (deviceVolume == getVolume(device, -1)) { Loading @@ -321,8 +323,8 @@ class AvrcpVolumeManager extends AudioDeviceCallback { + avrcpVolume + " deviceVolume=" + deviceVolume + " sDeviceMaxVolume=" + sDeviceMaxVolume); + " mDeviceMaxVolume=" + mDeviceMaxVolume); mNativeInterface.sendVolumeChanged(device, avrcpVolume); storeVolumeForDevice(device); } Loading
android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java +49 −3 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -67,6 +68,12 @@ import java.util.UUID; public class HeadsetClientService extends ProfileService { private static final String TAG = HeadsetClientService.class.getSimpleName(); // Maximum number of devices we can try connecting to in one session private static final int MAX_STATE_MACHINES_POSSIBLE = 100; @VisibleForTesting static final int MAX_HFP_SCO_VOICE_CALL_VOLUME = 15; // HFP 1.5 spec. @VisibleForTesting static final int MIN_HFP_SCO_VOICE_CALL_VOLUME = 1; // HFP 1.5 spec. // This is also used as a lock for shared data in {@link HeadsetClientService} @GuardedBy("mStateMachineMap") private final HashMap<BluetoothDevice, HeadsetClientStateMachine> mStateMachineMap = Loading @@ -81,8 +88,9 @@ public class HeadsetClientService extends ProfileService { private final AudioManager mAudioManager; private BatteryManager mBatteryManager = null; private int mLastBatteryLevel = -1; // Maximum number of devices we can try connecting to in one session private static final int MAX_STATE_MACHINES_POSSIBLE = 100; private final int mMaxAmVcVol; private final int mMinAmVcVol; private final Object mStartStopLock = new Object(); Loading @@ -93,6 +101,8 @@ public class HeadsetClientService extends ProfileService { mAdapterService = adapterService; mDatabaseManager = requireNonNull(adapterService.getDatabase()); mAudioManager = requireNonNull(getSystemService(AudioManager.class)); mMaxAmVcVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); mMinAmVcVol = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); } public static boolean isEnabled() { Loading Loading @@ -188,6 +198,42 @@ public class HeadsetClientService extends ProfileService { } } int hfToAmVol(int hfVol) { int amRange = mMaxAmVcVol - mMinAmVcVol; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int amVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { amVol = (int) Math.round( (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) * ((double) amRange / hfRange)) + mMinAmVcVol; } else { int amOffset = (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange; amVol = mMinAmVcVol + amOffset; } Log.d(TAG, "HF -> AM " + hfVol + " " + amVol); return amVol; } @VisibleForTesting int amToHfVol(int amVol) { int amRange = (mMaxAmVcVol > mMinAmVcVol) ? (mMaxAmVcVol - mMinAmVcVol) : 1; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int hfVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { hfVol = (int) Math.round((amVol - mMinAmVcVol) * ((double) hfRange / amRange)) + MIN_HFP_SCO_VOICE_CALL_VOLUME; } else { int hfOffset = (hfRange * (amVol - mMinAmVcVol)) / amRange; hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset; } Log.d(TAG, "AM -> HF " + amVol + " " + hfVol); return hfVol; } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override Loading @@ -210,7 +256,7 @@ public class HeadsetClientService extends ProfileService { if (streamType == AudioManager.STREAM_VOICE_CALL) { int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); int hfVol = HeadsetClientStateMachine.amToHfVol(streamValue); int hfVol = amToHfVol(streamValue); Log.d( TAG, "Setting volume to audio manager: " Loading
android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +3 −48 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.HeadsetService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IState; Loading Loading @@ -118,9 +117,6 @@ public class HeadsetClientStateMachine extends StateMachine { @VisibleForTesting static final int CONNECTING_TIMEOUT_MS = 10000; // 10s private static final int ROUTING_DELAY_MS = 250; @VisibleForTesting static final int MAX_HFP_SCO_VOICE_CALL_VOLUME = 15; // HFP 1.5 spec. @VisibleForTesting static final int MIN_HFP_SCO_VOICE_CALL_VOLUME = 1; // HFP 1.5 spec. static final int HF_ORIGINATED_CALL_ID = -1; private static final long OUTGOING_TIMEOUT_MILLI = 10 * 1000; // 10 seconds private static final long QUERY_CURRENT_CALLS_WAIT_MILLIS = 2 * 1000; // 2 seconds Loading Loading @@ -154,9 +150,6 @@ public class HeadsetClientStateMachine extends StateMachine { private String mOperatorName; @VisibleForTesting String mSubscriberInfo; private static int sMaxAmVcVol; private static int sMinAmVcVol; // queue of send actions (pair action, action_data) @VisibleForTesting ArrayDeque<Pair<Integer, Object>> mQueuedActions; Loading Loading @@ -927,9 +920,6 @@ public class HeadsetClientStateMachine extends StateMachine { mIndicatorNetworkSignal = 0; mIndicatorBatteryLevel = 0; sMaxAmVcVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); sMinAmVcVol = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); mOperatorName = null; mSubscriberInfo = null; Loading Loading @@ -1010,41 +1000,6 @@ public class HeadsetClientStateMachine extends StateMachine { mAudioFocusRequest = null; } static int hfToAmVol(int hfVol) { int amRange = sMaxAmVcVol - sMinAmVcVol; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int amVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { amVol = (int) Math.round( (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) * ((double) amRange / hfRange)) + sMinAmVcVol; } else { int amOffset = (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange; amVol = sMinAmVcVol + amOffset; } Log.d(TAG, "HF -> AM " + hfVol + " " + amVol); return amVol; } static int amToHfVol(int amVol) { int amRange = (sMaxAmVcVol > sMinAmVcVol) ? (sMaxAmVcVol - sMinAmVcVol) : 1; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; int hfVol = 0; if (Flags.headsetClientAmHfVolumeSymmetric()) { hfVol = (int) Math.round((amVol - sMinAmVcVol) * ((double) hfRange / amRange)) + MIN_HFP_SCO_VOICE_CALL_VOLUME; } else { int hfOffset = (hfRange * (amVol - sMinAmVcVol)) / amRange; hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset; } Log.d(TAG, "AM -> HF " + amVol + " " + hfVol); return hfVol; } class Disconnected extends State { @Override public void enter() { Loading Loading @@ -1528,7 +1483,7 @@ public class HeadsetClientStateMachine extends StateMachine { case SET_SPEAKER_VOLUME: // This message should always contain the volume in AudioManager max normalized. int amVol = message.arg1; int hfVol = amToHfVol(amVol); int hfVol = mService.amToHfVol(amVol); if (amVol != mCommandedSpeakerVolume) { debug("Volume" + amVol + ":" + mCommandedSpeakerVolume); // Volume was changed by a 3rd party Loading Loading @@ -1734,7 +1689,7 @@ public class HeadsetClientStateMachine extends StateMachine { break; case StackEvent.EVENT_TYPE_VOLUME_CHANGED: if (event.valueInt == HeadsetClientHalConstants.VOLUME_TYPE_SPK) { mCommandedSpeakerVolume = hfToAmVol(event.valueInt2); mCommandedSpeakerVolume = mService.hfToAmVol(event.valueInt2); debug("AM volume set to " + mCommandedSpeakerVolume); boolean show_volume = SystemProperties.getBoolean( Loading Loading @@ -1916,7 +1871,7 @@ public class HeadsetClientStateMachine extends StateMachine { // We need to set the volume after switching into HFP mode as some Audio HALs // reset the volume to a known-default on mode switch. final int amVol = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); final int hfVol = amToHfVol(amVol); final int hfVol = mService.amToHfVol(amVol); debug("hfp_enable=true mAudioSWB is " + mAudioSWB); debug("hfp_enable=true mAudioWbs is " + mAudioWbs); Loading
android/app/src/com/android/bluetooth/mapclient/MnsService.java +13 −14 Original line number Diff line number Diff line Loading @@ -39,19 +39,18 @@ public class MnsService { static final int EVENT_REPORT = 1001; /* MAP version 1.4 */ private static final int MNS_VERSION = 0x0104; /* these are shared across instances */ private static SocketAcceptor sAcceptThread = null; private static ObexServerSockets sServerSockets = null; private static MapClientService sContext; private final SocketAcceptor mAcceptThread = new SocketAcceptor(); private ObexServerSockets mServerSockets; private MapClientService mContext; private volatile boolean mShutdown = false; // Used to interrupt socket accept thread private int mSdpHandle = -1; MnsService(MapClientService context) { Log.v(TAG, "MnsService()"); sContext = context; sAcceptThread = new SocketAcceptor(); sServerSockets = ObexServerSockets.create(sAcceptThread); mContext = context; mServerSockets = ObexServerSockets.create(mAcceptThread); SdpManagerNativeInterface nativeInterface = SdpManagerNativeInterface.getInstance(); if (!nativeInterface.isAvailable()) { Log.e(TAG, "SdpManagerNativeInterface is not available"); Loading @@ -60,8 +59,8 @@ public class MnsService { mSdpHandle = nativeInterface.createMapMnsRecord( "MAP Message Notification Service", sServerSockets.getRfcommChannel(), sServerSockets.getL2capPsm(), mServerSockets.getRfcommChannel(), mServerSockets.getL2capPsm(), MNS_VERSION, MasClient.MAP_SUPPORTED_FEATURES); } Loading @@ -70,9 +69,9 @@ public class MnsService { Log.v(TAG, "stop()"); mShutdown = true; cleanUpSdpRecord(); if (sServerSockets != null) { sServerSockets.shutdown(false); sServerSockets = null; if (mServerSockets != null) { mServerSockets.shutdown(false); mServerSockets = null; } } Loading Loading @@ -107,7 +106,7 @@ public class MnsService { @Override public synchronized void onAcceptFailed() { Log.e(TAG, "OnAcceptFailed"); sServerSockets = null; // Will cause a new to be created when calling start. mServerSockets = null; // Will cause a new to be created when calling start. if (mShutdown) { Log.e(TAG, "Failed to accept incoming connection - shutdown"); } Loading @@ -117,7 +116,7 @@ public class MnsService { public synchronized boolean onConnect(BluetoothDevice device, BluetoothSocket socket) { Log.d(TAG, "onConnect" + device + " SOCKET: " + socket); /* Signal to the service that we have received an incoming connection.*/ MceStateMachine stateMachine = sContext.getMceStateMachineForDevice(device); MceStateMachine stateMachine = mContext.getMceStateMachineForDevice(device); if (stateMachine == null) { Log.e( TAG, Loading