1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "bt_headless_mode"
18
19 #include <inttypes.h>
20 #include <chrono>
21 #include <cstdint>
22 #include <cstdio>
23 #include <future>
24 #include <map>
25 #include <string>
26
27 #include "base/logging.h" // LOG() stdout and android log
28 #include "btif/include/stack_manager.h"
29 #include "osi/include/log.h" // android log only
30 #include "stack/include/btm_api.h"
31 #include "stack/include/btm_api_types.h"
32 #include "stack/include/hci_error_code.h"
33 #include "stack/include/l2cap_acl_interface.h"
34 #include "test/headless/connect/connect.h"
35 #include "test/headless/get_options.h"
36 #include "test/headless/headless.h"
37 #include "test/headless/interface.h"
38 #include "types/raw_address.h"
39
40 const stack_manager_t* stack_manager_get_interface();
41 extern bt_interface_t bluetoothInterface;
42
power_mode_callback(const RawAddress & p_bda,tBTM_PM_STATUS status,uint16_t value,tHCI_STATUS hci_status)43 void power_mode_callback(const RawAddress& p_bda, tBTM_PM_STATUS status,
44 uint16_t value, tHCI_STATUS hci_status) {
45 fprintf(stdout, "Got callback\n");
46 };
47
48 std::promise<acl_state_changed_params_t> acl_state_changed_promise;
49
callback_interface(interface_data_t data)50 void callback_interface(interface_data_t data) {
51 if (data.name == "acl_state_changed") {
52 LOG(INFO) << "Received acl state changed";
53 acl_state_changed_params_t p{
54 .status = BT_STATUS_SUCCESS,
55 .remote_bd_addr = nullptr,
56 .state = BT_ACL_STATE_CONNECTED,
57 };
58 acl_state_changed_promise.set_value(p);
59 return;
60 }
61 LOG(ERROR) << "Received unexpected interface callback";
62 }
63
64 namespace {
65
do_connect(unsigned int num_loops,const RawAddress & bd_addr,std::list<std::string> options)66 int do_connect(unsigned int num_loops, const RawAddress& bd_addr,
67 std::list<std::string> options) {
68 int disconnect_wait_time{0};
69
70 if (options.size() != 0) {
71 std::string opt = options.front();
72 options.pop_front();
73 auto v = bluetooth::test::headless::GetOpt::Split(opt);
74 if (v.size() == 2) {
75 if (v[0] == "wait") disconnect_wait_time = std::stoi(v[1]);
76 }
77 }
78 ASSERT_LOG(disconnect_wait_time >= 0, "Time cannot go backwards");
79
80 headless_add_callback("acl_state_changed", callback_interface);
81
82 acl_state_changed_promise = std::promise<acl_state_changed_params_t>();
83 auto future = acl_state_changed_promise.get_future();
84
85 fprintf(stdout, "Creating connection to:%s\n", bd_addr.ToString().c_str());
86 LOG(INFO) << "Creating classic connection to " << bd_addr.ToString();
87 acl_create_classic_connection(bd_addr, false, false);
88
89 acl_state_changed_params_t result = future.get();
90 fprintf(stdout, "Connected created to:%s result:%s[%u]\n",
91 bd_addr.ToString().c_str(), bt_status_text(result.status).c_str(),
92 result.status);
93 acl_state_changed_promise = std::promise<acl_state_changed_params_t>();
94 future = acl_state_changed_promise.get_future();
95
96 uint64_t connect = std::chrono::duration_cast<std::chrono::milliseconds>(
97 std::chrono::system_clock::now().time_since_epoch())
98 .count();
99
100 fprintf(stdout, "Just crushing stack\n");
101 LOG(INFO) << "Just crushing stack";
102 stack_manager_get_interface()->clean_up_stack();
103
104 if (disconnect_wait_time == 0) {
105 fprintf(stdout, "Waiting to disconnect from supervision timeout\n");
106 result = future.get();
107 uint64_t disconnect =
108 std::chrono::duration_cast<std::chrono::milliseconds>(
109 std::chrono::system_clock::now().time_since_epoch())
110 .count();
111
112 fprintf(stdout, "Disconnected after:%" PRId64 "ms from:%s result:%s[%u]\n",
113 disconnect - connect, bd_addr.ToString().c_str(),
114 bt_status_text(result.status).c_str(), result.status);
115
116 headless_remove_callback("acl_state_changed", callback_interface);
117 } else {
118 fprintf(stdout, "Waiting %d seconds to just shutdown\n",
119 disconnect_wait_time);
120 sleep(disconnect_wait_time);
121 bluetoothInterface.dump(1, nullptr);
122 bluetoothInterface.cleanup();
123 }
124 return 0;
125 }
126
127 } // namespace
128
Run()129 int bluetooth::test::headless::Connect::Run() {
130 return RunOnHeadlessStack<int>([this]() {
131 return do_connect(options_.loop_, options_.device_.front(),
132 options_.non_options_);
133 });
134 }
135