// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/bluetooth/bluetooth_adapter_mac.h"

#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothHostController.h>
#include <stddef.h>

#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/mac/mac_util.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/task_traits.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "device/bluetooth/bluetooth_adapter_mac_metrics.h"
#include "device/bluetooth/bluetooth_advertisement_mac.h"
#include "device/bluetooth/bluetooth_classic_device_mac.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_discovery_session_outcome.h"
#include "device/bluetooth/bluetooth_low_energy_central_manager_delegate.h"
#include "device/bluetooth/bluetooth_low_energy_device_watcher_mac.h"
#include "device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h"
#include "device/bluetooth/bluetooth_socket_mac.h"

extern "C" {
// Undocumented IOBluetooth Preference API [1]. Used by `blueutil` [2] and
// `Karabiner` [3] to programmatically control the Bluetooth state. Calling the
// method with `1` powers the adapter on, calling it with `0` powers it off.
// Using this API has the same effect as turning Bluetooth on or off using the
// macOS System Preferences [4], and will effect all adapters.
//
// [1] https://goo.gl/Gbjm1x
// [2] http://www.frederikseiffert.de/blueutil/
// [3] https://pqrs.org/osx/karabiner/
// [4] https://support.apple.com/kb/PH25091
void IOBluetoothPreferenceSetControllerPowerState(int state);
}

namespace {

// The frequency with which to poll the adapter for updates.
const int kPollIntervalMs = 500;

bool IsDeviceSystemPaired(const std::string& device_address) {
  IOBluetoothDevice* device = [IOBluetoothDevice
      deviceWithAddressString:base::SysUTF8ToNSString(device_address)];
  return device && [device isPaired];
}

}  // namespace

namespace device {

CBCentralManagerState GetCBManagerState(CBCentralManager* manager) {
#if defined(MAC_OS_X_VERSION_10_13)
  return static_cast<CBCentralManagerState>([manager state]);
#else
  return [manager state];
#endif
}

// static
base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
    InitCallback init_callback) {
  return BluetoothAdapterMac::CreateAdapter();
}

// static
base::WeakPtr<BluetoothAdapterMac> BluetoothAdapterMac::CreateAdapter() {
  BluetoothAdapterMac* adapter = new BluetoothAdapterMac();
  adapter->Init();
  return adapter->weak_ptr_factory_.GetWeakPtr();
}

// static
base::WeakPtr<BluetoothAdapterMac> BluetoothAdapterMac::CreateAdapterForTest(
    std::string name,
    std::string address,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
  BluetoothAdapterMac* adapter = new BluetoothAdapterMac();
  adapter->InitForTest(ui_task_runner);
  adapter->name_ = name;
  adapter->should_update_name_ = false;
  adapter->address_ = address;
  return adapter->weak_ptr_factory_.GetWeakPtr();
}

// static
BluetoothUUID BluetoothAdapterMac::BluetoothUUIDWithCBUUID(CBUUID* uuid) {
  // UUIDString only available OS X >= 10.10.
  if (@available(macOS 10.10, *)) {
    std::string uuid_c_string = base::SysNSStringToUTF8([uuid UUIDString]);
    return device::BluetoothUUID(uuid_c_string);
  } else {
    DCHECK(false);
    return {};
  }
}

// static
std::string BluetoothAdapterMac::String(NSError* error) {
  if (!error) {
    return "no error";
  }
  return std::string("error domain: ") + base::SysNSStringToUTF8(error.domain) +
         ", code: " + std::to_string(error.code) + ", description: " +
         base::SysNSStringToUTF8(error.localizedDescription);
}

