Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b537e91 authored by Michael Sun's avatar Michael Sun Committed by Mingguang Xu
Browse files

btaa: HCI command process

Introduce the first phase of BTAA HCI command process. Upon receives a
HCI command packet, processing module will search the opcode against a
lookup table, only simple (contains only device info) and identifiable
command will be processed. Pair information of connection handle and
device address are associated and recorded for future references.

The lookup table is a skelton implementation that does not contain 100%
correct information.

Tag: #feature
Bug: 177230507
Test: verified locally BTAA can partially process HCI commands
BYPASS_LONG_LINES_REASON: consist with gd format

Change-Id: I7c8640e60ffa06f45953403549d28dc530383bd9
parent a1b88d63
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -20,10 +20,13 @@ filegroup {
        "host/activity_attribution.cc",
    ],
}

filegroup {
    name: "BluetoothBtaaSources_linux_generic",
    srcs: [
        "linux_generic/attribution_processor.cc",
        "linux_generic/cmd_evt_classification.cc",
        "linux_generic/hci_processor.cc",
        "linux_generic/wakelock_processor.cc",
    ],
}
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#pragma once

#include "btaa/activity_attribution.h"
#include "hci/hci_packets.h"

namespace bluetooth {
namespace activity_attribution {

struct CmdEvtActivityClassification {
  Activity activity;
  uint16_t connection_handle_pos;
  uint16_t address_pos;
};

CmdEvtActivityClassification lookup_cmd(hci::OpCode opcode);

}  // namespace activity_attribution
}  // namespace bluetooth
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#pragma once

#include "btaa/activity_attribution.h"
#include "hal/snoop_logger.h"
#include "hci/address.h"

namespace bluetooth {
namespace activity_attribution {

struct BtaaHciPacket {
  Activity activity;
  hci::Address address;
  uint16_t byte_count;
  BtaaHciPacket() {}
  BtaaHciPacket(Activity activity, hci::Address address, uint16_t byte_count)
      : activity(activity), address(address), byte_count(byte_count) {}
} __attribute__((__packed__));

class HciProcessor {
 public:
  std::vector<BtaaHciPacket> OnHciPacket(hal::HciPacket packet, hal::SnoopLogger::PacketType type, uint16_t length);
};

}  // namespace activity_attribution
}  // namespace bluetooth
+331 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#include "btaa/cmd_evt_classification.h"

namespace bluetooth {
namespace activity_attribution {

CmdEvtActivityClassification lookup_cmd(hci::OpCode opcode) {
  CmdEvtActivityClassification classification = {};
  switch (opcode) {
    case hci::OpCode::INQUIRY:
    case hci::OpCode::INQUIRY_CANCEL:
    case hci::OpCode::PERIODIC_INQUIRY_MODE:
    case hci::OpCode::EXIT_PERIODIC_INQUIRY_MODE:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 0};
      break;

    case hci::OpCode::CREATE_CONNECTION:
    case hci::OpCode::CREATE_CONNECTION_CANCEL:
    case hci::OpCode::ACCEPT_CONNECTION_REQUEST:
    case hci::OpCode::LINK_KEY_REQUEST_REPLY:
    case hci::OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::PIN_CODE_REQUEST_REPLY:
    case hci::OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::REJECT_CONNECTION_REQUEST:
    case hci::OpCode::REMOTE_NAME_REQUEST:
    case hci::OpCode::REMOTE_NAME_REQUEST_CANCEL:
    case hci::OpCode::ACCEPT_SYNCHRONOUS_CONNECTION:
    case hci::OpCode::REJECT_SYNCHRONOUS_CONNECTION:
    case hci::OpCode::IO_CAPABILITY_REQUEST_REPLY:
    case hci::OpCode::USER_CONFIRMATION_REQUEST_REPLY:
    case hci::OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::USER_PASSKEY_REQUEST_REPLY:
    case hci::OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::REMOTE_OOB_DATA_REQUEST_REPLY:
    case hci::OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION:
    case hci::OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY:
    case hci::OpCode::SWITCH_ROLE:
    case hci::OpCode::READ_STORED_LINK_KEY:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 3};
      break;

