/* * Copyright 2020 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. */ #define LOG_TAG "bt_headless_mode" #include #include #include #include #include #include #include #include "base/logging.h" // LOG() stdout and android log #include "btif/include/stack_manager.h" #include "osi/include/log.h" // android log only #include "stack/include/btm_api.h" #include "stack/include/btm_api_types.h" #include "stack/include/hci_error_code.h" #include "stack/include/l2cap_acl_interface.h" #include "test/headless/connect/connect.h" #include "test/headless/get_options.h" #include "test/headless/headless.h" #include "test/headless/interface.h" #include "types/raw_address.h" const stack_manager_t* stack_manager_get_interface(); extern bt_interface_t bluetoothInterface; void power_mode_callback(const RawAddress& p_bda, tBTM_PM_STATUS status, uint16_t value, tHCI_STATUS hci_status) { fprintf(stdout, "Got callback\n"); }; std::promise acl_state_changed_promise; void callback_interface(interface_data_t data) { if (data.name == "acl_state_changed") { LOG(INFO) << "Received acl state changed"; acl_state_changed_params_t p{ .status = BT_STATUS_SUCCESS, .remote_bd_addr = nullptr, .state = BT_ACL_STATE_CONNECTED, }; acl_state_changed_promise.set_value(p); return; } LOG(ERROR) << "Received unexpected interface callback"; } namespace { int do_connect(unsigned int num_loops, const RawAddress& bd_addr, std::list options) { int disconnect_wait_time{0}; if (options.size() != 0) { std::string opt = options.front(); options.pop_front(); auto v = bluetooth::test::headless::GetOpt::Split(opt); if (v.size() == 2) { if (v[0] == "wait") disconnect_wait_time = std::stoi(v[1]); } } ASSERT_LOG(disconnect_wait_time >= 0, "Time cannot go backwards"); headless_add_callback("acl_state_changed", callback_interface); acl_state_changed_promise = std::promise(); auto future = acl_state_changed_promise.get_future(); fprintf(stdout, "Creating connection to:%s\n", bd_addr.ToString().c_str()); LOG(INFO) << "Creating classic connection to " << bd_addr.ToString(); acl_create_classic_connection(bd_addr, false, false); acl_state_changed_params_t result = future.get(); fprintf(stdout, "Connected created to:%s result:%s[%u]\n", bd_addr.ToString().c_str(), bt_status_text(result.status).c_str(), result.status); acl_state_changed_promise = std::promise(); future = acl_state_changed_promise.get_future(); uint64_t connect = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); fprintf(stdout, "Just crushing stack\n"); LOG(INFO) << "Just crushing stack"; stack_manager_get_interface()->clean_up_stack(); if (disconnect_wait_time == 0) { fprintf(stdout, "Waiting to disconnect from supervision timeout\n"); result = future.get(); uint64_t disconnect = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); fprintf(stdout, "Disconnected after:%" PRId64 "ms from:%s result:%s[%u]\n", disconnect - connect, bd_addr.ToString().c_str(), bt_status_text(result.status).c_str(), result.status); headless_remove_callback("acl_state_changed", callback_interface); } else { fprintf(stdout, "Waiting %d seconds to just shutdown\n", disconnect_wait_time); sleep(disconnect_wait_time); bluetoothInterface.dump(1, nullptr); bluetoothInterface.cleanup(); } return 0; } } // namespace int bluetooth::test::headless::Connect::Run() { return RunOnHeadlessStack([this]() { return do_connect(options_.loop_, options_.device_.front(), options_.non_options_); }); }