1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include "minadbd_services.h"
18*e7c364b6SAndroid Build Coastguard Worker
19*e7c364b6SAndroid Build Coastguard Worker #include <errno.h>
20*e7c364b6SAndroid Build Coastguard Worker #include <inttypes.h>
21*e7c364b6SAndroid Build Coastguard Worker #include <stdio.h>
22*e7c364b6SAndroid Build Coastguard Worker #include <stdlib.h>
23*e7c364b6SAndroid Build Coastguard Worker #include <string.h>
24*e7c364b6SAndroid Build Coastguard Worker #include <unistd.h>
25*e7c364b6SAndroid Build Coastguard Worker
26*e7c364b6SAndroid Build Coastguard Worker #include <chrono>
27*e7c364b6SAndroid Build Coastguard Worker #include <functional>
28*e7c364b6SAndroid Build Coastguard Worker #include <memory>
29*e7c364b6SAndroid Build Coastguard Worker #include <set>
30*e7c364b6SAndroid Build Coastguard Worker #include <string>
31*e7c364b6SAndroid Build Coastguard Worker #include <string_view>
32*e7c364b6SAndroid Build Coastguard Worker #include <thread>
33*e7c364b6SAndroid Build Coastguard Worker
34*e7c364b6SAndroid Build Coastguard Worker #include <android-base/file.h>
35*e7c364b6SAndroid Build Coastguard Worker #include <android-base/logging.h>
36*e7c364b6SAndroid Build Coastguard Worker #include <android-base/memory.h>
37*e7c364b6SAndroid Build Coastguard Worker #include <android-base/parseint.h>
38*e7c364b6SAndroid Build Coastguard Worker #include <android-base/properties.h>
39*e7c364b6SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
40*e7c364b6SAndroid Build Coastguard Worker #include <android-base/strings.h>
41*e7c364b6SAndroid Build Coastguard Worker
42*e7c364b6SAndroid Build Coastguard Worker #include "adb.h"
43*e7c364b6SAndroid Build Coastguard Worker #include "adb_unique_fd.h"
44*e7c364b6SAndroid Build Coastguard Worker #include "adb_utils.h"
45*e7c364b6SAndroid Build Coastguard Worker #include "fuse_adb_provider.h"
46*e7c364b6SAndroid Build Coastguard Worker #include "fuse_sideload.h"
47*e7c364b6SAndroid Build Coastguard Worker #include "minadbd/types.h"
48*e7c364b6SAndroid Build Coastguard Worker #include "recovery_utils/battery_utils.h"
49*e7c364b6SAndroid Build Coastguard Worker #include "services.h"
50*e7c364b6SAndroid Build Coastguard Worker #include "sysdeps.h"
51*e7c364b6SAndroid Build Coastguard Worker
52*e7c364b6SAndroid Build Coastguard Worker static int minadbd_socket = -1;
53*e7c364b6SAndroid Build Coastguard Worker static bool rescue_mode = false;
54*e7c364b6SAndroid Build Coastguard Worker static std::string sideload_mount_point = FUSE_SIDELOAD_HOST_MOUNTPOINT;
55*e7c364b6SAndroid Build Coastguard Worker
SetMinadbdSocketFd(int socket_fd)56*e7c364b6SAndroid Build Coastguard Worker void SetMinadbdSocketFd(int socket_fd) {
57*e7c364b6SAndroid Build Coastguard Worker minadbd_socket = socket_fd;
58*e7c364b6SAndroid Build Coastguard Worker }
59*e7c364b6SAndroid Build Coastguard Worker
SetMinadbdRescueMode(bool rescue)60*e7c364b6SAndroid Build Coastguard Worker void SetMinadbdRescueMode(bool rescue) {
61*e7c364b6SAndroid Build Coastguard Worker rescue_mode = rescue;
62*e7c364b6SAndroid Build Coastguard Worker }
63*e7c364b6SAndroid Build Coastguard Worker
SetSideloadMountPoint(const std::string & path)64*e7c364b6SAndroid Build Coastguard Worker void SetSideloadMountPoint(const std::string& path) {
65*e7c364b6SAndroid Build Coastguard Worker sideload_mount_point = path;
66*e7c364b6SAndroid Build Coastguard Worker }
67*e7c364b6SAndroid Build Coastguard Worker
WriteCommandToFd(MinadbdCommand cmd,int fd)68*e7c364b6SAndroid Build Coastguard Worker static bool WriteCommandToFd(MinadbdCommand cmd, int fd) {
69*e7c364b6SAndroid Build Coastguard Worker char message[kMinadbdMessageSize];
70*e7c364b6SAndroid Build Coastguard Worker memcpy(message, kMinadbdCommandPrefix, strlen(kMinadbdStatusPrefix));
71*e7c364b6SAndroid Build Coastguard Worker android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), cmd);
72*e7c364b6SAndroid Build Coastguard Worker
73*e7c364b6SAndroid Build Coastguard Worker if (!android::base::WriteFully(fd, message, kMinadbdMessageSize)) {
74*e7c364b6SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to write message " << message;
75*e7c364b6SAndroid Build Coastguard Worker return false;
76*e7c364b6SAndroid Build Coastguard Worker }
77*e7c364b6SAndroid Build Coastguard Worker return true;
78*e7c364b6SAndroid Build Coastguard Worker }
79*e7c364b6SAndroid Build Coastguard Worker
80*e7c364b6SAndroid Build Coastguard Worker // Blocks and reads the command status from |fd|. Returns false if the received message has a
81*e7c364b6SAndroid Build Coastguard Worker // format error.
WaitForCommandStatus(int fd,MinadbdCommandStatus * status)82*e7c364b6SAndroid Build Coastguard Worker static bool WaitForCommandStatus(int fd, MinadbdCommandStatus* status) {
83*e7c364b6SAndroid Build Coastguard Worker char buffer[kMinadbdMessageSize];
84*e7c364b6SAndroid Build Coastguard Worker if (!android::base::ReadFully(fd, buffer, kMinadbdMessageSize)) {
85*e7c364b6SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to response status from socket";
86*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdSocketIOError);
87*e7c364b6SAndroid Build Coastguard Worker }
88*e7c364b6SAndroid Build Coastguard Worker
89*e7c364b6SAndroid Build Coastguard Worker std::string message(buffer, buffer + kMinadbdMessageSize);
90*e7c364b6SAndroid Build Coastguard Worker if (!android::base::StartsWith(message, kMinadbdStatusPrefix)) {
91*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse status in " << message;
92*e7c364b6SAndroid Build Coastguard Worker return false;
93*e7c364b6SAndroid Build Coastguard Worker }
94*e7c364b6SAndroid Build Coastguard Worker
95*e7c364b6SAndroid Build Coastguard Worker *status = android::base::get_unaligned<MinadbdCommandStatus>(
96*e7c364b6SAndroid Build Coastguard Worker message.substr(strlen(kMinadbdStatusPrefix)).c_str());
97*e7c364b6SAndroid Build Coastguard Worker return true;
98*e7c364b6SAndroid Build Coastguard Worker }
99*e7c364b6SAndroid Build Coastguard Worker
RunAdbFuseSideload(int sfd,const std::string & args,MinadbdCommandStatus * status)100*e7c364b6SAndroid Build Coastguard Worker static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args,
101*e7c364b6SAndroid Build Coastguard Worker MinadbdCommandStatus* status) {
102*e7c364b6SAndroid Build Coastguard Worker auto pieces = android::base::Split(args, ":");
103*e7c364b6SAndroid Build Coastguard Worker int64_t file_size;
104*e7c364b6SAndroid Build Coastguard Worker int block_size;
105*e7c364b6SAndroid Build Coastguard Worker if (pieces.size() != 2 || !android::base::ParseInt(pieces[0], &file_size) || file_size <= 0 ||
106*e7c364b6SAndroid Build Coastguard Worker !android::base::ParseInt(pieces[1], &block_size) || block_size <= 0) {
107*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "bad sideload-host arguments: " << args;
108*e7c364b6SAndroid Build Coastguard Worker return kMinadbdHostCommandArgumentError;
109*e7c364b6SAndroid Build Coastguard Worker }
110*e7c364b6SAndroid Build Coastguard Worker
111*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "sideload-host file size " << file_size << ", block size " << block_size;
112*e7c364b6SAndroid Build Coastguard Worker
113*e7c364b6SAndroid Build Coastguard Worker if (!WriteCommandToFd(MinadbdCommand::kInstall, minadbd_socket)) {
114*e7c364b6SAndroid Build Coastguard Worker return kMinadbdSocketIOError;
115*e7c364b6SAndroid Build Coastguard Worker }
116*e7c364b6SAndroid Build Coastguard Worker
117*e7c364b6SAndroid Build Coastguard Worker auto adb_data_reader = std::make_unique<FuseAdbDataProvider>(sfd, file_size, block_size);
118*e7c364b6SAndroid Build Coastguard Worker if (int result = run_fuse_sideload(std::move(adb_data_reader), sideload_mount_point.c_str());
119*e7c364b6SAndroid Build Coastguard Worker result != 0) {
120*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to start fuse";
121*e7c364b6SAndroid Build Coastguard Worker return kMinadbdFuseStartError;
122*e7c364b6SAndroid Build Coastguard Worker }
123*e7c364b6SAndroid Build Coastguard Worker
124*e7c364b6SAndroid Build Coastguard Worker if (!WaitForCommandStatus(minadbd_socket, status)) {
125*e7c364b6SAndroid Build Coastguard Worker return kMinadbdMessageFormatError;
126*e7c364b6SAndroid Build Coastguard Worker }
127*e7c364b6SAndroid Build Coastguard Worker
128*e7c364b6SAndroid Build Coastguard Worker // Signal host-side adb to stop. For sideload mode, we always send kMinadbdServicesExitSuccess
129*e7c364b6SAndroid Build Coastguard Worker // (i.e. "DONEDONE") regardless of the install result. For rescue mode, we send failure message on
130*e7c364b6SAndroid Build Coastguard Worker // install error.
131*e7c364b6SAndroid Build Coastguard Worker if (!rescue_mode || *status == MinadbdCommandStatus::kSuccess) {
132*e7c364b6SAndroid Build Coastguard Worker if (!android::base::WriteFully(sfd, kMinadbdServicesExitSuccess,
133*e7c364b6SAndroid Build Coastguard Worker strlen(kMinadbdServicesExitSuccess))) {
134*e7c364b6SAndroid Build Coastguard Worker return kMinadbdHostSocketIOError;
135*e7c364b6SAndroid Build Coastguard Worker }
136*e7c364b6SAndroid Build Coastguard Worker } else {
137*e7c364b6SAndroid Build Coastguard Worker if (!android::base::WriteFully(sfd, kMinadbdServicesExitFailure,
138*e7c364b6SAndroid Build Coastguard Worker strlen(kMinadbdServicesExitFailure))) {
139*e7c364b6SAndroid Build Coastguard Worker return kMinadbdHostSocketIOError;
140*e7c364b6SAndroid Build Coastguard Worker }
141*e7c364b6SAndroid Build Coastguard Worker }
142*e7c364b6SAndroid Build Coastguard Worker
143*e7c364b6SAndroid Build Coastguard Worker return kMinadbdSuccess;
144*e7c364b6SAndroid Build Coastguard Worker }
145*e7c364b6SAndroid Build Coastguard Worker
WaitForSocketClose(int fd,std::chrono::milliseconds timeout)146*e7c364b6SAndroid Build Coastguard Worker static bool WaitForSocketClose(int fd, std::chrono::milliseconds timeout) {
147*e7c364b6SAndroid Build Coastguard Worker const auto begin = std::chrono::steady_clock::now();
148*e7c364b6SAndroid Build Coastguard Worker const auto end = begin + timeout;
149*e7c364b6SAndroid Build Coastguard Worker while (std::chrono::steady_clock::now() < end) {
150*e7c364b6SAndroid Build Coastguard Worker // We don't care about reading the socket, we just want to wait until
151*e7c364b6SAndroid Build Coastguard Worker // socket closes. In this case .events = 0 will tell the kernel to wait
152*e7c364b6SAndroid Build Coastguard Worker // for close events.
153*e7c364b6SAndroid Build Coastguard Worker struct pollfd pfd = { .fd = fd, .events = 0 };
154*e7c364b6SAndroid Build Coastguard Worker auto timeout_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
155*e7c364b6SAndroid Build Coastguard Worker end - std::chrono::steady_clock::now())
156*e7c364b6SAndroid Build Coastguard Worker .count();
157*e7c364b6SAndroid Build Coastguard Worker int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, timeout_ms));
158*e7c364b6SAndroid Build Coastguard Worker if (rc == 1) {
159*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "revents: " << pfd.revents;
160*e7c364b6SAndroid Build Coastguard Worker if (pfd.revents & (POLLHUP | POLLRDHUP)) {
161*e7c364b6SAndroid Build Coastguard Worker return true;
162*e7c364b6SAndroid Build Coastguard Worker }
163*e7c364b6SAndroid Build Coastguard Worker } else {
164*e7c364b6SAndroid Build Coastguard Worker PLOG(ERROR) << "poll() failed";
165*e7c364b6SAndroid Build Coastguard Worker // poll failed, almost definitely due to timeout
166*e7c364b6SAndroid Build Coastguard Worker // If not, you're screwed anyway, because it probably means the kernel ran
167*e7c364b6SAndroid Build Coastguard Worker // out of memory.
168*e7c364b6SAndroid Build Coastguard Worker return false;
169*e7c364b6SAndroid Build Coastguard Worker }
170*e7c364b6SAndroid Build Coastguard Worker }
171*e7c364b6SAndroid Build Coastguard Worker return false;
172*e7c364b6SAndroid Build Coastguard Worker }
173*e7c364b6SAndroid Build Coastguard Worker
174*e7c364b6SAndroid Build Coastguard Worker // Sideload service always exits after serving an install command.
SideloadHostService(unique_fd sfd,const std::string & args)175*e7c364b6SAndroid Build Coastguard Worker static void SideloadHostService(unique_fd sfd, const std::string& args) {
176*e7c364b6SAndroid Build Coastguard Worker using namespace std::chrono_literals;
177*e7c364b6SAndroid Build Coastguard Worker MinadbdCommandStatus status;
178*e7c364b6SAndroid Build Coastguard Worker auto error = RunAdbFuseSideload(sfd.get(), args, &status);
179*e7c364b6SAndroid Build Coastguard Worker // No need to wait if the socket is already closed, meaning the other end
180*e7c364b6SAndroid Build Coastguard Worker // already exited for some reason.
181*e7c364b6SAndroid Build Coastguard Worker if (error != kMinadbdHostSocketIOError) {
182*e7c364b6SAndroid Build Coastguard Worker // We sleep for a little bit just to wait for the host to receive last
183*e7c364b6SAndroid Build Coastguard Worker // "DONEDONE" message. However minadbd process is likely to get terminated
184*e7c364b6SAndroid Build Coastguard Worker // early due to exit_on_close
185*e7c364b6SAndroid Build Coastguard Worker WaitForSocketClose(sfd, 3000ms);
186*e7c364b6SAndroid Build Coastguard Worker }
187*e7c364b6SAndroid Build Coastguard Worker exit(error);
188*e7c364b6SAndroid Build Coastguard Worker }
189*e7c364b6SAndroid Build Coastguard Worker
190*e7c364b6SAndroid Build Coastguard Worker // Rescue service waits for the next command after an install command.
RescueInstallHostService(unique_fd sfd,const std::string & args)191*e7c364b6SAndroid Build Coastguard Worker static void RescueInstallHostService(unique_fd sfd, const std::string& args) {
192*e7c364b6SAndroid Build Coastguard Worker MinadbdCommandStatus status;
193*e7c364b6SAndroid Build Coastguard Worker if (auto result = RunAdbFuseSideload(sfd.get(), args, &status); result != kMinadbdSuccess) {
194*e7c364b6SAndroid Build Coastguard Worker exit(result);
195*e7c364b6SAndroid Build Coastguard Worker }
196*e7c364b6SAndroid Build Coastguard Worker }
197*e7c364b6SAndroid Build Coastguard Worker
198*e7c364b6SAndroid Build Coastguard Worker // Answers the query on a given property |prop|, by writing the result to the given |sfd|. The
199*e7c364b6SAndroid Build Coastguard Worker // result will be newline-terminated, so nonexistent or nonallowed query will be answered with "\n".
200*e7c364b6SAndroid Build Coastguard Worker // If given an empty string, dumps all the supported properties (analogous to `adb shell getprop`)
201*e7c364b6SAndroid Build Coastguard Worker // in lines, e.g. "[prop]: [value]".
RescueGetpropHostService(unique_fd sfd,const std::string & prop)202*e7c364b6SAndroid Build Coastguard Worker static void RescueGetpropHostService(unique_fd sfd, const std::string& prop) {
203*e7c364b6SAndroid Build Coastguard Worker constexpr const char* kRescueBatteryLevelProp = "rescue.battery_level";
204*e7c364b6SAndroid Build Coastguard Worker static const std::set<std::string> kGetpropAllowedProps = {
205*e7c364b6SAndroid Build Coastguard Worker // clang-format off
206*e7c364b6SAndroid Build Coastguard Worker kRescueBatteryLevelProp,
207*e7c364b6SAndroid Build Coastguard Worker "ro.build.date.utc",
208*e7c364b6SAndroid Build Coastguard Worker "ro.build.fingerprint",
209*e7c364b6SAndroid Build Coastguard Worker "ro.build.flavor",
210*e7c364b6SAndroid Build Coastguard Worker "ro.build.id",
211*e7c364b6SAndroid Build Coastguard Worker "ro.build.product",
212*e7c364b6SAndroid Build Coastguard Worker "ro.build.tags",
213*e7c364b6SAndroid Build Coastguard Worker "ro.build.version.incremental",
214*e7c364b6SAndroid Build Coastguard Worker "ro.product.device",
215*e7c364b6SAndroid Build Coastguard Worker "ro.product.vendor.device",
216*e7c364b6SAndroid Build Coastguard Worker // clang-format on
217*e7c364b6SAndroid Build Coastguard Worker };
218*e7c364b6SAndroid Build Coastguard Worker
219*e7c364b6SAndroid Build Coastguard Worker auto query_prop = [](const std::string& key) {
220*e7c364b6SAndroid Build Coastguard Worker if (key == kRescueBatteryLevelProp) {
221*e7c364b6SAndroid Build Coastguard Worker auto battery_info = GetBatteryInfo();
222*e7c364b6SAndroid Build Coastguard Worker return std::to_string(battery_info.capacity);
223*e7c364b6SAndroid Build Coastguard Worker }
224*e7c364b6SAndroid Build Coastguard Worker return android::base::GetProperty(key, "");
225*e7c364b6SAndroid Build Coastguard Worker };
226*e7c364b6SAndroid Build Coastguard Worker
227*e7c364b6SAndroid Build Coastguard Worker std::string result;
228*e7c364b6SAndroid Build Coastguard Worker if (prop.empty()) {
229*e7c364b6SAndroid Build Coastguard Worker for (const auto& key : kGetpropAllowedProps) {
230*e7c364b6SAndroid Build Coastguard Worker auto value = query_prop(key);
231*e7c364b6SAndroid Build Coastguard Worker if (value.empty()) {
232*e7c364b6SAndroid Build Coastguard Worker continue;
233*e7c364b6SAndroid Build Coastguard Worker }
234*e7c364b6SAndroid Build Coastguard Worker result += "[" + key + "]: [" + value + "]\n";
235*e7c364b6SAndroid Build Coastguard Worker }
236*e7c364b6SAndroid Build Coastguard Worker } else if (kGetpropAllowedProps.contains(prop)) {
237*e7c364b6SAndroid Build Coastguard Worker result = query_prop(prop) + "\n";
238*e7c364b6SAndroid Build Coastguard Worker }
239*e7c364b6SAndroid Build Coastguard Worker if (result.empty()) {
240*e7c364b6SAndroid Build Coastguard Worker result = "\n";
241*e7c364b6SAndroid Build Coastguard Worker }
242*e7c364b6SAndroid Build Coastguard Worker if (!android::base::WriteFully(sfd, result.data(), result.size())) {
243*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdHostSocketIOError);
244*e7c364b6SAndroid Build Coastguard Worker }
245*e7c364b6SAndroid Build Coastguard Worker
246*e7c364b6SAndroid Build Coastguard Worker // Send heartbeat signal to keep the rescue service alive.
247*e7c364b6SAndroid Build Coastguard Worker if (!WriteCommandToFd(MinadbdCommand::kNoOp, minadbd_socket)) {
248*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdSocketIOError);
249*e7c364b6SAndroid Build Coastguard Worker }
250*e7c364b6SAndroid Build Coastguard Worker if (MinadbdCommandStatus status; !WaitForCommandStatus(minadbd_socket, &status)) {
251*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdMessageFormatError);
252*e7c364b6SAndroid Build Coastguard Worker }
253*e7c364b6SAndroid Build Coastguard Worker }
254*e7c364b6SAndroid Build Coastguard Worker
255*e7c364b6SAndroid Build Coastguard Worker // Reboots into the given target. We don't reboot directly from minadbd, but going through recovery
256*e7c364b6SAndroid Build Coastguard Worker // instead. This allows recovery to finish all the pending works (clear BCB, save logs etc) before
257*e7c364b6SAndroid Build Coastguard Worker // the reboot.
RebootHostService(unique_fd,const std::string & target)258*e7c364b6SAndroid Build Coastguard Worker static void RebootHostService(unique_fd /* sfd */, const std::string& target) {
259*e7c364b6SAndroid Build Coastguard Worker MinadbdCommand command;
260*e7c364b6SAndroid Build Coastguard Worker if (target == "bootloader") {
261*e7c364b6SAndroid Build Coastguard Worker command = MinadbdCommand::kRebootBootloader;
262*e7c364b6SAndroid Build Coastguard Worker } else if (target == "rescue") {
263*e7c364b6SAndroid Build Coastguard Worker command = MinadbdCommand::kRebootRescue;
264*e7c364b6SAndroid Build Coastguard Worker } else if (target == "recovery") {
265*e7c364b6SAndroid Build Coastguard Worker command = MinadbdCommand::kRebootRecovery;
266*e7c364b6SAndroid Build Coastguard Worker } else if (target == "fastboot") {
267*e7c364b6SAndroid Build Coastguard Worker command = MinadbdCommand::kRebootFastboot;
268*e7c364b6SAndroid Build Coastguard Worker } else {
269*e7c364b6SAndroid Build Coastguard Worker command = MinadbdCommand::kRebootAndroid;
270*e7c364b6SAndroid Build Coastguard Worker }
271*e7c364b6SAndroid Build Coastguard Worker if (!WriteCommandToFd(command, minadbd_socket)) {
272*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdSocketIOError);
273*e7c364b6SAndroid Build Coastguard Worker }
274*e7c364b6SAndroid Build Coastguard Worker MinadbdCommandStatus status;
275*e7c364b6SAndroid Build Coastguard Worker if (!WaitForCommandStatus(minadbd_socket, &status)) {
276*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdMessageFormatError);
277*e7c364b6SAndroid Build Coastguard Worker }
278*e7c364b6SAndroid Build Coastguard Worker }
279*e7c364b6SAndroid Build Coastguard Worker
WipeDeviceService(unique_fd fd,const std::string & args)280*e7c364b6SAndroid Build Coastguard Worker static void WipeDeviceService(unique_fd fd, const std::string& args) {
281*e7c364b6SAndroid Build Coastguard Worker auto pieces = android::base::Split(args, ":");
282*e7c364b6SAndroid Build Coastguard Worker if (pieces.size() != 2 || pieces[0] != "userdata") {
283*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse wipe device command arguments " << args;
284*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdHostCommandArgumentError);
285*e7c364b6SAndroid Build Coastguard Worker }
286*e7c364b6SAndroid Build Coastguard Worker
287*e7c364b6SAndroid Build Coastguard Worker size_t message_size;
288*e7c364b6SAndroid Build Coastguard Worker if (!android::base::ParseUint(pieces[1], &message_size) ||
289*e7c364b6SAndroid Build Coastguard Worker message_size < strlen(kMinadbdServicesExitSuccess)) {
290*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse wipe device message size in " << args;
291*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdHostCommandArgumentError);
292*e7c364b6SAndroid Build Coastguard Worker }
293*e7c364b6SAndroid Build Coastguard Worker
294*e7c364b6SAndroid Build Coastguard Worker WriteCommandToFd(MinadbdCommand::kWipeData, minadbd_socket);
295*e7c364b6SAndroid Build Coastguard Worker MinadbdCommandStatus status;
296*e7c364b6SAndroid Build Coastguard Worker if (!WaitForCommandStatus(minadbd_socket, &status)) {
297*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdMessageFormatError);
298*e7c364b6SAndroid Build Coastguard Worker }
299*e7c364b6SAndroid Build Coastguard Worker
300*e7c364b6SAndroid Build Coastguard Worker std::string response = (status == MinadbdCommandStatus::kSuccess) ? kMinadbdServicesExitSuccess
301*e7c364b6SAndroid Build Coastguard Worker : kMinadbdServicesExitFailure;
302*e7c364b6SAndroid Build Coastguard Worker response += std::string(message_size - response.size(), '\0');
303*e7c364b6SAndroid Build Coastguard Worker if (!android::base::WriteFully(fd, response.c_str(), response.size())) {
304*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdHostSocketIOError);
305*e7c364b6SAndroid Build Coastguard Worker }
306*e7c364b6SAndroid Build Coastguard Worker }
307*e7c364b6SAndroid Build Coastguard Worker
daemon_service_to_socket(std::string_view,atransport *)308*e7c364b6SAndroid Build Coastguard Worker asocket* daemon_service_to_socket(std::string_view, atransport*) {
309*e7c364b6SAndroid Build Coastguard Worker return nullptr;
310*e7c364b6SAndroid Build Coastguard Worker }
311*e7c364b6SAndroid Build Coastguard Worker
daemon_service_to_fd(std::string_view name,atransport *)312*e7c364b6SAndroid Build Coastguard Worker unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport */) {
313*e7c364b6SAndroid Build Coastguard Worker // Common services that are supported both in sideload and rescue modes.
314*e7c364b6SAndroid Build Coastguard Worker if (android::base::ConsumePrefix(&name, "reboot:")) {
315*e7c364b6SAndroid Build Coastguard Worker // "reboot:<target>", where target must be one of the following.
316*e7c364b6SAndroid Build Coastguard Worker std::string args(name);
317*e7c364b6SAndroid Build Coastguard Worker if (args.empty() || args == "bootloader" || args == "rescue" || args == "recovery" ||
318*e7c364b6SAndroid Build Coastguard Worker args == "fastboot") {
319*e7c364b6SAndroid Build Coastguard Worker return create_service_thread("reboot",
320*e7c364b6SAndroid Build Coastguard Worker std::bind(RebootHostService, std::placeholders::_1, args));
321*e7c364b6SAndroid Build Coastguard Worker }
322*e7c364b6SAndroid Build Coastguard Worker return unique_fd{};
323*e7c364b6SAndroid Build Coastguard Worker }
324*e7c364b6SAndroid Build Coastguard Worker
325*e7c364b6SAndroid Build Coastguard Worker // Rescue-specific services.
326*e7c364b6SAndroid Build Coastguard Worker if (rescue_mode) {
327*e7c364b6SAndroid Build Coastguard Worker if (android::base::ConsumePrefix(&name, "rescue-install:")) {
328*e7c364b6SAndroid Build Coastguard Worker // rescue-install:<file-size>:<block-size>
329*e7c364b6SAndroid Build Coastguard Worker std::string args(name);
330*e7c364b6SAndroid Build Coastguard Worker return create_service_thread(
331*e7c364b6SAndroid Build Coastguard Worker "rescue-install", std::bind(RescueInstallHostService, std::placeholders::_1, args));
332*e7c364b6SAndroid Build Coastguard Worker } else if (android::base::ConsumePrefix(&name, "rescue-getprop:")) {
333*e7c364b6SAndroid Build Coastguard Worker // rescue-getprop:<prop>
334*e7c364b6SAndroid Build Coastguard Worker std::string args(name);
335*e7c364b6SAndroid Build Coastguard Worker return create_service_thread(
336*e7c364b6SAndroid Build Coastguard Worker "rescue-getprop", std::bind(RescueGetpropHostService, std::placeholders::_1, args));
337*e7c364b6SAndroid Build Coastguard Worker } else if (android::base::ConsumePrefix(&name, "rescue-wipe:")) {
338*e7c364b6SAndroid Build Coastguard Worker // rescue-wipe:target:<message-size>
339*e7c364b6SAndroid Build Coastguard Worker std::string args(name);
340*e7c364b6SAndroid Build Coastguard Worker return create_service_thread("rescue-wipe",
341*e7c364b6SAndroid Build Coastguard Worker std::bind(WipeDeviceService, std::placeholders::_1, args));
342*e7c364b6SAndroid Build Coastguard Worker }
343*e7c364b6SAndroid Build Coastguard Worker
344*e7c364b6SAndroid Build Coastguard Worker return unique_fd{};
345*e7c364b6SAndroid Build Coastguard Worker }
346*e7c364b6SAndroid Build Coastguard Worker
347*e7c364b6SAndroid Build Coastguard Worker // Sideload-specific services.
348*e7c364b6SAndroid Build Coastguard Worker if (name.starts_with("sideload:")) {
349*e7c364b6SAndroid Build Coastguard Worker // This exit status causes recovery to print a special error message saying to use a newer adb
350*e7c364b6SAndroid Build Coastguard Worker // (that supports sideload-host).
351*e7c364b6SAndroid Build Coastguard Worker exit(kMinadbdAdbVersionError);
352*e7c364b6SAndroid Build Coastguard Worker } else if (android::base::ConsumePrefix(&name, "sideload-host:")) {
353*e7c364b6SAndroid Build Coastguard Worker // sideload-host:<file-size>:<block-size>
354*e7c364b6SAndroid Build Coastguard Worker std::string args(name);
355*e7c364b6SAndroid Build Coastguard Worker return create_service_thread("sideload-host",
356*e7c364b6SAndroid Build Coastguard Worker std::bind(SideloadHostService, std::placeholders::_1, args));
357*e7c364b6SAndroid Build Coastguard Worker }
358*e7c364b6SAndroid Build Coastguard Worker return unique_fd{};
359*e7c364b6SAndroid Build Coastguard Worker }
360