BluetoothAdapterMac::BluetoothAdapterMac()
    : BluetoothAdapter(),
      classic_powered_(false),
      num_discovery_sessions_(0),
      controller_state_function_(
          base::BindRepeating(&BluetoothAdapterMac::GetHostControllerState,
                              base::Unretained(this))),
      power_state_function_(
          base::BindRepeating(IOBluetoothPreferenceSetControllerPowerState)),
      should_update_name_(true),
      classic_discovery_manager_(
          BluetoothDiscoveryManagerMac::CreateClassic(this)),
      device_paired_status_callback_(
          base::BindRepeating(&IsDeviceSystemPaired)),
      weak_ptr_factory_(this) {
  if (IsLowEnergyAvailable()) {
    low_energy_discovery_manager_.reset(
        BluetoothLowEnergyDiscoveryManagerMac::Create(this));
    low_energy_central_manager_delegate_.reset(
        [[BluetoothLowEnergyCentralManagerDelegate alloc]
            initWithDiscoveryManager:low_energy_discovery_manager_.get()
                          andAdapter:this]);
    low_energy_central_manager_.reset([[CBCentralManager alloc]
        initWithDelegate:low_energy_central_manager_delegate_
                   queue:dispatch_get_main_queue()]);
    low_energy_discovery_manager_->SetCentralManager(
        low_energy_central_manager_);

    low_energy_advertisement_manager_.reset(
        new BluetoothLowEnergyAdvertisementManagerMac());
    low_energy_peripheral_manager_delegate_.reset(
        [[BluetoothLowEnergyPeripheralManagerDelegate alloc]
            initWithAdvertisementManager:low_energy_advertisement_manager_.get()
                              andAdapter:this]);
    low_energy_peripheral_manager_.reset([[CBPeripheralManager alloc]
        initWithDelegate:low_energy_peripheral_manager_delegate_
                   queue:dispatch_get_main_queue()]);
  }
  DCHECK(classic_discovery_manager_);
}

BluetoothAdapterMac::~BluetoothAdapterMac() {
  // When devices will be destroyed, they will need this current instance to
  // disconnect the gatt connection. To make sure they don't use the mac
  // adapter, they should be explicitly destroyed here.
  devices_.clear();
  // Explicitly clear out delegates, which might outlive the Adapter.
  [low_energy_peripheral_manager_ setDelegate:nil];
  [low_energy_central_manager_ setDelegate:nil];
  // Set low_energy_central_manager_ to nil so no devices will try to use it
  // while being destroyed after this method. |devices_| is owned by
  // BluetoothAdapter.
  low_energy_central_manager_.reset();
}

std::string BluetoothAdapterMac::GetAddress() const {
  return address_;
}

std::string BluetoothAdapterMac::GetName() const {
  if (!should_update_name_) {
    return name_;
  }

  IOBluetoothHostController* controller =
      [IOBluetoothHostController defaultController];
  name_ = controller != nil ? base::SysNSStringToUTF8([controller nameAsString])
                            : std::string();
  should_update_name_ = name_.empty();
  return name_;
}