    case hci::OpCode::CENTRAL_LINK_KEY:
    case hci::OpCode::READ_DEFAULT_LINK_POLICY_SETTINGS:
    case hci::OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS:
    case hci::OpCode::WRITE_SCAN_ENABLE:
    case hci::OpCode::READ_PAGE_SCAN_ACTIVITY:
    case hci::OpCode::WRITE_PAGE_SCAN_ACTIVITY:
    case hci::OpCode::READ_PAGE_SCAN_TYPE:
    case hci::OpCode::WRITE_PAGE_SCAN_TYPE:
    case hci::OpCode::READ_SIMPLE_PAIRING_MODE:
    case hci::OpCode::WRITE_SIMPLE_PAIRING_MODE:
    case hci::OpCode::READ_SCAN_ENABLE:
    case hci::OpCode::LE_CREATE_CONNECTION_CANCEL:
    case hci::OpCode::LE_READ_CONNECT_LIST_SIZE:
    case hci::OpCode::LE_CLEAR_CONNECT_LIST:
    case hci::OpCode::SEND_KEYPRESS_NOTIFICATION:
    case hci::OpCode::LE_CLEAR_RESOLVING_LIST:
    case hci::OpCode::LE_READ_RESOLVING_LIST_SIZE:
    case hci::OpCode::LE_SET_HOST_CHANNEL_CLASSIFICATION:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 0};
      break;

