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
power_mode_callback(const RawAddress & p_bda,tBTM_PM_STATUS status,uint16_t value,tHCI_STATUS hci_status)42 void power_mode_callback([[maybe_unused]] const RawAddress& p_bda,
43 [[maybe_unused]] tBTM_PM_STATUS status,
44 [[maybe_unused]] uint16_t value,
45 [[maybe_unused]] tHCI_STATUS hci_status) {
46 fprintf(stdout, "Got callback\n");
47 };
48
49 namespace connect {
50 std::promise<acl_state_changed_params_t> acl_state_changed_promise;
51
52 } // namespace connect
53
callback_interface(callback_data_t * data)54 void callback_interface(callback_data_t* data) {
55 if (data->Name() == "acl_state_changed") {
56 LOG(INFO) << "Received acl state changed discovery";
57 auto params = static_cast<acl_state_changed_params_t*>(data);
58 acl_state_changed_params_t p(*params);
59 connect::acl_state_changed_promise.set_value(p);
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([[maybe_unused]] unsigned int num_loops,
67 [[maybe_unused]] const RawAddress& bd_addr,
68 [[maybe_unused]] std::list<std::string> options) {
69 int disconnect_wait_time{0};
70
71 if (options.size() != 0) {
72 std::string opt = options.front();
73 options.pop_front();
74 auto v = bluetooth::test::headless::GetOpt::Split(opt);
75 if (v.size() == 2) {
76 if (v[0] == "wait") disconnect_wait_time = std::stoi(v[1]);
77 }
78 }
79 ASSERT_LOG(disconnect_wait_time >= 0, "Time cannot go backwards");
80
81 headless_add_callback("acl_state_changed", callback_interface);
82
83 connect::acl_state_changed_promise =
84 std::promise<acl_state_changed_params_t>();
85 auto future = connect::acl_state_changed_promise.get_future();
86
87 fprintf(stdout, "Creating connection to:%s\n", bd_addr.ToString().c_str());
88 LOG(INFO) << "Creating classic connection to " << bd_addr.ToString();
89 acl_create_classic_connection(bd_addr, false, false);
90
91 auto result = future.get();
92 LOG_CONSOLE("Connected created %s", result.ToString().c_str());
93
94 connect::acl_state_changed_promise =
95 std::promise<acl_state_changed_params_t>();
96 future = connect::acl_state_changed_promise.get_future();
97
98 uint64_t connect = std::chrono::duration_cast<std::chrono::milliseconds>(
99 std::chrono::system_clock::now().time_since_epoch())
100 .count();
101
102 fprintf(stdout, "Just crushing stack\n");
103 LOG(INFO) << "Just crushing stack";
104 bluetoothInterface.disable();
105
106 if (disconnect_wait_time == 0) {
107 fprintf(stdout, "Waiting to disconnect from supervision timeout\n");
108 auto result = future.get();
109 uint64_t disconnect =
110 std::chrono::duration_cast<std::chrono::milliseconds>(
111 std::chrono::system_clock::now().time_since_epoch())
112 .count();
113
114 LOG_CONSOLE("Disconnected after:%" PRId64 "ms from:%s result:%s[%u]\n",
115 disconnect - connect, bd_addr.ToString().c_str(),
116 bt_status_text(result.status).c_str(), result.status);
117 headless_remove_callback("acl_state_changed", callback_interface);
118 } else {
119 fprintf(stdout, "Waiting %d seconds to just shutdown\n",
120 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