void BluetoothAdapterMac::SetName(const std::string& name,
                                  const base::Closure& callback,
                                  const ErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

bool BluetoothAdapterMac::IsInitialized() const {
  return true;
}

bool BluetoothAdapterMac::IsPresent() const {
  bool is_present = !address_.empty();
  if (IsLowEnergyAvailable()) {
    is_present =
        is_present || (GetCBManagerState(low_energy_central_manager_) !=
                       CBCentralManagerStateUnsupported);
  }
  return is_present;
}

bool BluetoothAdapterMac::IsPowered() const {
  return classic_powered_ || IsLowEnergyPowered();
}

// TODO(krstnmnlsn): If this information is retrievable form IOBluetooth we
// should return the discoverable status.
bool BluetoothAdapterMac::IsDiscoverable() const {
  return false;
}

void BluetoothAdapterMac::SetDiscoverable(
    bool discoverable,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

bool BluetoothAdapterMac::IsDiscovering() const {
  bool is_discovering = classic_discovery_manager_->IsDiscovering();
  if (IsLowEnergyAvailable())
    is_discovering =
        is_discovering || low_energy_discovery_manager_->IsDiscovering();
  return is_discovering;
}

std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
BluetoothAdapterMac::RetrieveGattConnectedDevicesWithDiscoveryFilter(
    const BluetoothDiscoveryFilter& discovery_filter) {
  std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
      connected_devices;
  std::set<device::BluetoothUUID> uuids;
  discovery_filter.GetUUIDs(uuids);
  if (uuids.empty()) {
    for (BluetoothDevice* device :
         RetrieveGattConnectedDevicesWithService(nullptr)) {
      connected_devices[device] = BluetoothDevice::UUIDSet();
    }
    return connected_devices;
  }
  for (const BluetoothUUID& uuid : uuids) {
    for (BluetoothDevice* device :
         RetrieveGattConnectedDevicesWithService(&uuid)) {
      connected_devices[device].insert(uuid);
    }
  }
  return connected_devices;
}

BluetoothAdapter::UUIDList BluetoothAdapterMac::GetUUIDs() const {
  NOTIMPLEMENTED();
  return UUIDList();
}

void BluetoothAdapterMac::CreateRfcommService(
    const BluetoothUUID& uuid,
    const ServiceOptions& options,
    const CreateServiceCallback& callback,
    const CreateServiceErrorCallback& error_callback) {
  scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
  socket->ListenUsingRfcomm(
      this, uuid, options, base::Bind(callback, socket), error_callback);
}

void BluetoothAdapterMac::CreateL2capService(
    const BluetoothUUID& uuid,
    const ServiceOptions& options,
    const CreateServiceCallback& callback,
    const CreateServiceErrorCallback& error_callback) {
  scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
  socket->ListenUsingL2cap(
      this, uuid, options, base::Bind(callback, socket), error_callback);
}

void BluetoothAdapterMac::RegisterAdvertisement(
    std::unique_ptr<BluetoothAdvertisement::Data> advertisement_data,
    const CreateAdvertisementCallback& callback,
    const AdvertisementErrorCallback& error_callback) {
  low_energy_advertisement_manager_->RegisterAdvertisement(
      std::move(advertisement_data), callback, error_callback);
}

BluetoothLocalGattService* BluetoothAdapterMac::GetGattService(
    const std::string& identifier) const {
  return nullptr;
}

void BluetoothAdapterMac::ClassicDeviceFound(IOBluetoothDevice* device) {
  ClassicDeviceAdded(device);
}

void BluetoothAdapterMac::ClassicDiscoveryStopped(bool unexpected) {
  if (unexpected) {
    DVLOG(1) << "Discovery stopped unexpectedly";
    num_discovery_sessions_ = 0;
    MarkDiscoverySessionsAsInactive();
  }
  for (auto& observer : observers_)
    observer.AdapterDiscoveringChanged(this, false);
}

void BluetoothAdapterMac::DeviceConnected(IOBluetoothDevice* device) {
  // TODO(isherman): Investigate whether this method can be replaced with a call
  // to +registerForConnectNotifications:selector:.
  DVLOG(1) << "Adapter registered a new connection from device with address: "
           << BluetoothClassicDeviceMac::GetDeviceAddress(device);
  ClassicDeviceAdded(device);
}

// static
bool BluetoothAdapterMac::IsLowEnergyAvailable() {
  return base::mac::IsAtLeastOS10_10();
}

bool BluetoothAdapterMac::SetPoweredImpl(bool powered) {
  power_state_function_.Run(base::strict_cast<int>(powered));
  return true;
}

void BluetoothAdapterMac::RemovePairingDelegateInternal(
    BluetoothDevice::PairingDelegate* pairing_delegate) {}

BluetoothAdapterMac::HostControllerState
BluetoothAdapterMac::GetHostControllerState() {
  HostControllerState state;
  IOBluetoothHostController* controller =
      [IOBluetoothHostController defaultController];
  if (controller != nil) {
    state.classic_powered =
        ([controller powerState] == kBluetoothHCIPowerStateON);
    state.address = BluetoothDevice::CanonicalizeAddress(
        base::SysNSStringToUTF8([controller addressAsString]));
    state.is_present = !state.address.empty();
  }
  return state;
}

void BluetoothAdapterMac::UpdateKnownLowEnergyDevices(
    std::map<std::string, std::string> updated_low_energy_devices_info) {
  std::map<std::string, std::string> changed_devices;
  // Notify DeviceChanged() to devices that have been newly paired as well as to
  // devices that have been removed from the pairing list.
  std::set_symmetric_difference(
      updated_low_energy_devices_info.begin(),
      updated_low_energy_devices_info.end(), low_energy_devices_info_.begin(),
      low_energy_devices_info_.end(),
      std::inserter(changed_devices, changed_devices.end()));

  low_energy_devices_info_ = std::move(updated_low_energy_devices_info);
  for (const auto& info : changed_devices) {
    auto it = devices_.find(
        BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(info.first));
    if (it == devices_.end())
      continue;

    NotifyDeviceChanged(it->second.get());
  }
}

void BluetoothAdapterMac::SetCentralManagerForTesting(
    CBCentralManager* central_manager) {
  CHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
  central_manager.delegate = low_energy_central_manager_delegate_;
  low_energy_central_manager_.reset(central_manager,
                                    base::scoped_policy::RETAIN);
  low_energy_discovery_manager_->SetCentralManager(low_energy_central_manager_);
}

CBCentralManager* BluetoothAdapterMac::GetCentralManager() {
  return low_energy_central_manager_;
}

CBPeripheralManager* BluetoothAdapterMac::GetPeripheralManager() {
  return low_energy_peripheral_manager_;
}

void BluetoothAdapterMac::SetHostControllerStateFunctionForTesting(
    HostControllerStateFunction controller_state_function) {
  controller_state_function_ = std::move(controller_state_function);
}

void BluetoothAdapterMac::SetPowerStateFunctionForTesting(
    SetControllerPowerStateFunction power_state_function) {
  power_state_function_ = std::move(power_state_function);
}

void BluetoothAdapterMac::SetLowEnergyDeviceWatcherForTesting(
    scoped_refptr<BluetoothLowEnergyDeviceWatcherMac>
        bluetooth_low_energy_device_watcher) {
  bluetooth_low_energy_device_watcher_ =
      std::move(bluetooth_low_energy_device_watcher);
  bluetooth_low_energy_device_watcher_->Init();
}

void BluetoothAdapterMac::SetGetDevicePairedStatusCallbackForTesting(
    GetDevicePairedStatusCallback device_paired_status_callback) {
  device_paired_status_callback_ = std::move(device_paired_status_callback);
}

void BluetoothAdapterMac::AddDiscoverySession(
    BluetoothDiscoveryFilter* discovery_filter,
    const base::Closure& callback,
    DiscoverySessionErrorCallback error_callback) {
  DVLOG(1) << __func__;
  if (num_discovery_sessions_ > 0) {
    DCHECK(IsDiscovering());
    num_discovery_sessions_++;
    // We are already running a discovery session, notify the system if the
    // filter has changed.
    if (!StartDiscovery(discovery_filter)) {
      // TODO: Provide a more precise error here.
      ui_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(std::move(error_callback),
                         UMABluetoothDiscoverySessionOutcome::UNKNOWN));
      return;
    }
    ui_task_runner_->PostTask(FROM_HERE, callback);
    return;
  }

  DCHECK_EQ(0, num_discovery_sessions_);

  if (!StartDiscovery(discovery_filter)) {
    // TODO: Provide a more precise error here.
    ui_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(error_callback),
                       UMABluetoothDiscoverySessionOutcome::UNKNOWN));
    return;
  }

  DVLOG(1) << "Added a discovery session";
  num_discovery_sessions_++;
  for (auto& observer : observers_)
    observer.AdapterDiscoveringChanged(this, true);
  ui_task_runner_->PostTask(FROM_HERE, callback);
}

