diff options
author | Eric Laurent <elaurent@google.com> | 2020-12-23 13:31:28 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-12-23 13:31:28 +0000 |
commit | b4d0c3785e7fd537dff671bbfaf0c0679783342b (patch) | |
tree | d41e738d6b42cf4abe295472af65fd63e738d033 | |
parent | cb629524ecfcfc801f70f84775fefec457bbf23b (diff) | |
parent | 10c636203057457a2f88e0c3b46298ec46cb8359 (diff) |
Merge changes from topic "comm_routing" am: 8553f77dce am: 10c6362030
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1534433
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: Ib8c5ace4fd7636db42e14523557604fb5d80542a
7 files changed, 163 insertions, 74 deletions
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1ca45fe9f70b..20e64ffe9471 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -294,20 +294,25 @@ static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env, return old; } -#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status)) +#define check_AudioSystem_Command(...) _check_AudioSystem_Command(__func__, __VA_ARGS__) -static int _check_AudioSystem_Command(const char* caller, status_t status) -{ - ALOGE_IF(status, "Command failed for %s: %d", caller, status); +static int _check_AudioSystem_Command(const char *caller, status_t status, + std::vector<status_t> ignoredErrors = {}) { + int jniStatus = kAudioStatusOk; switch (status) { case DEAD_OBJECT: - return kAudioStatusMediaServerDied; + jniStatus = kAudioStatusMediaServerDied; + break; case NO_ERROR: - return kAudioStatusOk; + break; default: + if (std::find(begin(ignoredErrors), end(ignoredErrors), status) == end(ignoredErrors)) { + jniStatus = kAudioStatusError; + } break; } - return kAudioStatusError; + ALOGE_IF(jniStatus != kAudioStatusOk, "Command failed for %s: %d", caller, status); + return jniStatus; } static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes, @@ -2381,9 +2386,12 @@ static jint android_media_AudioSystem_setDevicesRoleForStrategy(JNIEnv *env, job static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz, jint strategy, jint role) { - return (jint)check_AudioSystem_Command( - AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy, - (device_role_t)role)); + return (jint) + check_AudioSystem_Command(AudioSystem::removeDevicesRoleForStrategy((product_strategy_t) + strategy, + (device_role_t) + role), + {NAME_NOT_FOUND}); } static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz, diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java index 6c8b50037d3d..7caac899a603 100644 --- a/media/java/android/media/AudioDeviceAttributes.java +++ b/media/java/android/media/AudioDeviceAttributes.java @@ -120,7 +120,13 @@ public final class AudioDeviceAttributes implements Parcelable { mAddress = address; } - /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) { + /** + * @hide + * Constructor from internal device type and address + * @param type the internal device type, as defined in {@link AudioSystem} + * @param address the address of the device, or an empty string for devices without one + */ + public AudioDeviceAttributes(int nativeType, @NonNull String address) { mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT; mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType); mAddress = address; @@ -191,10 +197,8 @@ public final class AudioDeviceAttributes implements Parcelable { public String toString() { return new String("AudioDeviceAttributes:" + " role:" + roleToString(mRole) - + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName( - AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)) - : AudioSystem.getInputDeviceName( - AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))) + + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType) + : AudioSystem.getInputDeviceName(mNativeType)) + " addr:" + mAddress); } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index ef6ba065f414..18c8a72b165b 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1712,7 +1712,7 @@ public class AudioSystem int[] types = new int[devices.size()]; String[] addresses = new String[devices.size()]; for (int i = 0; i < devices.size(); ++i) { - types[i] = AudioDeviceInfo.convertDeviceTypeToInternalDevice(devices.get(i).getType()); + types[i] = devices.get(i).getInternalType(); addresses[i] = devices.get(i).getAddress(); } return setDevicesRoleForStrategy(strategy, role, types, addresses); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index f04c5eb030db..26f5c4ca1e80 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -16,6 +16,7 @@ package com.android.server.audio; import android.annotation.NonNull; +import android.annotation.Nullable; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; @@ -34,6 +35,7 @@ import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.ICommunicationDeviceDispatcher; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.MediaMetrics; +import android.media.audiopolicy.AudioProductStrategy; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -51,6 +53,7 @@ import android.util.PrintWriterPrinter; import com.android.internal.annotations.GuardedBy; import java.io.PrintWriter; +import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -77,7 +80,8 @@ import java.util.concurrent.atomic.AtomicBoolean; private final @NonNull Context mContext; /** Forced device usage for communications sent to AudioSystem */ - private int mForcedUseForComm; + private AudioDeviceAttributes mPreferredDeviceforComm; + private int mCommunicationStrategyId = -1; // Manages all connected devices, only ever accessed on the message loop private final AudioDeviceInventory mDeviceInventory; @@ -133,10 +137,23 @@ import java.util.concurrent.atomic.AtomicBoolean; init(); } + private void initCommunicationStrategyId() { + List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies(); + for (AudioProductStrategy strategy : strategies) { + if (strategy.getAudioAttributesForLegacyStreamType(AudioSystem.STREAM_VOICE_CALL) + != null) { + mCommunicationStrategyId = strategy.getId(); + return; + } + } + mCommunicationStrategyId = -1; + } + private void init() { setupMessaging(mContext); - mForcedUseForComm = AudioSystem.FORCE_NONE; + mPreferredDeviceforComm = null; + initCommunicationStrategyId(); } /*package*/ Context getContext() { @@ -221,8 +238,7 @@ import java.util.concurrent.atomic.AtomicBoolean; synchronized (mDeviceStateLock) { AudioDeviceAttributes device = null; if (on) { - device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, ""); + device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""); } else { CommunicationRouteClient client = getCommunicationRouteClientForPid(pid); if (client == null || !client.requestsSpeakerphone()) { @@ -275,6 +291,10 @@ import java.util.concurrent.atomic.AtomicBoolean; if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setCommunicationRouteForClient: device: " + device); } + AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( + "setCommunicationRouteForClient for pid: " + pid + + " device: " + device + + " from API: " + eventSource)).printLog(TAG)); final boolean wasBtScoRequested = isBluetoothScoRequested(); final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested(); @@ -393,7 +413,11 @@ import java.util.concurrent.atomic.AtomicBoolean; * @return true if speakerphone is active, false otherwise. */ /*package*/ boolean isSpeakerphoneOn() { - return getForcedUseForComm() == AudioSystem.FORCE_SPEAKER; + AudioDeviceAttributes device = getPreferredDeviceForComm(); + if (device == null) { + return false; + } + return device.getInternalType() == AudioSystem.DEVICE_OUT_SPEAKER; } /** @@ -560,7 +584,11 @@ import java.util.concurrent.atomic.AtomicBoolean; * @return true if Bluetooth SCO is active , false otherwise. */ /*package*/ boolean isBluetoothScoOn() { - return getForcedUseForComm() == AudioSystem.FORCE_BT_SCO; + AudioDeviceAttributes device = getPreferredDeviceForComm(); + if (device == null) { + return false; + } + return AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType()); } /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { @@ -612,8 +640,8 @@ import java.util.concurrent.atomic.AtomicBoolean; synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { - AudioDeviceAttributes device = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, ""); + AudioDeviceAttributes device = + new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""); setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource); } } @@ -643,10 +671,19 @@ import java.util.concurrent.atomic.AtomicBoolean; return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices); } + /*package*/ void postSetPreferredDevicesForStrategy(int strategy, + @NonNull List<AudioDeviceAttributes> devices) { + sendILMsgNoDelay(MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy, devices); + } + /*package*/ int removePreferredDevicesForStrategySync(int strategy) { return mDeviceInventory.removePreferredDevicesForStrategySync(strategy); } + /*package*/ void postRemovePreferredDevicesForStrategy(int strategy) { + sendIMsgNoDelay(MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy); + } + /*package*/ void registerStrategyPreferredDevicesDispatcher( @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher); @@ -971,9 +1008,12 @@ import java.util.concurrent.atomic.AtomicBoolean; pw.println(" " + prefix + "pid: " + cl.getPid() + " device: " + cl.getDevice() + " cb: " + cl.getBinder()); }); - pw.println("\n" + prefix + "mForcedUseForComm: " - + AudioSystem.forceUseConfigToString(mForcedUseForComm)); - pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid); + pw.println("\n" + prefix + "mPreferredDeviceforComm: " + + mPreferredDeviceforComm); + pw.println(prefix + "mCommunicationStrategyId: " + + mCommunicationStrategyId); + + pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid); mBtHelper.dump(pw, prefix); } @@ -1068,6 +1108,7 @@ import java.util.concurrent.atomic.AtomicBoolean; case MSG_RESTORE_DEVICES: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { + initCommunicationStrategyId(); mDeviceInventory.onRestoreDevices(); mBtHelper.onAudioServerDiedRestoreA2dp(); onUpdateCommunicationRoute("MSG_RESTORE_DEVICES"); @@ -1277,6 +1318,17 @@ import java.util.concurrent.atomic.AtomicBoolean; final int strategy = msg.arg1; mDeviceInventory.onSaveRemovePreferredDevices(strategy); } break; + case MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY: { + final int strategy = msg.arg1; + final List<AudioDeviceAttributes> devices = + (List<AudioDeviceAttributes>) msg.obj; + setPreferredDevicesForStrategySync(strategy, devices); + + } break; + case MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY: { + final int strategy = msg.arg1; + removePreferredDevicesForStrategySync(strategy); + } break; case MSG_CHECK_MUTE_MUSIC: checkMessagesMuteMusic(0); break; @@ -1369,7 +1421,8 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39; - + private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40; + private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41; private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { @@ -1609,16 +1662,25 @@ import java.util.concurrent.atomic.AtomicBoolean; * @return selected forced usage for communication. */ @GuardedBy("mDeviceStateLock") - private int getForcedUseForComm() { + @Nullable private AudioDeviceAttributes getPreferredDeviceForComm() { boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn(); - if (btSCoOn) { - return AudioSystem.FORCE_BT_SCO; + // Use the SCO device known to BtHelper so that it matches exactly + // what has been communicated to audio policy manager. The device + // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy + // APIs are used to start SCO audio. + AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice(); + if (device != null) { + return device; + } } - if (isSpeakerphoneRequested()) { - return AudioSystem.FORCE_SPEAKER; + AudioDeviceAttributes device = requestedCommunicationDevice(); + if (device == null + || AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType())) { + // Do not indicate BT SCO selection if SCO is requested but SCO is not ON + return null; } - return AudioSystem.FORCE_NONE; + return device; } /** @@ -1628,30 +1690,24 @@ import java.util.concurrent.atomic.AtomicBoolean; // @GuardedBy("mSetModeLock") @GuardedBy("mDeviceStateLock") private void onUpdateCommunicationRoute(String eventSource) { - mForcedUseForComm = getForcedUseForComm(); - + mPreferredDeviceforComm = getPreferredDeviceForComm(); if (AudioService.DEBUG_COMM_RTE) { - Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm - + " eventSource: " + eventSource); + Log.v(TAG, "onUpdateCommunicationRoute, mPreferredDeviceforComm: " + + mPreferredDeviceforComm + " eventSource: " + eventSource); } - if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { + if (mPreferredDeviceforComm == null + || !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains( + mPreferredDeviceforComm.getInternalType())) { + AudioSystem.setParameters("BT_SCO=off"); + } else { AudioSystem.setParameters("BT_SCO=on"); - setForceUse_Async( - AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource); - setForceUse_Async( - AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource); + } + if (mPreferredDeviceforComm == null) { + postRemovePreferredDevicesForStrategy(mCommunicationStrategyId); } else { - AudioSystem.setParameters("BT_SCO=off"); - setForceUse_Async( - AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); - if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { - setForceUse_Async( - AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER, eventSource); - } else { - setForceUse_Async( - AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource); - } + postSetPreferredDevicesForStrategy( + mCommunicationStrategyId, Arrays.asList(mPreferredDeviceforComm)); } mAudioService.postUpdateRingerModeServiceInt(); dispatchCommunicationDevice(); diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 33a8a30243de..82586b8f9b23 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -648,6 +648,10 @@ public class AudioDeviceInventory { /*package*/ int setPreferredDevicesForStrategySync(int strategy, @NonNull List<AudioDeviceAttributes> devices) { final long identity = Binder.clearCallingIdentity(); + + AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( + "setPreferredDevicesForStrategySync, strategy: " + strategy + + " devices: " + devices)).printLog(TAG)); final int status = mAudioSystem.setDevicesRoleForStrategy( strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices); Binder.restoreCallingIdentity(identity); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 2621e6994599..22a585fa9b41 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4972,8 +4972,7 @@ public class AudioService extends IAudioService.Stub switch (mPlatformType) { case AudioSystem.PLATFORM_VOICE: if (isInCommunication()) { - if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) - == AudioSystem.FORCE_BT_SCO) { + if (mDeviceBroker.isBluetoothScoOn()) { // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); return AudioSystem.STREAM_BLUETOOTH_SCO; } else { @@ -5009,8 +5008,7 @@ public class AudioService extends IAudioService.Stub } default: if (isInCommunication()) { - if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) - == AudioSystem.FORCE_BT_SCO) { + if (mDeviceBroker.isBluetoothScoOn()) { if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); return AudioSystem.STREAM_BLUETOOTH_SCO; } else { diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 354472da9286..c9a1fcf76f5b 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -27,6 +27,7 @@ import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.content.Intent; +import android.media.AudioDeviceAttributes; import android.media.AudioManager; import android.media.AudioSystem; import android.os.Binder; @@ -530,46 +531,64 @@ public class BtHelper { mDeviceBroker.postBroadcastScoConnectionState(state); } - private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) { - if (btDevice == null) { - return true; + @Nullable AudioDeviceAttributes getHeadsetAudioDevice() { + if (mBluetoothHeadsetDevice == null) { + return null; } + return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice); + } + + private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) { String address = btDevice.getAddress(); + if (!BluetoothAdapter.checkBluetoothAddress(address)) { + address = ""; + } BluetoothClass btClass = btDevice.getBluetoothClass(); - int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; - int[] outDeviceTypes = { - AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, - AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, - AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT - }; + int nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; if (btClass != null) { switch (btClass.getDeviceClass()) { case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: - outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET }; + nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; break; case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: - outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT }; + nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; break; } } - if (!BluetoothAdapter.checkBluetoothAddress(address)) { - address = ""; + if (AudioService.DEBUG_DEVICES) { + Log.i(TAG, "btHeadsetDeviceToAudioDevice btDevice: " + btDevice + + " btClass: " + (btClass == null ? "Unknown" : btClass) + + " nativeType: " + nativeType + " address: " + address); + } + return new AudioDeviceAttributes(nativeType, address); + } + + private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) { + if (btDevice == null) { + return true; } + int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; + AudioDeviceAttributes audioDevice = btHeadsetDeviceToAudioDevice(btDevice); String btDeviceName = getName(btDevice); boolean result = false; if (isActive) { - result |= mDeviceBroker.handleDeviceConnection( - isActive, outDeviceTypes[0], address, btDeviceName); + result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(), + audioDevice.getAddress(), btDeviceName); } else { + int[] outDeviceTypes = { + AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, + AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, + AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT + }; for (int outDeviceType : outDeviceTypes) { result |= mDeviceBroker.handleDeviceConnection( - isActive, outDeviceType, address, btDeviceName); + isActive, outDeviceType, audioDevice.getAddress(), btDeviceName); } } // handleDeviceConnection() && result to make sure the method get executed result = mDeviceBroker.handleDeviceConnection( - isActive, inDevice, address, btDeviceName) && result; + isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result; return result; } |