1 /*
2  * Copyright (C) 2018 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 #include "adb.h"
18 #include "adb_io.h"
19 #include "adb_unique_fd.h"
20 #include "adb_utils.h"
21 #include "shell_service.h"
22 
23 #include <android-base/cmsg.h>
24 
25 namespace {
26 
27 struct AbbProcess;
28 static auto& abbp = *new std::unique_ptr<AbbProcess>(std::make_unique<AbbProcess>());
29 
30 struct AbbProcess {
31     unique_fd sendCommand(std::string_view command);
32 
33   private:
34     static unique_fd startAbbProcess(unique_fd* error_fd);
35 
36     static constexpr auto kRetries = 2;
37     static constexpr auto kErrorProtocol = SubprocessProtocol::kShell;
38 
39     std::mutex locker_;
40     unique_fd socket_fd_;
41 };
42 
sendCommand(std::string_view command)43 unique_fd AbbProcess::sendCommand(std::string_view command) {
44     std::unique_lock lock{locker_};
45 
46     for (int i = 0; i < kRetries; ++i) {
47         unique_fd error_fd;
48         if (socket_fd_ == -1) {
49             socket_fd_ = startAbbProcess(&error_fd);
50         }
51         if (socket_fd_ == -1) {
52             LOG(ERROR) << "failed to start abb process";
53             return error_fd;
54         }
55 
56         if (!SendProtocolString(socket_fd_, command)) {
57             PLOG(ERROR) << "failed to send command to abb";
58             socket_fd_.reset();
59             continue;
60         }
61 
62         unique_fd fd;
63         char buf;
64         if (android::base::ReceiveFileDescriptors(socket_fd_, &buf, 1, &fd) != 1) {
65             PLOG(ERROR) << "failed to receive FD from abb";
66             socket_fd_.reset();
67             continue;
68         }
69 
70         return fd;
71     }
72 
73     LOG(ERROR) << "abb is unavailable";
74     socket_fd_.reset();
75     return ReportError(kErrorProtocol, "abb is unavailable");
76 }
77 
startAbbProcess(unique_fd * error_fd)78 unique_fd AbbProcess::startAbbProcess(unique_fd* error_fd) {
79     constexpr auto abb_process_type = SubprocessType::kRaw;
80     constexpr auto abb_protocol = SubprocessProtocol::kNone;
81     constexpr auto make_pty_raw = false;
82     return StartSubprocess("abb", "dumb", abb_process_type, abb_protocol, make_pty_raw,
83                            kErrorProtocol, error_fd);
84 }
85 
86 }  // namespace
87 
execute_abb_command(std::string_view command)88 unique_fd execute_abb_command(std::string_view command) {
89     return abbp->sendCommand(command);
90 }
91