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

Commit 0bc58bf0 authored by Chris Manton's avatar Chris Manton
Browse files

btif::dm Lifecycle check for energy module enabled

Bug: 310317358
Test: atest net_test_btif
Change-Id: I66aaec0e016b614fd99acfb8a1889939c397e21c
parent 7513109b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ cc_test {
    host_supported: true,
    include_dirs: btifCommonIncludes,
    srcs: [
        "test/btif_dm_test.cc",
        "test/btif_storage_test.cc",
    ],
    header_libs: ["libbluetooth_headers"],
@@ -308,6 +309,7 @@ cc_test {
        "libevent",
        "libflatbuffers-cpp",
        "libg722codec",
        "libgmock",
        "liblc3",
        "libopus",
        "libosi",
+134 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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 <gmock/gmock.h>

#include "btif/include/core_callbacks.h"
#include "include/hardware/bluetooth.h"
#include "types/raw_address.h"

namespace bluetooth {
namespace core {
namespace testing {

// These callbacks are not profile specific (e.g. connection complete, bond
// complete, etc) and are what go to the Java layer.
EventCallbacks mock_event_callbacks = {
    .invoke_adapter_state_changed_cb = [](bt_state_t /* state */) {},
    .invoke_adapter_properties_cb = [](bt_status_t /* status */,
                                       int /* num_properties */,
                                       bt_property_t* /* properties */) {},
    .invoke_remote_device_properties_cb =
        [](bt_status_t /* status */, RawAddress /* bd_addr */,
           int /* num_properties */, bt_property_t* /* properties */) {},
    .invoke_device_found_cb = [](int /* num_properties */,
                                 bt_property_t* /* properties */) {},
    .invoke_discovery_state_changed_cb =
        [](bt_discovery_state_t /* state */) {},
    .invoke_pin_request_cb = [](RawAddress /* bd_addr */,
                                bt_bdname_t /* bd_name */, uint32_t /* cod */,
                                bool /* min_16_digit */) {},
    .invoke_ssp_request_cb = [](RawAddress /* bd_addr */,
                                bt_bdname_t /* bd_name */, uint32_t /* cod */,
                                bt_ssp_variant_t /* pairing_variant */,
                                uint32_t /* pass_key */) {},
    .invoke_oob_data_request_cb = [](tBT_TRANSPORT /* t */, bool /* valid */,
                                     Octet16 /* c */, Octet16 /* r */,
                                     RawAddress /* raw_address */,
                                     uint8_t /* address_type */) {},
    .invoke_bond_state_changed_cb =
        [](bt_status_t /* status */, RawAddress /* bd_addr */,
           bt_bond_state_t /* state */, int /* fail_reason */) {},
    .invoke_address_consolidate_cb = [](RawAddress /* main_bd_addr */,
                                        RawAddress /* secondary_bd_addr */) {},
    .invoke_le_address_associate_cb = [](RawAddress /* main_bd_addr */,
                                         RawAddress /* secondary_bd_addr */) {},
    .invoke_acl_state_changed_cb =
        [](bt_status_t /* status */, RawAddress /* bd_addr */,
           bt_acl_state_t /* state */, int /* transport_link_type */,
           bt_hci_error_code_t /* hci_reason */,
           bt_conn_direction_t /* direction */, uint16_t /* acl_handle */) {},
    .invoke_thread_evt_cb = [](bt_cb_thread_evt /* event */) {},
    .invoke_le_test_mode_cb = [](bt_status_t /* status */,
                                 uint16_t /* count */) {},
    .invoke_energy_info_cb = [](bt_activity_energy_info /* energy_info */,
                                bt_uid_traffic_t* /* uid_data */) {},
    .invoke_link_quality_report_cb =
        [](uint64_t /* timestamp */, int /* report_id */, int /* rssi */,
           int /* snr */, int /* retransmission_count */,
           int /* packets_not_receive_count */,
           int /* negative_acknowledgement_count */) {},
};

// This interface lets us query for configuration properties of the stack that
// could change at runtime
struct MockConfigInterface : public ConfigInterface {
  MOCK_METHOD((bool), isA2DPOffloadEnabled, (), ());
  MOCK_METHOD((bool), isAndroidTVDevice, (), ());
  MOCK_METHOD((bool), isRestrictedMode, (), ());
};
MockConfigInterface mock_config_interface;

// This interface lets us communicate with encoders used in profiles
struct MockCodecInterface : public CodecInterface {
  MOCK_METHOD((void), initialize, (), ());
  MOCK_METHOD((void), cleanup, (), ());
  MOCK_METHOD((uint32_t), encodePacket, (int16_t * input, uint8_t* output), ());
  MOCK_METHOD((bool), decodePacket,
              (const uint8_t* i_buf, int16_t* o_buf, size_t out_len), ());
};
MockCodecInterface mock_codec_msbcCodec;
MockCodecInterface mock_codec_lc3Codec;

HACK_ProfileInterface mock_HACK_profile_interface = {
    .btif_hh_connect = [](const RawAddress* /* bd_addr */) -> bt_status_t {
      return BT_STATUS_SUCCESS;
    },
    .btif_hh_virtual_unplug = [](const RawAddress* /* bd_addr */)
        -> bt_status_t { return BT_STATUS_SUCCESS; },
    .bta_hh_read_ssr_param =
        [](const RawAddress& /* bd_addr */, uint16_t* /* p_max_ssr_lat */,
           uint16_t* /* p_min_ssr_tout */) -> tBTA_HH_STATUS {
      return BTA_HH_OK;
    },

    .btif_av_set_dynamic_audio_buffer_size =
        [](uint8_t /* dynamic_audio_buffer_size */) {},
    .GetHearingAidDeviceCount = []() -> int { return 0; },
    .IsLeAudioClientRunning = []() -> bool { return false; },
    .AVRC_GetProfileVersion = []() -> uint16_t { return 0; },
};

// This class defines the overall interface expected by bluetooth::core.
struct MockCoreInterface : public CoreInterface {
  MockCoreInterface()
      : CoreInterface(&mock_event_callbacks, &mock_config_interface,
                      &mock_codec_msbcCodec, &mock_codec_lc3Codec,
                      &mock_HACK_profile_interface) {}

  MOCK_METHOD((void), onBluetoothEnabled, (), ());
  MOCK_METHOD((bt_status_t), toggleProfile,
              (tBTA_SERVICE_ID service_id, bool enable), ());
  MOCK_METHOD((void), removeDeviceFromProfiles, (const RawAddress& bd_addr),
              ());
  MOCK_METHOD((void), onLinkDown, (const RawAddress& bd_addr), ());
};

}  // namespace testing
}  // namespace core
}  // namespace bluetooth
+31 −10
Original line number Diff line number Diff line
@@ -2444,6 +2444,7 @@ static void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,
      "idle_time=%u,used=%u",
      status, ctrl_state, tx_time, rx_time, idle_time, energy_used);

  if (uid_set != nullptr) {
    bt_activity_energy_info energy_info;
    energy_info.status = status;
    energy_info.ctrl_state = ctrl_state;
@@ -2454,6 +2455,9 @@ static void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,

    bt_uid_traffic_t* data = uid_set_read_and_clear(uid_set);
    GetInterfaceToProfiles()->events->invoke_energy_info_cb(energy_info, data);
  } else {
    LOG_WARN("Energy info event dropped as module is inactive");
  }
}