void BluetoothAdapterMac::RemoveDiscoverySession(
    BluetoothDiscoveryFilter* discovery_filter,
    const base::Closure& callback,
    DiscoverySessionErrorCallback error_callback) {
  DVLOG(1) << __func__;

  if (num_discovery_sessions_ > 1) {
    // There are active sessions other than the one currently being removed.
    DCHECK(IsDiscovering());
    num_discovery_sessions_--;
    callback.Run();
    return;
  }

  if (num_discovery_sessions_ == 0) {
    DVLOG(1) << "No active discovery sessions. Returning error.";
    std::move(error_callback)
        .Run(UMABluetoothDiscoverySessionOutcome::NOT_ACTIVE);
    return;
  }

  // Default to dual discovery if |discovery_filter| is NULL.
  BluetoothTransport transport = BLUETOOTH_TRANSPORT_DUAL;
  if (discovery_filter)
    transport = discovery_filter->GetTransport();

  if (transport & BLUETOOTH_TRANSPORT_CLASSIC) {
    if (!classic_discovery_manager_->StopDiscovery()) {
      DVLOG(1) << "Failed to stop classic discovery";
      // TODO: Provide a more precise error here.
      std::move(error_callback)
          .Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN);
      return;
    }
  }
  if (transport & BLUETOOTH_TRANSPORT_LE) {
    if (IsLowEnergyAvailable()) {
      low_energy_discovery_manager_->StopDiscovery();
      for (const auto& device_id_object_pair : devices_) {
        device_id_object_pair.second->ClearAdvertisementData();
      }
    }
  }

  DVLOG(1) << "Discovery stopped";
  num_discovery_sessions_--;
  callback.Run();
}

