/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.bluetooth; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothVcp; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.UserHandle; import android.telephony.TelephonyManager; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.settingslib.R; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.UUID; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth * API and dispatches the event on the UI thread to the right class in the * Settings. */ public class BluetoothEventManager { private static final String TAG = "BluetoothEventManager"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final LocalBluetoothAdapter mLocalAdapter; private final CachedBluetoothDeviceManager mDeviceManager; private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter; private final Map mHandlerMap; private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BroadcastReceiver mProfileBroadcastReceiver = new BluetoothBroadcastReceiver(); private final Collection mCallbacks = new CopyOnWriteArrayList<>(); private final android.os.Handler mReceiverHandler; private final UserHandle mUserHandle; private final Context mContext; private final String ACT_BROADCAST_SOURCE_INFO = "android.bluetooth.BroadcastAudioSAManager.action.BROADCAST_SOURCE_INFO"; interface Handler { void onReceive(Context context, Intent intent, BluetoothDevice device); } /** * Creates BluetoothEventManager with the ability to pass in {@link UserHandle} that tells it to * listen for bluetooth events for that particular userHandle. * *

If passing in userHandle that's different from the user running the process, * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission is required. If * userHandle passed in is {@code null}, we register event receiver for the * {@code context.getUser()} handle. */ BluetoothEventManager(LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, Context context, android.os.Handler handler, @Nullable UserHandle userHandle) { mLocalAdapter = adapter; mDeviceManager = deviceManager; mAdapterIntentFilter = new IntentFilter(); mProfileIntentFilter = new IntentFilter(); mHandlerMap = new HashMap<>(); mContext = context; mUserHandle = userHandle; mReceiverHandler = handler; // Bluetooth on/off broadcasts addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler()); // Generic connected/not broadcast addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED, new ConnectionStateChangedHandler()); // Discovery broadcasts addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true)); addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false)); addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler()); addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler()); addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler()); // Pairing broadcasts addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler()); // Fine-grained state broadcasts addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler()); addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler()); addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler()); addHandler(BluetoothHeadset.ACTION_HF_TWSP_BATTERY_STATE_CHANGED , new TwspBatteryLevelChangedHandler()); // Active device broadcasts addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler()); addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler()); addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler()); // Headset state changed broadcasts addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED, new AudioModeChangedHandler()); addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED, new AudioModeChangedHandler()); // ACL connection changed broadcasts addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler()); addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler()); addHandler(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED, new A2dpCodecConfigChangedHandler()); Object sourceInfoHandler = null; try { Class classSourceInfoHandler = Class.forName("com.android.settingslib.bluetooth.BroadcastSourceInfoHandler"); Constructor ctor; ctor = classSourceInfoHandler.getDeclaredConstructor( new Class[] {CachedBluetoothDeviceManager.class}); sourceInfoHandler = ctor.newInstance(mDeviceManager); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } if (sourceInfoHandler != null) { Log.d(TAG, "adding SourceInfo Handler"); addHandler(ACT_BROADCAST_SOURCE_INFO, (Handler)sourceInfoHandler); } // Broadcast broadcasts addHandler("android.bluetooth.broadcast.profile.action.BROADCAST_STATE_CHANGED", new BroadcastStateChangedHandler()); addHandler("android.bluetooth.broadcast.profile.action.BROADCAST_ENCRYPTION_KEY_GENERATED", new BroadcastKeyGeneratedHandler()); // VCP state changed broadcasts addHandler(BluetoothVcp.ACTION_CONNECTION_MODE_CHANGED, new VcpModeChangedHandler()); addHandler(BluetoothVcp.ACTION_VOLUME_CHANGED, new VcpVolumeChangedHandler()); registerAdapterIntentReceiver(); } /** Register to start receiving callbacks for Bluetooth events. */ public void registerCallback(BluetoothCallback callback) { mCallbacks.add(callback); } /** Unregister to stop receiving callbacks for Bluetooth events. */ public void unregisterCallback(BluetoothCallback callback) { mCallbacks.remove(callback); } @VisibleForTesting void registerProfileIntentReceiver() { registerIntentReceiver(mProfileBroadcastReceiver, mProfileIntentFilter); } @VisibleForTesting void registerAdapterIntentReceiver() { registerIntentReceiver(mBroadcastReceiver, mAdapterIntentFilter); } /** * Registers the provided receiver to receive the broadcasts that correspond to the * passed intent filter, in the context of the provided handler. */ private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) { if (mUserHandle == null) { // If userHandle has not been provided, simply call registerReceiver. mContext.registerReceiver(receiver, filter, null, mReceiverHandler); } else { // userHandle was explicitly specified, so need to call multi-user aware API. mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler); } } @VisibleForTesting void addProfileHandler(String action, Handler handler) { mHandlerMap.put(action, handler); mProfileIntentFilter.addAction(action); } boolean readPairedDevices() { Set bondedDevices = mLocalAdapter.getBondedDevices(); if (bondedDevices == null) { return false; } boolean deviceAdded = false; for (BluetoothDevice device : bondedDevices) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { mDeviceManager.addDevice(device); deviceAdded = true; } } return deviceAdded; } void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) { for (BluetoothCallback callback : mCallbacks) { callback.onDeviceAdded(cachedDevice); } } void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) { for (BluetoothCallback callback : mCallbacks) { callback.onDeviceDeleted(cachedDevice); } } void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state, int bluetoothProfile) { for (BluetoothCallback callback : mCallbacks) { callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); } } private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { for (BluetoothCallback callback : mCallbacks) { callback.onConnectionStateChanged(cachedDevice, state); } } private void dispatchAudioModeChanged() { for (CachedBluetoothDevice cachedDevice : mDeviceManager.getCachedDevicesCopy()) { cachedDevice.onAudioModeChanged(); } for (BluetoothCallback callback : mCallbacks) { callback.onAudioModeChanged(); } } private void dispatchBroadcastStateChanged(int state) { for (BluetoothCallback callback : mCallbacks) { callback.onBroadcastStateChanged(state); } } private void dispatchBroadcastKeyGenerated() { for (BluetoothCallback callback : mCallbacks) { callback.onBroadcastKeyGenerated(); } } @VisibleForTesting void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { for (CachedBluetoothDevice cachedDevice : mDeviceManager.getCachedDevicesCopy()) { boolean isActive = Objects.equals(cachedDevice, activeDevice); cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile); } for (BluetoothCallback callback : mCallbacks) { callback.onActiveDeviceChanged(activeDevice, bluetoothProfile); } } private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice, int state) { for (BluetoothCallback callback : mCallbacks) { callback.onAclConnectionStateChanged(activeDevice, state); } } private void dispatchA2dpCodecConfigChanged(CachedBluetoothDevice cachedDevice, BluetoothCodecStatus codecStatus) { for (BluetoothCallback callback : mCallbacks) { callback.onA2dpCodecConfigChanged(cachedDevice, codecStatus); } } protected void dispatchNewGroupFound( CachedBluetoothDevice cachedDevice, int groupId, UUID setPrimaryServiceUuid) { synchronized(mCallbacks) { updateCacheDeviceInfo(groupId, cachedDevice); for (BluetoothCallback callback : mCallbacks) { callback.onNewGroupFound(cachedDevice, groupId, setPrimaryServiceUuid); } } } protected void dispatchGroupDiscoveryStatusChanged(int groupId, int status, int reason) { synchronized(mCallbacks) { for (BluetoothCallback callback : mCallbacks) { callback.onGroupDiscoveryStatusChanged(groupId, status, reason); } } } @VisibleForTesting void addHandler(String action, Handler handler) { mHandlerMap.put(action, handler); mAdapterIntentFilter.addAction(action); } private class BluetoothBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Handler handler = mHandlerMap.get(action); if (handler != null) { handler.onReceive(context, intent, device); } } } private class AdapterStateChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); // update local profiles and get paired devices mLocalAdapter.setBluetoothStateInt(state); // send callback to update UI and possibly start scanning for (BluetoothCallback callback : mCallbacks) { callback.onBluetoothStateChanged(state); } // Inform CachedDeviceManager that the adapter state has changed mDeviceManager.onBluetoothStateChanged(state); } } private class ScanningStateChangedHandler implements Handler { private final boolean mStarted; ScanningStateChangedHandler(boolean started) { mStarted = started; } public void onReceive(Context context, Intent intent, BluetoothDevice device) { for (BluetoothCallback callback : mCallbacks) { callback.onScanningStateChanged(mStarted); } mDeviceManager.onScanningStateChanged(mStarted); } } private class DeviceFoundHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE); String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); // TODO Pick up UUID. They should be available for 2.1 devices. // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1. CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { cachedDevice = mDeviceManager.addDevice(device); Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice"); } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED && !cachedDevice.getDevice().isConnected()) { // Dispatch device add callback to show bonded but // not connected devices in discovery mode dispatchDeviceAdded(cachedDevice); } cachedDevice.setRssi(rssi); cachedDevice.setJustDiscovered(true); } } private class ConnectionStateChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR); dispatchConnectionStateChanged(cachedDevice, state); } } private class BroadcastStateChangedHandler implements Handler { //@Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR); dispatchBroadcastStateChanged(state); } } private class BroadcastKeyGeneratedHandler implements Handler { //@Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { dispatchBroadcastKeyGenerated(); } } private class NameChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { mDeviceManager.onDeviceNameUpdated(device); } } private class BondStateChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { if (device == null) { Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); return; } int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR); CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { Log.w(TAG, "Got bonding state changed for " + device + ", but we have no record of that device."); cachedDevice = mDeviceManager.addDevice(device); } if(bondState == BluetoothDevice.BOND_BONDED) { int groupId = intent.getIntExtra(BluetoothDevice.EXTRA_GROUP_ID, BluetoothDevice.ERROR); if (groupId != BluetoothDevice.ERROR && groupId >= 0) { updateCacheDeviceInfo(groupId, cachedDevice); } else if (intent.getBooleanExtra(BluetoothDevice.EXTRA_IS_PRIVATE_ADDRESS, false)) { /* * Do not show private address in UI, just ignore assuming remaining * events will receive on public address (connection, disconnection) */ Log.d(TAG, "Hide showing private address in UI " + cachedDevice); updateIgnoreDeviceFlag(cachedDevice); } } for (BluetoothCallback callback : mCallbacks) { callback.onDeviceBondStateChanged(cachedDevice, bondState); } cachedDevice.onBondingStateChanged(bondState); if (bondState == BluetoothDevice.BOND_NONE) { /* Check if we need to remove other Hearing Aid devices */ if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) { mDeviceManager.onDeviceUnpaired(cachedDevice); } int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.ERROR); showUnbondMessage(context, cachedDevice.getName(), reason); } } /** * Called when we have reached the unbonded state. * * @param reason one of the error reasons from * BluetoothDevice.UNBOND_REASON_* */ private void showUnbondMessage(Context context, String name, int reason) { if (DEBUG) { Log.d(TAG, "showUnbondMessage() name : " + name + ", reason : " + reason); } int errorMsg; switch (reason) { case BluetoothDevice.UNBOND_REASON_AUTH_FAILED: errorMsg = R.string.bluetooth_pairing_pin_error_message; break; case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED: errorMsg = R.string.bluetooth_pairing_rejected_error_message; break; case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN: errorMsg = R.string.bluetooth_pairing_device_down_error_message; break; case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS: case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT: case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS: case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED: errorMsg = R.string.bluetooth_pairing_error_message; break; default: Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason); return; } BluetoothUtils.showError(context, name, errorMsg); } } private class ClassChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { cachedDevice.refresh(); } } } private class UuidChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { cachedDevice.onUuidChanged(); } } } private class BatteryLevelChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { cachedDevice.refresh(); } } } private class TwspBatteryLevelChangedHandler implements Handler { public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { cachedDevice.mTwspBatteryState = intent.getIntExtra( BluetoothHeadset.EXTRA_HF_TWSP_BATTERY_STATE, -1); cachedDevice.mTwspBatteryLevel = intent.getIntExtra( BluetoothHeadset.EXTRA_HF_TWSP_BATTERY_LEVEL, -1); Log.i(TAG, cachedDevice + ": mTwspBatteryState: " + cachedDevice.mTwspBatteryState + "mTwspBatteryLevel: " + cachedDevice.mTwspBatteryLevel); cachedDevice.refresh(); } } } private class ActiveDeviceChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { String action = intent.getAction(); if (action == null) { Log.w(TAG, "ActiveDeviceChangedHandler: action is null"); return; } CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device); int bluetoothProfile = 0; if (Objects.equals(action, BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) { bluetoothProfile = BluetoothProfile.A2DP; } else if (Objects.equals(action, BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) { bluetoothProfile = BluetoothProfile.HEADSET; } else if (Objects.equals(action, BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED)) { bluetoothProfile = BluetoothProfile.HEARING_AID; } else { Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action); return; } dispatchActiveDeviceChanged(activeDevice, bluetoothProfile); } } private class AclStateChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { if (device == null) { Log.w(TAG, "AclStateChangedHandler: device is null"); return; } // Avoid to notify Settings UI for Hearing Aid sub device. if (mDeviceManager.isSubDevice(device)) { return; } final String action = intent.getAction(); if (action == null) { Log.w(TAG, "AclStateChangedHandler: action is null"); return; } final CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device); if (activeDevice == null) { Log.w(TAG, "AclStateChangedHandler: activeDevice is null"); return; } final int state; switch (action) { case BluetoothDevice.ACTION_ACL_CONNECTED: state = BluetoothAdapter.STATE_CONNECTED; break; case BluetoothDevice.ACTION_ACL_DISCONNECTED: state = BluetoothAdapter.STATE_DISCONNECTED; break; default: Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action); return; } dispatchAclStateChanged(activeDevice, state); } } private class AudioModeChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { final String action = intent.getAction(); if (action == null) { Log.w(TAG, "AudioModeChangedHandler() action is null"); return; } dispatchAudioModeChanged(); } } private class A2dpCodecConfigChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { final String action = intent.getAction(); if (action == null) { Log.w(TAG, "A2dpCodecConfigChangedHandler: action is null"); return; } CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { Log.w(TAG, "A2dpCodecConfigChangedHandler: device is null"); return; } BluetoothCodecStatus codecStatus = intent.getParcelableExtra( BluetoothCodecStatus.EXTRA_CODEC_STATUS); Log.d(TAG, "A2dpCodecConfigChangedHandler: device=" + device + ", codecStatus=" + codecStatus); dispatchA2dpCodecConfigChanged(cachedDevice, codecStatus); } } private class VcpModeChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); int mode = intent.getIntExtra(BluetoothVcp.EXTRA_MODE, 0); if (cachedDevice != null) { Log.i(TAG, cachedDevice + " Vcp connection mode change to " + mode); cachedDevice.refresh(); } } } private class VcpVolumeChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { Log.i(TAG, cachedDevice + " Vcp volume change"); cachedDevice.refresh(); } } } private void updateCacheDeviceInfo(int groupId, CachedBluetoothDevice cachedDevice) { BluetoothDevice device = cachedDevice.getDevice(); boolean isGroup = cachedDevice.isGroupDevice(); Log.d(TAG, "updateCacheDeviceInfo groupId " + groupId + ", cachedDevice :" + cachedDevice + ", name :" + cachedDevice.getName() +" isGroup :" + isGroup + " groupId " + cachedDevice.getGroupId()); if (isGroup) { if (groupId != cachedDevice.getGroupId()) { Log.d(TAG, "groupId mismatch ignore" + cachedDevice.getGroupId()); return; } Log.d(TAG, "updateCacheDeviceInfo update ignored "); } else { cachedDevice.setDeviceType(groupId); } } private void updateIgnoreDeviceFlag(CachedBluetoothDevice cachedDevice) { cachedDevice.setDeviceType(CachedBluetoothDevice.PRIVATE_ADDR); } }