/*****************************************************************************
@@ -4130,3 +4134,20 @@ void btif_dm_metadata_changed(const RawAddress& remote_bd_addr, int key,
    metadata_cb.le_audio_cache.insert_or_assign(remote_bd_addr, value);
  }
}

namespace bluetooth {
namespace legacy {
namespace testing {

void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,
                        tBTM_BLE_RX_TIME_MS rx_time,
                        tBTM_BLE_IDLE_TIME_MS idle_time,
                        tBTM_BLE_ENERGY_USED energy_used,
                        tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status) {
  ::bta_energy_info_cb(tx_time, rx_time, idle_time, energy_used, ctrl_state,
                       status);
}

}  // namespace testing
}  // namespace legacy
}  // namespace bluetooth
+13 −0
Original line number Diff line number Diff line
@@ -481,3 +481,16 @@ const stack_manager_t* stack_manager_get_interface() {
}

future_t* stack_manager_get_hack_future() { return hack_future; }

namespace bluetooth {
namespace legacy {
namespace testing {

void set_interface_to_profiles(
    bluetooth::core::CoreInterface* interfaceToProfiles) {
  ::interfaceToProfiles = interfaceToProfiles;
}

}  // namespace testing
}  // namespace legacy
}  // namespace bluetooth
+107 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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 "btif/include/btif_dm.h"

#include <gtest/gtest.h>

#include <memory>

#include "bta/include/bta_api_data_types.h"
#include "btif/include/mock_core_callbacks.h"
#include "stack/include/btm_api_types.h"
#include "stack/include/btm_ble_api_types.h"

using bluetooth::core::testing::MockCoreInterface;

namespace bluetooth {
namespace legacy {
namespace testing {

void set_interface_to_profiles(
    bluetooth::core::CoreInterface* interfaceToProfiles);

void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,
                        tBTM_BLE_RX_TIME_MS rx_time,
                        tBTM_BLE_IDLE_TIME_MS idle_time,
                        tBTM_BLE_ENERGY_USED energy_used,
                        tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status);

}  // namespace testing
}  // namespace legacy
}  // namespace bluetooth

namespace {
constexpr tBTM_BLE_TX_TIME_MS tx_time = 0x12345678;
constexpr tBTM_BLE_RX_TIME_MS rx_time = 0x87654321;
constexpr tBTM_BLE_IDLE_TIME_MS idle_time = 0x2468acd0;
constexpr tBTM_BLE_ENERGY_USED energy_used = 0x13579bdf;
}  // namespace

class BtifDmTest : public ::testing::Test {
 protected:
  void SetUp() override {
    mock_core_interface_ = std::make_unique<MockCoreInterface>();
    bluetooth::legacy::testing::set_interface_to_profiles(
        mock_core_interface_.get());
  }

  void TearDown() override {}

  std::unique_ptr<MockCoreInterface> mock_core_interface_;
};

TEST_F(BtifDmTest, bta_energy_info_cb__with_no_uid) {
  static bool invoke_energy_info_cb_entered = false;
  bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
      [](bt_activity_energy_info /* energy_info */,
         bt_uid_traffic_t* /* uid_data */) {
        invoke_energy_info_cb_entered = true;
      };

  bluetooth::legacy::testing::bta_energy_info_cb(
      tx_time, rx_time, idle_time, energy_used, BTM_CONTRL_UNKNOWN,
      BTA_SUCCESS);

  ASSERT_FALSE(invoke_energy_info_cb_entered);
}

class BtifDmWithUidTest : public BtifDmTest {
 protected:
  void SetUp() override {
    BtifDmTest::SetUp();
    btif_dm_init(uid_set_create());
  }

  void TearDown() override {
    void btif_dm_cleanup();
    BtifDmTest::TearDown();
  }
};

TEST_F(BtifDmWithUidTest, bta_energy_info_cb__with_uid) {
  static bool invoke_energy_info_cb_entered = false;
  bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
      [](bt_activity_energy_info /* energy_info */,
         bt_uid_traffic_t* /* uid_data */) {
        invoke_energy_info_cb_entered = true;
      };
  bluetooth::legacy::testing::bta_energy_info_cb(
      tx_time, rx_time, idle_time, energy_used, BTM_CONTRL_UNKNOWN,
      BTA_SUCCESS);

  ASSERT_TRUE(invoke_energy_info_cb_entered);
}