    case hci::OpCode::DISCONNECT:
    case hci::OpCode::CHANGE_CONNECTION_PACKET_TYPE:
    case hci::OpCode::AUTHENTICATION_REQUESTED:
    case hci::OpCode::SET_CONNECTION_ENCRYPTION:
    case hci::OpCode::CHANGE_CONNECTION_LINK_KEY:
    case hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES:
    case hci::OpCode::READ_REMOTE_EXTENDED_FEATURES:
    case hci::OpCode::READ_REMOTE_VERSION_INFORMATION:
    case hci::OpCode::READ_CLOCK_OFFSET:
    case hci::OpCode::READ_LMP_HANDLE:
    case hci::OpCode::SETUP_SYNCHRONOUS_CONNECTION:
    case hci::OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION:
    case hci::OpCode::HOLD_MODE:
    case hci::OpCode::SNIFF_MODE:
    case hci::OpCode::EXIT_SNIFF_MODE:
    case hci::OpCode::QOS_SETUP:
    case hci::OpCode::ROLE_DISCOVERY:
    case hci::OpCode::READ_LINK_POLICY_SETTINGS:
    case hci::OpCode::WRITE_LINK_POLICY_SETTINGS:
    case hci::OpCode::FLOW_SPECIFICATION:
    case hci::OpCode::SNIFF_SUBRATING:
    case hci::OpCode::FLUSH:
    case hci::OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT:
    case hci::OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT:
    case hci::OpCode::READ_LINK_SUPERVISION_TIMEOUT:
    case hci::OpCode::WRITE_LINK_SUPERVISION_TIMEOUT:
    case hci::OpCode::REFRESH_ENCRYPTION_KEY:
    case hci::OpCode::READ_FAILED_CONTACT_COUNTER:
    case hci::OpCode::RESET_FAILED_CONTACT_COUNTER:
    case hci::OpCode::READ_LINK_QUALITY:
    case hci::OpCode::READ_RSSI:
    case hci::OpCode::READ_AFH_CHANNEL_MAP:
    case hci::OpCode::READ_CLOCK:
    case hci::OpCode::READ_ENCRYPTION_KEY_SIZE:
    // READ_LOOPBACK_MODE = 0x1801,
    // WRITE_LOOPBACK_MODE = 0x1802,
    // ENABLE_DEVICE_UNDER_TEST_MODE = 0x1803,
    // WRITE_SIMPLE_PAIRING_DEBUG_MODE = 0x1804,
    // WRITE_SECURE_CONNECTIONS_TEST_MODE = 0x180a,
    case hci::OpCode::ENHANCED_FLUSH:
    case hci::OpCode::LE_CONNECTION_UPDATE:
    case hci::OpCode::LE_START_ENCRYPTION:
    case hci::OpCode::LE_LONG_TERM_KEY_REQUEST_REPLY:
    case hci::OpCode::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::LE_READ_PHY:
    case hci::OpCode::LE_SET_PHY:
    case hci::OpCode::LE_READ_REMOTE_FEATURES:
    case hci::OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY:
    case hci::OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY:
    case hci::OpCode::LE_SET_DATA_LENGTH:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 3, .address_pos = 0};
      break;

    case hci::OpCode::SET_EVENT_MASK:
    case hci::OpCode::RESET:
    case hci::OpCode::SET_EVENT_FILTER:
    case hci::OpCode::READ_PIN_TYPE:
    case hci::OpCode::WRITE_PIN_TYPE:
    case hci::OpCode::WRITE_LOCAL_NAME:
    case hci::OpCode::READ_LOCAL_NAME:
    case hci::OpCode::READ_CONNECTION_ACCEPT_TIMEOUT:
    case hci::OpCode::WRITE_CONNECTION_ACCEPT_TIMEOUT:
    case hci::OpCode::READ_PAGE_TIMEOUT:
    case hci::OpCode::WRITE_PAGE_TIMEOUT:
    case hci::OpCode::READ_AUTHENTICATION_ENABLE:
    case hci::OpCode::WRITE_AUTHENTICATION_ENABLE:
    case hci::OpCode::READ_CLASS_OF_DEVICE:
    case hci::OpCode::WRITE_CLASS_OF_DEVICE:
    case hci::OpCode::READ_VOICE_SETTING:
    case hci::OpCode::WRITE_VOICE_SETTING:
    case hci::OpCode::READ_NUM_BROADCAST_RETRANSMITS:
    case hci::OpCode::WRITE_NUM_BROADCAST_RETRANSMITS:
    case hci::OpCode::READ_HOLD_MODE_ACTIVITY:
    case hci::OpCode::WRITE_HOLD_MODE_ACTIVITY:
    case hci::OpCode::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE:
    case hci::OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE:
    case hci::OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL:
    case hci::OpCode::HOST_BUFFER_SIZE:
    case hci::OpCode::HOST_NUM_COMPLETED_PACKETS:
    case hci::OpCode::READ_NUMBER_OF_SUPPORTED_IAC:
    case hci::OpCode::READ_CURRENT_IAC_LAP:
    case hci::OpCode::WRITE_CURRENT_IAC_LAP:
    case hci::OpCode::SET_AFH_HOST_CHANNEL_CLASSIFICATION:
    case hci::OpCode::READ_AFH_CHANNEL_ASSESSMENT_MODE:
    case hci::OpCode::WRITE_AFH_CHANNEL_ASSESSMENT_MODE:
    case hci::OpCode::READ_LE_HOST_SUPPORT:
    case hci::OpCode::WRITE_LE_HOST_SUPPORT:
    case hci::OpCode::READ_SECURE_CONNECTIONS_HOST_SUPPORT:
    case hci::OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT:
    case hci::OpCode::READ_LOCAL_OOB_EXTENDED_DATA:
    case hci::OpCode::SET_ECOSYSTEM_BASE_INTERVAL:
    case hci::OpCode::CONFIGURE_DATA_PATH:
    case hci::OpCode::READ_LOCAL_VERSION_INFORMATION:
    case hci::OpCode::READ_LOCAL_SUPPORTED_COMMANDS:
    case hci::OpCode::READ_LOCAL_SUPPORTED_FEATURES:
    case hci::OpCode::READ_LOCAL_EXTENDED_FEATURES:
    case hci::OpCode::READ_BUFFER_SIZE:
    case hci::OpCode::READ_BD_ADDR:
    case hci::OpCode::READ_DATA_BLOCK_SIZE:
    case hci::OpCode::READ_LOCAL_SUPPORTED_CODECS_V1:
    case hci::OpCode::READ_LOCAL_SUPPORTED_CODECS_V2:
    case hci::OpCode::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES:
    case hci::OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY:
    case hci::OpCode::READ_LOCAL_OOB_DATA:
    case hci::OpCode::LE_GENERATE_DHKEY_COMMAND:
    case hci::OpCode::LE_MODIFY_SLEEP_CLOCK_ACCURACY:
    case hci::OpCode::LE_READ_BUFFER_SIZE_V2:
    case hci::OpCode::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH:
    case hci::OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH:
    case hci::OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND:
    case hci::OpCode::LE_GENERATE_DHKEY_COMMAND_V1:
    case hci::OpCode::LE_SET_EVENT_MASK:
    case hci::OpCode::LE_READ_BUFFER_SIZE_V1:
    case hci::OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES:
    case hci::OpCode::LE_SET_RANDOM_ADDRESS:
    case hci::OpCode::LE_READ_TRANSMIT_POWER:
    case hci::OpCode::LE_READ_RF_PATH_COMPENSATION_POWER:
    case hci::OpCode::LE_WRITE_RF_PATH_COMPENSATION_POWER:
    case hci::OpCode::LE_SET_DEFAULT_PHY:
    case hci::OpCode::LE_ENCRYPT:
    case hci::OpCode::LE_RAND:
    case hci::OpCode::LE_SET_ADDRESS_RESOLUTION_ENABLE:
    case hci::OpCode::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT:
    case hci::OpCode::LE_READ_MAXIMUM_DATA_LENGTH:
    case hci::OpCode::LE_READ_SUPPORTED_STATES:
      classification = {.activity = Activity::CONTROL, .connection_handle_pos = 0, .address_pos = 0};
      break;

    case hci::OpCode::DELETE_STORED_LINK_KEY:
      classification = {.activity = Activity::CONTROL, .connection_handle_pos = 0, .address_pos = 3};
      break;
    case hci::OpCode::READ_TRANSMIT_POWER_LEVEL:
      classification = {.activity = Activity::CONTROL, .connection_handle_pos = 3, .address_pos = 0};
      break;

    case hci::OpCode::READ_INQUIRY_SCAN_ACTIVITY:
    case hci::OpCode::WRITE_INQUIRY_SCAN_ACTIVITY:
    case hci::OpCode::READ_INQUIRY_SCAN_TYPE:
    case hci::OpCode::WRITE_INQUIRY_SCAN_TYPE:
    case hci::OpCode::READ_INQUIRY_MODE:
    case hci::OpCode::WRITE_INQUIRY_MODE:
    case hci::OpCode::READ_EXTENDED_INQUIRY_RESPONSE:
    case hci::OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE:
    case hci::OpCode::LE_SET_CIG_PARAMETERS:
    case hci::OpCode::LE_CREATE_CIS:
    case hci::OpCode::LE_REMOVE_CIG:
    case hci::OpCode::LE_ACCEPT_CIS_REQUEST:
    case hci::OpCode::LE_REJECT_CIS_REQUEST:
    case hci::OpCode::LE_CREATE_BIG:
    case hci::OpCode::LE_TERMINATE_BIG:
    case hci::OpCode::LE_BIG_CREATE_SYNC:
    case hci::OpCode::LE_BIG_TERMINATE_SYNC:
    case hci::OpCode::LE_REQUEST_PEER_SCA:
    case hci::OpCode::LE_SETUP_ISO_DATA_PATH:
    case hci::OpCode::LE_REMOVE_ISO_DATA_PATH:
    case hci::OpCode::LE_SET_HOST_FEATURE:
    case hci::OpCode::LE_READ_ISO_LINK_QUALITY:
    case hci::OpCode::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL:
    case hci::OpCode::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL:
    case hci::OpCode::LE_SET_PATH_LOSS_REPORTING_PARAMETERS:
    case hci::OpCode::LE_SET_PATH_LOSS_REPORTING_ENABLE:
    case hci::OpCode::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE:
    case hci::OpCode::LE_GET_VENDOR_CAPABILITIES:
    case hci::OpCode::LE_MULTI_ADVT:
    case hci::OpCode::LE_BATCH_SCAN:
    case hci::OpCode::LE_ADV_FILTER:
    case hci::OpCode::LE_ENERGY_INFO:
    case hci::OpCode::LE_EXTENDED_SCAN_PARAMS:
    case hci::OpCode::CONTROLLER_DEBUG_INFO:
    case hci::OpCode::CONTROLLER_A2DP_OPCODE:
    case hci::OpCode::CONTROLLER_BQR:
    case hci::OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL:
    case hci::OpCode::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL:
    case hci::OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS:
    case hci::OpCode::LE_SET_EXTENDED_SCAN_ENABLE:
    case hci::OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL:
    case hci::OpCode::LE_SET_SCAN_PARAMETERS:
    case hci::OpCode::LE_SET_SCAN_ENABLE:
    case hci::OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS:
    case hci::OpCode::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE:
    case hci::OpCode::LE_CLEAR_PERIODIC_ADVERTISING_LIST:
    case hci::OpCode::LE_READ_PERIODIC_ADVERTISING_LIST_SIZE:
    case hci::OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 0};
      break;

    case hci::OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER:
    case hci::OpCode::LE_SET_ADVERTISING_DATA:
    case hci::OpCode::LE_SET_SCAN_RESPONSE_DATA:
    case hci::OpCode::LE_SET_ADVERTISING_ENABLE:
    case hci::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA:
    case hci::OpCode::LE_SET_EXTENDED_ADVERTISING_SCAN_RESPONSE:
    case hci::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE:
    case hci::OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH:
    case hci::OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS:
    case hci::OpCode::LE_REMOVE_ADVERTISING_SET:
    case hci::OpCode::LE_CLEAR_ADVERTISING_SETS:
    case hci::OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM:
    case hci::OpCode::LE_SET_PERIODIC_ADVERTISING_DATA:
    case hci::OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE:
    case hci::OpCode::LE_SET_EXTENDED_ADVERTISING_RANDOM_ADDRESS:
      classification = {.activity = Activity::ADVERTISE, .connection_handle_pos = 0, .address_pos = 0};
      break;

    case hci::OpCode::LE_SET_ADVERTISING_PARAMETERS:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 10};
      break;
    case hci::OpCode::LE_CREATE_CONNECTION:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 9};
      break;
    case hci::OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST:
    case hci::OpCode::LE_READ_CHANNEL_MAP:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 4, .address_pos = 0};
      break;

    case hci::OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST:
    case hci::OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST:
    case hci::OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST:
    case hci::OpCode::LE_READ_PEER_RESOLVABLE_ADDRESS:
    case hci::OpCode::LE_READ_LOCAL_RESOLVABLE_ADDRESS:
    case hci::OpCode::LE_SET_PRIVACY_MODE:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 4};
      break;

    case hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS:
      classification = {.activity = Activity::ADVERTISE, .connection_handle_pos = 0, .address_pos = 15};
      break;
    case hci::OpCode::LE_EXTENDED_CREATE_CONNECTION:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 6};
      break;
    case hci::OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 6};
      break;
    case hci::OpCode::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST:
    case hci::OpCode::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISING_LIST:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 4};
      break;
    case hci::OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER:
    case hci::OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER:
    case hci::OpCode::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 3, .address_pos = 0};
      break;

    default:
      classification = {.activity = Activity::UNKNOWN, .connection_handle_pos = 0, .address_pos = 0};
      break;
  }
  return classification;
}

}  // namespace activity_attribution
}  // namespace bluetooth
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#include "btaa/hci_processor.h"