void BluetoothAdapterMac::SetDiscoveryFilter(
    std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
    const base::Closure& callback,
    DiscoverySessionErrorCallback error_callback) {
  NOTIMPLEMENTED();
  std::move(error_callback)
      .Run(UMABluetoothDiscoverySessionOutcome::NOT_IMPLEMENTED);
}

bool BluetoothAdapterMac::StartDiscovery(
    BluetoothDiscoveryFilter* discovery_filter) {
  // Default to dual discovery if |discovery_filter| is NULL.  IOBluetooth seems
  // allow starting low energy and classic discovery at once.
  BluetoothTransport transport = BLUETOOTH_TRANSPORT_DUAL;
  if (discovery_filter)
    transport = discovery_filter->GetTransport();

  if ((transport & BLUETOOTH_TRANSPORT_CLASSIC) &&
      !classic_discovery_manager_->IsDiscovering()) {
    // TODO(krstnmnlsn): If a classic discovery session is already running then
    // we should update its filter. crbug.com/498056
    if (!classic_discovery_manager_->StartDiscovery()) {
      DVLOG(1) << "Failed to add a classic discovery session";
      return false;
    }
  }
  if (transport & BLUETOOTH_TRANSPORT_LE) {
    // Begin a low energy discovery session or update it if one is already
    // running.
    if (IsLowEnergyAvailable())
      low_energy_discovery_manager_->StartDiscovery(
          BluetoothDevice::UUIDList());
  }
  return true;
}

void BluetoothAdapterMac::Init() {
  ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
  low_energy_advertisement_manager_->Init(ui_task_runner_,
                                          low_energy_peripheral_manager_);
  PollAdapter();

  // To obtain list of low energy devices known to the system, we need to parse
  // and watch system property list file for paired device addresses.
  bluetooth_low_energy_device_watcher_ =
      BluetoothLowEnergyDeviceWatcherMac::CreateAndStartWatching(
          ui_task_runner_,
          base::BindRepeating(&BluetoothAdapterMac::UpdateKnownLowEnergyDevices,
                              weak_ptr_factory_.GetWeakPtr()));

  bluetooth_low_energy_device_watcher_->ReadBluetoothPropertyListFile();
}

void BluetoothAdapterMac::InitForTest(
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
  ui_task_runner_ = ui_task_runner;
}

void BluetoothAdapterMac::PollAdapter() {
  const bool was_present = IsPresent();
  HostControllerState state = controller_state_function_.Run();

  if (address_ != state.address)
    should_update_name_ = true;
  address_ = std::move(state.address);

  if (was_present != state.is_present) {
    for (auto& observer : observers_)
      observer.AdapterPresentChanged(this, state.is_present);
  }

  if (classic_powered_ != state.classic_powered) {
    classic_powered_ = state.classic_powered;
    RunPendingPowerCallbacks();
    NotifyAdapterPoweredChanged(classic_powered_);
  }

  RemoveTimedOutDevices();
  AddPairedDevices();

  ui_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&BluetoothAdapterMac::PollAdapter,
                     weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(kPollIntervalMs));
}

void BluetoothAdapterMac::ClassicDeviceAdded(IOBluetoothDevice* device) {
  std::string device_address =
      BluetoothClassicDeviceMac::GetDeviceAddress(device);

  BluetoothDevice* device_classic = GetDevice(device_address);

  // Only notify observers once per device.
  if (device_classic != nullptr) {
    VLOG(3) << "Updating classic device: " << device_classic->GetAddress();
    device_classic->UpdateTimestamp();
    return;
  }

  device_classic = new BluetoothClassicDeviceMac(this, device);
  devices_[device_address] = base::WrapUnique(device_classic);
  VLOG(1) << "Adding new classic device: " << device_classic->GetAddress();

  for (auto& observer : observers_)
    observer.DeviceAdded(this, device_classic);
}

