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"
18
19 #include <bluetooth/log.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24
25 #include <iostream>
26 #include <unordered_map>
27
28 #include "os/log.h" // android log only
29 #include "test/headless/adapter/adapter.h"
30 #include "test/headless/connect/connect.h"
31 #include "test/headless/discovery/discovery.h"
32 #include "test/headless/dumpsys/dumpsys.h"
33 #include "test/headless/get_options.h"
34 #include "test/headless/headless.h"
35 #include "test/headless/log.h"
36 #include "test/headless/mode/mode.h"
37 #include "test/headless/nop/nop.h"
38 #include "test/headless/pairing/pairing.h"
39 #include "test/headless/read/read.h"
40 #include "test/headless/scan/scan.h"
41 #include "test/headless/sdp/sdp.h"
42 #include "test/headless/util.h"
43
44 using namespace bluetooth::test::headless;
45 using namespace bluetooth;
46
47 int console_fd = -1;
48
49 namespace {
50
51 constexpr char kRedirectedStderrFilename[] = "/dev/null";
52 FILE* redirected_stderr_{nullptr};
53
54 // Ok...so if `stderr` stream is closed, the Android logging system will find
55 // another stream to write `LOG(<LogLevel>)` messages...any...stream.
56 // Unfortunately the next stream/fd is the bluetooth snooplog output
57 // file, so then a btsnoop_hci.log will interleave both raw hci packet
58 // data and Android LOG files preventing proper capture of hci traffic.
59 // To mitigate this, the `stderr` stream is redirected to another user
60 // provided stream, may be `/dev/null`, may be any file if so desired.
61 // This keeps everybody happy.
start_trick_the_android_logging_subsystem()62 void start_trick_the_android_logging_subsystem() {
63 redirected_stderr_ = freopen(kRedirectedStderrFilename, "w", stderr);
64 log::assert_that(redirected_stderr_ != nullptr,
65 "Unable to open redirected stderr file");
66 }
67
stop_trick_the_android_logging_subsystem()68 void stop_trick_the_android_logging_subsystem() {
69 log::assert_that(redirected_stderr_ != nullptr,
70 "assert failed: redirected_stderr_ != nullptr");
71 fclose(redirected_stderr_);
72 redirected_stderr_ = nullptr;
73 }
74
clear_logcat()75 void clear_logcat() {
76 int pid;
77 if ((pid = fork())) {
78 // parent process
79 int status;
80 waitpid(pid, &status, 0); // wait for the child to exit
81 log::assert_that(WIFEXITED(status), "Unable to clear logcat");
82 } else {
83 // child process
84 const char exec[] = "/system/bin/logcat";
85 const char arg0[] = "-c";
86
87 execl(exec, exec, arg0, NULL);
88
89 log::fatal("Should not return from exec process");
90 }
91 }
92
93 class Main : public HeadlessTest<int> {
94 public:
Main(const bluetooth::test::headless::GetOpt & options)95 Main(const bluetooth::test::headless::GetOpt& options)
96 : HeadlessTest<int>(options) {
97 test_nodes_.emplace(
98 "adapter",
99 std::make_unique<bluetooth::test::headless::Adapter>(options));
100 test_nodes_.emplace(
101 "dumpsys",
102 std::make_unique<bluetooth::test::headless::Dumpsys>(options));
103 test_nodes_.emplace(
104 "connect",
105 std::make_unique<bluetooth::test::headless::Connect>(options));
106 test_nodes_.emplace(
107 "mode", std::make_unique<bluetooth::test::headless::Mode>(options));
108 test_nodes_.emplace(
109 "nop", std::make_unique<bluetooth::test::headless::Nop>(options));
110 test_nodes_.emplace(
111 "pairing",
112 std::make_unique<bluetooth::test::headless::Pairing>(options));
113 test_nodes_.emplace(
114 "read", std::make_unique<bluetooth::test::headless::Read>(options));
115 test_nodes_.emplace(
116 "scan", std::make_unique<bluetooth::test::headless::Scan>(options));
117 test_nodes_.emplace(
118 "sdp", std::make_unique<bluetooth::test::headless::Sdp>(options));
119 test_nodes_.emplace(
120 "discovery",
121 std::make_unique<bluetooth::test::headless::Discovery>(options));
122 }
123
Run()124 int Run() override {
125 console_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO);
126 log::assert_that(console_fd != -1, "assert failed: console_fd != -1");
127 if (options_.close_stderr_) {
128 fclose(stderr);
129 }
130
131 if (options_.clear_logcat_) {
132 clear_logcat();
133 }
134
135 start_trick_the_android_logging_subsystem();
136 if (is_android_running()) {
137 LOG_CONSOLE("Android must be shutdown for binary to run");
138 LOG_CONSOLE(" /system/bin/stop");
139 return -1;
140 }
141 LOG_CONSOLE("bt_headless version:\'%s\'", build_id().c_str());
142 int rc = HeadlessTest<int>::Run();
143 stop_trick_the_android_logging_subsystem();
144 return rc;
145 }
146 };
147
148 } // namespace
149
main(int argc,char ** argv)150 int main(int argc, char** argv) {
151 fflush(nullptr);
152 setvbuf(stdout, nullptr, _IOLBF, 0);
153
154 bluetooth::test::headless::GetOpt options(argc, argv);
155 if (!options.IsValid()) {
156 return -1;
157 }
158
159 Main main(options);
160 return main.Run();
161 }
162