private boolean addDevicePreference(CachedBluetoothDevice cachedDevice) {
    ParcelUuid[] uuids = cachedDevice.getDevice().getUuids();
    BluetoothClass bluetoothClass = cachedDevice.getDevice().getBluetoothClass();

    switch (mFilterType) {
      case BluetoothDevicePicker.FILTER_TYPE_TRANSFER:
        if (uuids != null)
          if (BluetoothUuid.containsAnyUuid(uuids, LocalBluetoothProfileManager.OPP_PROFILE_UUIDS))
            return true;
        if (bluetoothClass != null && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_OPP)) {
          return true;
        }
        break;
      case BluetoothDevicePicker.FILTER_TYPE_AUDIO:
        if (uuids != null) {
          if (BluetoothUuid.containsAnyUuid(uuids, LocalBluetoothProfileManager.A2DP_PROFILE_UUIDS))
            return true;

          if (BluetoothUuid.containsAnyUuid(
              uuids, LocalBluetoothProfileManager.HEADSET_PROFILE_UUIDS)) return true;
        } else if (bluetoothClass != null) {
          if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) return true;

          if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) return true;
        }
        break;
      default:
        return true;
    }
    return false;
  }
  @Override
  public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {

    if (KEY_BT_SCAN.equals(preference.getKey())) {
      mLocalManager.startScanning(true);
      return true;
    }

    if (preference instanceof BluetoothDevicePreference) {
      BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
      if (mScreenType == SCREEN_TYPE_SETTINGS) {
        btPreference.getCachedDevice().onClicked();
      } else if (mScreenType == SCREEN_TYPE_DEVICEPICKER) {
        CachedBluetoothDevice device = btPreference.getCachedDevice();

        mSelectedDevice = device.getDevice();
        mLocalManager.stopScanning();
        mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress());
        if ((device.getBondState() == BluetoothDevice.BOND_BONDED) || (mNeedAuth == false)) {
          sendDevicePickedIntent(mSelectedDevice);
          finish();
        } else {
          btPreference.getCachedDevice().onClicked();
        }
      }
      return true;
    }

    return super.onPreferenceTreeClick(preferenceScreen, preference);
  }
 /**
  * Search for existing {@link CachedBluetoothDevice} or return null if this device isn't in the
  * cache. Use {@link #addDevice} to create and return a new {@link CachedBluetoothDevice} for a
  * newly discovered {@link BluetoothDevice}.
  *
  * @param device the address of the Bluetooth device
  * @return the cached device object for this device, or null if it has not been previously seen
  */
 CachedBluetoothDevice findDevice(BluetoothDevice device) {
   for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
     if (cachedDevice.getDevice().equals(device)) {
       return cachedDevice;
     }
   }
   return null;
 }
  @Override
  public boolean onContextItemSelected(MenuItem item) {
    CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(item.getMenuInfo());
    if (cachedDevice == null) return false;

    cachedDevice.onContextItemSelected(item);
    return true;
  }
 public synchronized void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
   Log.d(TAG, "onDeviceDeleted");
   if (cachedDevice != null
       && cachedDevice.getBondState() == BluetoothDevice.BOND_NONE
       && cachedDevice.isRemovable()) {
     mCachedDevices.remove(cachedDevice);
   }
 }
 private synchronized void connectIfEnabled(BluetoothDevice device) {
   CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device);
   List<LocalBluetoothProfile> profiles = cachedDevice.getConnectableProfiles();
   for (LocalBluetoothProfile profile : profiles) {
     if (profile.getPreferred(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
       cachedDevice.connect(false);
       return;
     }
   }
 }
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    // For device picker, disable Context Menu
    if (mScreenType != SCREEN_TYPE_SETTINGS) {
      return;
    }
    CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(menuInfo);
    if (cachedDevice == null) return;

    cachedDevice.onCreateContextMenu(menu);
  }
  /**
   * Attempts to get the name of a remote device, otherwise returns the address.
   *
   * @param device The remote device.
   * @return The name, or if unavailable, the address.
   */
  public String getName(BluetoothDevice device) {
    CachedBluetoothDevice cachedDevice = findDevice(device);
    if (cachedDevice != null) {
      return cachedDevice.getName();
    }

    String name = device.getAliasName();
    if (name != null) {
      return name;
    }

    return device.getAddress();
  }
 private synchronized void handleUndocked(BluetoothDevice device) {
   mRunnable = null;
   mProfileManager.removeServiceListener(this);
   if (mDialog != null) {
     mDialog.dismiss();
     mDialog = null;
   }
   mDevice = null;
   mPendingDevice = null;
   if (device != null) {
     CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device);
     cachedDevice.disconnect();
   }
 }
 public synchronized void onScanningStateChanged(boolean started) {
   // If starting a new scan, clear old visibility
   // Iterate in reverse order since devices may be removed.
   for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
     CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
     if (started) {
       cachedDevice.setVisible(false);
     } else if (!started
         && cachedDevice.getBondState() == BluetoothDevice.BOND_NONE
         && cachedDevice.isRemovable()) {
       mCachedDevices.remove(cachedDevice);
     }
   }
 }
 public synchronized void onBluetoothStateChanged(int bluetoothState) {
   // When Bluetooth is turning off, we need to clear the non-bonded devices
   // Otherwise, they end up showing up on the next BT enable
   if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
     for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
       CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
       if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
         cachedDevice.setVisible(false);
         mCachedDevices.remove(i);
       } else {
         // For bonded devices, we need to clear the connection status so that
         // when BT is enabled next time, device connection status shall be retrieved
         // by making a binder call.
         cachedDevice.clearProfileConnectionState();
       }
     }
   }
 }
  synchronized boolean hasOtherConnectedDevices(BluetoothDevice dock) {
    Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy();
    Set<BluetoothDevice> btDevices = mLocalAdapter.getBondedDevices();
    if (btDevices == null || cachedDevices == null || btDevices.isEmpty()) {
      return false;
    }
    if (DEBUG) {
      Log.d(TAG, "btDevices = " + btDevices.size());
      Log.d(TAG, "cachedDeviceUIs = " + cachedDevices.size());
    }

    for (CachedBluetoothDevice deviceUI : cachedDevices) {
      BluetoothDevice btDevice = deviceUI.getDevice();
      if (!btDevice.equals(dock) && btDevices.contains(btDevice) && deviceUI.isConnected()) {
        if (DEBUG) Log.d(TAG, "connected deviceUI = " + deviceUI.getName());
        return true;
      }
    }
    return false;
  }
  /**
   * @return true user had made a choice, this method replies to the request according to user's
   *     previous decision false user hadnot made any choice on this device
   */
  private boolean checkUserChoice() {
    boolean processed = false;

    // we only remember PHONEBOOK permission
    if (mRequestType != BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) {
      return processed;
    }

    LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(mContext);
    CachedBluetoothDeviceManager cachedDeviceManager = bluetoothManager.getCachedDeviceManager();
    CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);

    if (cachedDevice == null) {
      cachedDevice =
          cachedDeviceManager.addDevice(
              bluetoothManager.getBluetoothAdapter(),
              bluetoothManager.getProfileManager(),
              mDevice);
    }

    int phonebookPermission = cachedDevice.getPhonebookPermissionChoice();

    if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_UNKNOWN) {
      return processed;
    }

    String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY;
    if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_ALLOWED) {
      sendIntentToReceiver(intentName, true, BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
      processed = true;
    } else if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_REJECTED) {
      sendIntentToReceiver(
          intentName, false, null, false // dummy value, no effect since previous param is null
          );
      processed = true;
    } else {
      Log.e(TAG, "Bad phonebookPermission: " + phonebookPermission);
    }
    return processed;
  }
  private synchronized void handleUnexpectedDisconnect(
      BluetoothDevice disconnectedDevice, LocalBluetoothProfile profile, int startId) {
    if (DEBUG) {
      Log.d(TAG, "handling failed connect for " + disconnectedDevice);
    }

    // Reconnect if docked.
    if (disconnectedDevice != null) {
      // registerReceiver can't be called from a BroadcastReceiver
      Intent intent = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
      if (intent != null) {
        int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
        if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
          BluetoothDevice dockedDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
          if (dockedDevice != null && dockedDevice.equals(disconnectedDevice)) {
            CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(dockedDevice);
            cachedDevice.connectProfile(profile);
          }
        }
      }
    }

    DockEventReceiver.finishStartingService(this, startId);
  }
  private synchronized void applyBtSettings(BluetoothDevice device, int startId) {
    if (device == null || mProfiles == null || mCheckedItems == null || mLocalAdapter == null) {
      return;
    }

    // Turn on BT if something is enabled
    for (boolean enable : mCheckedItems) {
      if (enable) {
        int btState = mLocalAdapter.getBluetoothState();
        if (DEBUG) {
          Log.d(TAG, "BtState = " + btState);
        }
        // May have race condition as the phone comes in and out and in the dock.
        // Always turn on BT
        mLocalAdapter.enable();

        // if adapter was previously OFF, TURNING_OFF, or TURNING_ON
        if (btState != BluetoothAdapter.STATE_ON) {
          if (mPendingDevice != null && mPendingDevice.equals(mDevice)) {
            return;
          }

          mPendingDevice = device;
          mPendingStartId = startId;
          if (btState != BluetoothAdapter.STATE_TURNING_ON) {
            getPrefs().edit().putBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, true).apply();
          }
          return;
        }
      }
    }

    mPendingDevice = null;

    boolean callConnect = false;
    CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device);
    for (int i = 0; i < mProfiles.length; i++) {
      LocalBluetoothProfile profile = mProfiles[i];
      if (DEBUG) Log.d(TAG, profile.toString() + " = " + mCheckedItems[i]);

      if (mCheckedItems[i]) {
        // Checked but not connected
        callConnect = true;
      } else if (!mCheckedItems[i]) {
        // Unchecked, may or may not be connected.
        int status = profile.getConnectionStatus(cachedDevice.getDevice());
        if (status == BluetoothProfile.STATE_CONNECTED) {
          if (DEBUG) Log.d(TAG, "applyBtSettings - Disconnecting");
          cachedDevice.disconnect(mProfiles[i]);
        }
      }
      profile.setPreferred(device, mCheckedItems[i]);
      if (DEBUG) {
        if (mCheckedItems[i] != profile.isPreferred(device)) {
          Log.e(TAG, "Can't save preferred value");
        }
      }
    }

    if (callConnect) {
      if (DEBUG) Log.d(TAG, "applyBtSettings - Connecting");
      cachedDevice.connect(false);
    }
  }
 public synchronized void onUuidChanged(BluetoothDevice device) {
   CachedBluetoothDevice cachedDevice = findDevice(device);
   if (cachedDevice != null) {
     cachedDevice.onUuidChanged();
   }
 }
 public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
   cachedDevice.setVisible(false);
   return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
 }
 public void onDeviceNameUpdated(BluetoothDevice device) {
   CachedBluetoothDevice cachedDevice = findDevice(device);
   if (cachedDevice != null) {
     cachedDevice.refreshName();
   }
 }
 public synchronized void onBtClassChanged(BluetoothDevice device) {
   CachedBluetoothDevice cachedDevice = findDevice(device);
   if (cachedDevice != null) {
     cachedDevice.refreshBtClass();
   }
 }