bool BluetoothAdapterMac::IsLowEnergyPowered() const {
  if (!IsLowEnergyAvailable()) {
    return false;
  }

  return GetCBManagerState(low_energy_central_manager_) ==
         CBCentralManagerStatePoweredOn;
}

void BluetoothAdapterMac::LowEnergyDeviceUpdated(
    CBPeripheral* peripheral,
    NSDictionary* advertisement_data,
    int rssi) {
  BluetoothLowEnergyDeviceMac* device_mac =
      GetBluetoothLowEnergyDeviceMac(peripheral);
  // If has no entry in the map, create new device and insert into |devices_|,
  // otherwise update the existing device.
  const bool is_new_device = device_mac == nullptr;
  if (is_new_device) {
    // A new device has been found.
    device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral);
    VLOG(1) << *device_mac << ": New Device.";
  } else if (DoesCollideWithKnownDevice(peripheral, device_mac)) {
    return;
  }

  DCHECK(device_mac);
  VLOG(3) << *device_mac << ": Device updated with "
          << base::SysNSStringToUTF8([advertisement_data description]);

  // Get Advertised UUIDs
  // Core Specification Supplement (CSS) v7, Part 1.1
  // https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataserviceuuidskey
  BluetoothDevice::UUIDList advertised_uuids;
  NSArray* service_uuids =
      [advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey];
  for (CBUUID* uuid in service_uuids) {
    advertised_uuids.push_back(
        BluetoothAdapterMac::BluetoothUUIDWithCBUUID(uuid));
  }
  NSArray* overflow_service_uuids = [advertisement_data
      objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
  for (CBUUID* uuid in overflow_service_uuids) {
    advertised_uuids.push_back(
        BluetoothAdapterMac::BluetoothUUIDWithCBUUID(uuid));
  }

  // Get Service Data.
  // Core Specification Supplement (CSS) v7, Part 1.11
  // https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataservicedatakey
  BluetoothDevice::ServiceDataMap service_data_map;
  NSDictionary* service_data =
      [advertisement_data objectForKey:CBAdvertisementDataServiceDataKey];
  for (CBUUID* uuid in service_data) {
    NSData* data = [service_data objectForKey:uuid];
    const uint8_t* bytes = static_cast<const uint8_t*>([data bytes]);
    size_t length = [data length];
    service_data_map.emplace(BluetoothAdapterMac::BluetoothUUIDWithCBUUID(uuid),
                             std::vector<uint8_t>(bytes, bytes + length));
  }

  // Get Manufacturer Data.
  // "Size: 2 or more octets
  // The first 2 octets contain the Company Identifier Code followed
  // by additional manufacturer specific data"
  // Core Specification Supplement (CSS) v7, Part 1.4
  // https://developer.apple.com/documentation/corebluetooth/cbadvertisementdatamanufacturerdatakey
  //
  BluetoothDevice::ManufacturerDataMap manufacturer_data_map;
  NSData* manufacturer_data =
      [advertisement_data objectForKey:CBAdvertisementDataManufacturerDataKey];
  const uint8_t* bytes = static_cast<const uint8_t*>([manufacturer_data bytes]);
  size_t length = [manufacturer_data length];
  if (length > 1) {
    const uint16_t manufacturer_id = bytes[0] | bytes[1] << 8;
    manufacturer_data_map.emplace(
        manufacturer_id, std::vector<uint8_t>(bytes + 2, bytes + length));
  }

  // Get Tx Power.
  // "Size: 1 octet
  //  0xXX: -127 to +127 dBm"
  // Core Specification Supplement (CSS) v7, Part 1.5
  // https://developer.apple.com/documentation/corebluetooth/cbadvertisementdatatxpowerlevelkey
  NSNumber* tx_power =
      [advertisement_data objectForKey:CBAdvertisementDataTxPowerLevelKey];
  int8_t clamped_tx_power = BluetoothDevice::ClampPower([tx_power intValue]);

  // Get the Advertising name
  NSString* local_name =
      [advertisement_data objectForKey:CBAdvertisementDataLocalNameKey];

  for (auto& observer : observers_) {
    base::Optional<std::string> device_name_opt = device_mac->GetName();
    base::Optional<std::string> local_name_opt =
        base::SysNSStringToUTF8(local_name);

    observer.DeviceAdvertisementReceived(
        device_mac->GetAddress(), device_name_opt,
        local_name == nil ? base::nullopt : local_name_opt, rssi,
        tx_power == nil ? base::nullopt : base::make_optional(clamped_tx_power),
        base::nullopt, /* TODO(crbug.com/588083) Implement appearance */
        advertised_uuids, service_data_map, manufacturer_data_map);
  }

  device_mac->UpdateAdvertisementData(
      BluetoothDevice::ClampPower(rssi), base::nullopt /* flags */,
      std::move(advertised_uuids),
      tx_power == nil ? base::nullopt : base::make_optional(clamped_tx_power),
      std::move(service_data_map), std::move(manufacturer_data_map));

  if (is_new_device) {
    std::string device_address =
        BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
    devices_[device_address] = base::WrapUnique(device_mac);
    for (auto& observer : observers_)
      observer.DeviceAdded(this, device_mac);
  } else {
    for (auto& observer : observers_)
      observer.DeviceChanged(this, device_mac);
  }
}

