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