#include "btaa/cmd_evt_classification.h"
#include "os/log.h"

namespace bluetooth {
namespace activity_attribution {

class DeviceParser {
 public:
  void match_handle_with_address(uint16_t connection_handle, hci::Address& address) {
    if (connection_handle && !address.IsEmpty()) {
      connection_lookup_table[connection_handle] = address;
    } else if (connection_handle) {
      if (connection_lookup_table.find(connection_handle) != connection_lookup_table.end()) {
        address = connection_lookup_table[connection_handle];
      }
    }
  }

 private:
  std::map<uint16_t, hci::Address> connection_lookup_table;
};

static DeviceParser device_parser;
static std::pair<hci::OpCode, BtaaHciPacket> pending_command;

static void process_command(
    std::vector<BtaaHciPacket>& btaa_hci_packets,
    packet::PacketView<packet::kLittleEndian>& packet_view,
    uint16_t byte_count) {
  hci::CommandView command = hci::CommandView::Create(packet_view);
  if (!command.IsValid()) {
    return;
  }

  uint16_t connection_handle_value = 0;
  hci::Address address_value;
  auto opcode = command.GetOpCode();
  auto cmd_info = lookup_cmd(opcode);

  if (cmd_info.connection_handle_pos) {
    auto connection_handle_it = command.begin() + cmd_info.connection_handle_pos;
    connection_handle_value = connection_handle_it.extract<uint16_t>();
  }
  if (cmd_info.address_pos) {
    auto address_value_it = command.begin() + cmd_info.address_pos;
    address_value = address_value_it.extract<hci::Address>();
  }
  device_parser.match_handle_with_address(connection_handle_value, address_value);
  pending_command.second = BtaaHciPacket(cmd_info.activity, address_value, byte_count);

  pending_command.first = opcode;
}

std::vector<BtaaHciPacket> HciProcessor::OnHciPacket(
    hal::HciPacket packet, hal::SnoopLogger::PacketType type, uint16_t length) {
  std::vector<BtaaHciPacket> btaa_hci_packets;
  auto packet_view = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(packet));
  switch (type) {
    case hal::SnoopLogger::PacketType::CMD:
      process_command(btaa_hci_packets, packet_view, length);
      break;
    case hal::SnoopLogger::PacketType::EVT:
      break;
    case hal::SnoopLogger::PacketType::ACL:
      break;
    case hal::SnoopLogger::PacketType::SCO:
      break;
    case hal::SnoopLogger::PacketType::ISO:
      break;
  }
  return btaa_hci_packets;
}

}  // namespace activity_attribution
}  // namespace bluetooth