// TODO(crbug.com/511025): Handle state < CBCentralManagerStatePoweredOff.
void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {
  VLOG(1) << "Central manager state updated: "
          << [low_energy_central_manager_ state];

  // A state with a value lower than CBCentralManagerStatePoweredOn implies that
  // scanning has stopped and that any connected peripherals have been
  // disconnected. Call DidDisconnectPeripheral manually to update the devices'
  // states since macOS doesn't call it.
  // See
  // https://developer.apple.com/reference/corebluetooth/cbcentralmanagerdelegate/1518888-centralmanagerdidupdatestate?language=objc
  if (GetCBManagerState(low_energy_central_manager_) <
      CBCentralManagerStatePoweredOn) {
    VLOG(1)
        << "Central no longer powered on. Notifying of device disconnection.";
    for (BluetoothDevice* device : GetDevices()) {
      BluetoothLowEnergyDeviceMac* device_mac =
          static_cast<BluetoothLowEnergyDeviceMac*>(device);
      if (device_mac->IsGattConnected()) {
        device_mac->DidDisconnectPeripheral(nullptr);
      }
    }
  }
}

void BluetoothAdapterMac::AddPairedDevices() {
  // Add any new paired devices.
  for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) {
    // pairedDevices sometimes includes unknown devices that are not paired.
    // Radar issue with id 2282763004 has been filed about it.
    if ([device isPaired]) {
      ClassicDeviceAdded(device);
    }
  }
}

std::vector<BluetoothDevice*>
BluetoothAdapterMac::RetrieveGattConnectedDevicesWithService(
    const BluetoothUUID* uuid) {
  NSArray* cbUUIDs = nil;
  if (!uuid) {
    VLOG(1) << "Retrieving all connected devices.";
    // It is not possible to ask for all connected peripherals with
    // -[CBCentralManager retrieveConnectedPeripheralsWithServices:] by passing
    // nil. To try to get most of the peripherals, the search is done with
    // Generic Access service.
    CBUUID* genericAccessServiceUUID = [CBUUID UUIDWithString:@"1800"];
    cbUUIDs = @[ genericAccessServiceUUID ];
  } else {
    VLOG(1) << "Retrieving connected devices with UUID: "
            << uuid->canonical_value();
    NSString* uuidString =
        base::SysUTF8ToNSString(uuid->canonical_value().c_str());
    cbUUIDs = @[ [CBUUID UUIDWithString:uuidString] ];
  }
  NSArray* peripherals = [low_energy_central_manager_
      retrieveConnectedPeripheralsWithServices:cbUUIDs];
  std::vector<BluetoothDevice*> connected_devices;
  for (CBPeripheral* peripheral in peripherals) {
    BluetoothLowEnergyDeviceMac* device_mac =
        GetBluetoothLowEnergyDeviceMac(peripheral);
    const bool is_new_device = device_mac == nullptr;

    if (!is_new_device && DoesCollideWithKnownDevice(peripheral, device_mac)) {
      continue;
    }
    if (is_new_device) {
      device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral);
      std::string device_address =
          BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
      devices_[device_address] = base::WrapUnique(device_mac);
      for (auto& observer : observers_) {
        observer.DeviceAdded(this, device_mac);
      }
    }
    connected_devices.push_back(device_mac);
    VLOG(1) << *device_mac << ": New connected device.";
  }
  return connected_devices;
}

void BluetoothAdapterMac::CreateGattConnection(
    BluetoothLowEnergyDeviceMac* device_mac) {
  VLOG(1) << *device_mac << ": Create gatt connection.";
  [low_energy_central_manager_ connectPeripheral:device_mac->peripheral_
                                         options:nil];
}

void BluetoothAdapterMac::DisconnectGatt(
    BluetoothLowEnergyDeviceMac* device_mac) {
  VLOG(1) << *device_mac << ": Disconnect gatt.";
  [low_energy_central_manager_
      cancelPeripheralConnection:device_mac->peripheral_];
}

void BluetoothAdapterMac::DidConnectPeripheral(CBPeripheral* peripheral) {
  BluetoothLowEnergyDeviceMac* device_mac =
      GetBluetoothLowEnergyDeviceMac(peripheral);
  if (!device_mac) {
    [low_energy_central_manager_ cancelPeripheralConnection:peripheral];
    return;
  }
  device_mac->DidConnectPeripheral();
}

void BluetoothAdapterMac::DidFailToConnectPeripheral(CBPeripheral* peripheral,
                                                     NSError* error) {
  BluetoothLowEnergyDeviceMac* device_mac =
      GetBluetoothLowEnergyDeviceMac(peripheral);
  if (!device_mac) {
    [low_energy_central_manager_ cancelPeripheralConnection:peripheral];
    return;
  }
  RecordDidFailToConnectPeripheralResult(error);
  BluetoothDevice::ConnectErrorCode error_code =
      BluetoothDevice::ConnectErrorCode::ERROR_UNKNOWN;
  if (error) {
    error_code = BluetoothDeviceMac::GetConnectErrorCodeFromNSError(error);
  }
  VLOG(1) << *device_mac << ": Failed to connect to peripheral with error "
          << BluetoothAdapterMac::String(error)
          << ", error code: " << error_code;
  device_mac->DidFailToConnectGatt(error_code);
}

void BluetoothAdapterMac::DidDisconnectPeripheral(CBPeripheral* peripheral,
                                                  NSError* error) {
  BluetoothLowEnergyDeviceMac* device_mac =
      GetBluetoothLowEnergyDeviceMac(peripheral);
  if (!device_mac) {
    [low_energy_central_manager_ cancelPeripheralConnection:peripheral];
    return;
  }
  device_mac->DidDisconnectPeripheral(error);
}

bool BluetoothAdapterMac::IsBluetoothLowEnergyDeviceSystemPaired(
    base::StringPiece device_identifier) const {
  auto it = std::find_if(
      low_energy_devices_info_.begin(), low_energy_devices_info_.end(),
      [&](const auto& info) { return info.first == device_identifier; });
  if (it == low_energy_devices_info_.end())
    return false;

  return device_paired_status_callback_.Run(it->second);
}

BluetoothLowEnergyDeviceMac*
BluetoothAdapterMac::GetBluetoothLowEnergyDeviceMac(CBPeripheral* peripheral) {
  std::string device_address =
      BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
  auto iter = devices_.find(device_address);
  if (iter == devices_.end()) {
    return nil;
  }
  return static_cast<BluetoothLowEnergyDeviceMac*>(iter->second.get());
}

bool BluetoothAdapterMac::DoesCollideWithKnownDevice(
    CBPeripheral* peripheral,
    BluetoothLowEnergyDeviceMac* device_mac) {
  // Check that there are no collisions.
  std::string stored_device_id = device_mac->GetIdentifier();
  std::string updated_device_id =
      BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(peripheral);
  if (stored_device_id != updated_device_id) {
    VLOG(1) << "LowEnergyDeviceUpdated stored_device_id != updated_device_id: "
            << std::endl
            << "  " << stored_device_id << std::endl
            << "  " << updated_device_id;
    // Collision, two identifiers map to the same hash address.  With a 48 bit
    // hash the probability of this occuring with 10,000 devices
    // simultaneously present is 1e-6 (see
    // https://en.wikipedia.org/wiki/Birthday_problem#Probability_table).  We
    // ignore the second device by returning.
    return true;
  }
  return false;
}

}  // namespace device
