xref: /aosp_15_r20/frameworks/native/libs/adbd_auth/adbd_auth.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2019 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 ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
18 
19 #include "include/adbd_auth.h"
20 
21 #include <inttypes.h>
22 #include <sys/epoll.h>
23 #include <sys/eventfd.h>
24 #include <sys/uio.h>
25 
26 #include <atomic>
27 #include <chrono>
28 #include <deque>
29 #include <optional>
30 #include <string>
31 #include <string_view>
32 #include <tuple>
33 #include <unordered_map>
34 #include <utility>
35 #include <variant>
36 #include <vector>
37 
38 #include <android-base/file.h>
39 #include <android-base/logging.h>
40 #include <android-base/macros.h>
41 #include <android-base/strings.h>
42 #include <android-base/thread_annotations.h>
43 #include <android-base/unique_fd.h>
44 #include <cutils/sockets.h>
45 
46 using android::base::unique_fd;
47 
48 static constexpr uint32_t kAuthVersion = 1;
49 
50 struct AdbdAuthPacketAuthenticated {
51     std::string public_key;
52 };
53 
54 struct AdbdAuthPacketDisconnected {
55     std::string public_key;
56 };
57 
58 struct AdbdAuthPacketRequestAuthorization {
59     std::string public_key;
60 };
61 
62 struct AdbdPacketTlsDeviceConnected {
63     uint8_t transport_type;
64     std::string public_key;
65 };
66 
67 struct AdbdPacketTlsDeviceDisconnected {
68     uint8_t transport_type;
69     std::string public_key;
70 };
71 
72 using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated,
73                                     AdbdAuthPacketDisconnected,
74                                     AdbdAuthPacketRequestAuthorization,
75                                     AdbdPacketTlsDeviceConnected,
76                                     AdbdPacketTlsDeviceDisconnected>;
77 
78 struct AdbdAuthContext {
79     static constexpr uint64_t kEpollConstSocket = 0;
80     static constexpr uint64_t kEpollConstEventFd = 1;
81     static constexpr uint64_t kEpollConstFramework = 2;
82 
83 public:
AdbdAuthContextAdbdAuthContext84     explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
85         InitFrameworkHandlers();
86         epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
87         if (epoll_fd_ == -1) {
88             PLOG(FATAL) << "adbd_auth: failed to create epoll fd";
89         }
90 
91         event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
92         if (event_fd_ == -1) {
93             PLOG(FATAL) << "adbd_auth: failed to create eventfd";
94         }
95 
96         sock_fd_.reset(android_get_control_socket("adbd"));
97         if (sock_fd_ == -1) {
98             PLOG(ERROR) << "adbd_auth: failed to get adbd authentication socket";
99         } else {
100             if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
101                 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket cloexec";
102             }
103 
104             if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
105                 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket nonblocking";
106             }
107 
108             if (listen(sock_fd_.get(), 4) != 0) {
109                 PLOG(FATAL) << "adbd_auth: failed to listen on adbd authentication socket";
110             }
111         }
112     }
113 
114     AdbdAuthContext(const AdbdAuthContext& copy) = delete;
115     AdbdAuthContext(AdbdAuthContext&& move) = delete;
116     AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
117     AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
118 
NextIdAdbdAuthContext119     uint64_t NextId() { return next_id_++; }
120 
DispatchPendingPromptAdbdAuthContext121     void DispatchPendingPrompt() REQUIRES(mutex_) {
122         if (dispatched_prompt_) {
123             LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
124             return;
125         }
126 
127         if (pending_prompts_.empty()) {
128             LOG(INFO) << "adbd_auth: no prompts to send";
129             return;
130         }
131 
132         LOG(INFO) << "adbd_auth: prompting user for adb authentication";
133         auto [id, public_key, arg] = std::move(pending_prompts_.front());
134         pending_prompts_.pop_front();
135 
136         this->output_queue_.emplace_back(
137                 AdbdAuthPacketRequestAuthorization{.public_key = public_key});
138 
139         Interrupt();
140         dispatched_prompt_ = std::make_tuple(id, public_key, arg);
141     }
142 
UpdateFrameworkWritableAdbdAuthContext143     void UpdateFrameworkWritable() REQUIRES(mutex_) {
144         // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
145         // at the same time as a framework connection, but that's unlikely and this doesn't need to
146         // be fast anyway.
147         if (framework_fd_ != -1) {
148             struct epoll_event event;
149             event.events = EPOLLIN;
150             if (!output_queue_.empty()) {
151                 LOG(INFO) << "adbd_auth: marking framework writable";
152                 event.events |= EPOLLOUT;
153             }
154             event.data.u64 = kEpollConstFramework;
155             CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
156         }
157     }
158 
ReplaceFrameworkFdAdbdAuthContext159     void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
160         LOG(INFO) << "adbd_auth: received new framework fd " << new_fd.get()
161                   << " (current = " << framework_fd_.get() << ")";
162 
163         // If we already had a framework fd, clean up after ourselves.
164         if (framework_fd_ != -1) {
165             output_queue_.clear();
166             dispatched_prompt_.reset();
167             CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
168             framework_fd_.reset();
169         }
170 
171         if (new_fd != -1) {
172             struct epoll_event event;
173             event.events = EPOLLIN;
174             if (!output_queue_.empty()) {
175                 LOG(INFO) << "adbd_auth: marking framework writable";
176                 event.events |= EPOLLOUT;
177             }
178             event.data.u64 = kEpollConstFramework;
179             CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
180             framework_fd_ = std::move(new_fd);
181         }
182     }
183 
HandlePacketAdbdAuthContext184     void HandlePacket(std::string_view packet) EXCLUDES(mutex_) {
185         LOG(INFO) << "adbd_auth: received packet: " << packet;
186 
187         if (packet.size() < 2) {
188             LOG(ERROR) << "adbd_auth: received packet of invalid length";
189             std::lock_guard<std::mutex> lock(mutex_);
190             ReplaceFrameworkFd(unique_fd());
191         }
192 
193         bool handled_packet = false;
194         for (size_t i = 0; i < framework_handlers_.size(); ++i) {
195             if (android::base::ConsumePrefix(&packet, framework_handlers_[i].code)) {
196                 framework_handlers_[i].cb(packet);
197                 handled_packet = true;
198                 break;
199             }
200         }
201         if (!handled_packet) {
202             LOG(ERROR) << "adbd_auth: unhandled packet: " << packet;
203             std::lock_guard<std::mutex> lock(mutex_);
204             ReplaceFrameworkFd(unique_fd());
205         }
206     }
207 
AllowUsbDeviceAdbdAuthContext208     void AllowUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
209         std::lock_guard<std::mutex> lock(mutex_);
210         CHECK(buf.empty());
211 
212         if (dispatched_prompt_.has_value()) {
213             // It's possible for the framework to send us a response without our having sent a
214             // request to it: e.g. if adbd restarts while we have a pending request.
215             auto& [id, key, arg] = *dispatched_prompt_;
216             keys_.emplace(id, std::move(key));
217 
218             callbacks_.key_authorized(arg, id);
219             dispatched_prompt_ = std::nullopt;
220         } else {
221             LOG(WARNING) << "adbd_auth: received authorization for unknown prompt, ignoring";
222         }
223 
224         // We need to dispatch pending prompts here upon success as well,
225         // since we might have multiple queued prompts.
226         DispatchPendingPrompt();
227     }
228 
DenyUsbDeviceAdbdAuthContext229     void DenyUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
230         std::lock_guard<std::mutex> lock(mutex_);
231         CHECK(buf.empty());
232         // TODO: Do we want a callback if the key is denied?
233         dispatched_prompt_ = std::nullopt;
234         DispatchPendingPrompt();
235     }
236 
KeyRemovedAdbdAuthContext237     void KeyRemoved(std::string_view buf) EXCLUDES(mutex_) {
238         CHECK(!buf.empty());
239         callbacks_.key_removed(buf.data(), buf.size());
240     }
241 
SendPacketAdbdAuthContext242     bool SendPacket() REQUIRES(mutex_) {
243         if (output_queue_.empty()) {
244             return false;
245         }
246 
247         CHECK_NE(-1, framework_fd_.get());
248 
249         auto& packet = output_queue_.front();
250         struct iovec iovs[3];
251         int iovcnt = 2;
252         if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
253             iovs[0].iov_base = const_cast<char*>("CK");
254             iovs[0].iov_len = 2;
255             iovs[1].iov_base = p->public_key.data();
256             iovs[1].iov_len = p->public_key.size();
257         } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
258             iovs[0].iov_base = const_cast<char*>("DC");
259             iovs[0].iov_len = 2;
260             iovs[1].iov_base = p->public_key.data();
261             iovs[1].iov_len = p->public_key.size();
262         } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
263             iovs[0].iov_base = const_cast<char*>("PK");
264             iovs[0].iov_len = 2;
265             iovs[1].iov_base = p->public_key.data();
266             iovs[1].iov_len = p->public_key.size();
267         } else if (auto* p = std::get_if<AdbdPacketTlsDeviceConnected>(&packet)) {
268             iovcnt = 3;
269             iovs[0].iov_base = const_cast<char*>("WE");
270             iovs[0].iov_len = 2;
271             iovs[1].iov_base = &p->transport_type;
272             iovs[1].iov_len = 1;
273             iovs[2].iov_base = p->public_key.data();
274             iovs[2].iov_len = p->public_key.size();
275         } else if (auto* p = std::get_if<AdbdPacketTlsDeviceDisconnected>(&packet)) {
276             iovcnt = 3;
277             iovs[0].iov_base = const_cast<char*>("WF");
278             iovs[0].iov_len = 2;
279             iovs[1].iov_base = &p->transport_type;
280             iovs[1].iov_len = 1;
281             iovs[2].iov_base = p->public_key.data();
282             iovs[2].iov_len = p->public_key.size();
283         } else {
284             LOG(FATAL) << "adbd_auth: unhandled packet type?";
285         }
286 
287         ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
288         output_queue_.pop_front();
289         if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
290             PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
291             ReplaceFrameworkFd(unique_fd());
292             return false;
293         }
294 
295         return true;
296     }
297 
RunAdbdAuthContext298     void Run() {
299         if (sock_fd_ == -1) {
300             LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
301         } else {
302             struct epoll_event event;
303             event.events = EPOLLIN;
304             event.data.u64 = kEpollConstSocket;
305             CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
306         }
307 
308         {
309             struct epoll_event event;
310             event.events = EPOLLIN;
311             event.data.u64 = kEpollConstEventFd;
312             CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
313         }
314 
315         while (true) {
316             struct epoll_event events[3];
317             int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
318             if (rc == -1) {
319                 PLOG(FATAL) << "adbd_auth: epoll_wait failed";
320             } else if (rc == 0) {
321                 LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
322             }
323 
324             bool restart = false;
325             for (int i = 0; i < rc; ++i) {
326                 if (restart) {
327                     break;
328                 }
329 
330                 struct epoll_event& event = events[i];
331                 switch (event.data.u64) {
332                     case kEpollConstSocket: {
333                         unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
334                                                            SOCK_CLOEXEC | SOCK_NONBLOCK));
335                         if (new_framework_fd == -1) {
336                             PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
337                         }
338 
339                         LOG(INFO) << "adbd_auth: received a new framework connection";
340                         std::lock_guard<std::mutex> lock(mutex_);
341                         ReplaceFrameworkFd(std::move(new_framework_fd));
342 
343                         // Stop iterating over events: one of the later ones might be the old
344                         // framework fd.
345                         restart = false;
346                         break;
347                     }
348 
349                     case kEpollConstEventFd: {
350                         // We were woken up to write something.
351                         uint64_t dummy;
352                         int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
353                         if (rc != 8) {
354                             PLOG(FATAL)
355                                     << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
356                         }
357 
358                         std::lock_guard<std::mutex> lock(mutex_);
359                         UpdateFrameworkWritable();
360                         break;
361                     }
362 
363                     case kEpollConstFramework: {
364                         char buf[4096];
365                         if (event.events & EPOLLIN) {
366                             int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
367                             if (rc == -1) {
368                                 PLOG(FATAL) << "adbd_auth: failed to read from framework fd";
369                             } else if (rc == 0) {
370                                 LOG(INFO) << "adbd_auth: hit EOF on framework fd";
371                                 std::lock_guard<std::mutex> lock(mutex_);
372                                 ReplaceFrameworkFd(unique_fd());
373                             } else {
374                                 HandlePacket(std::string_view(buf, rc));
375                             }
376                         }
377 
378                         if (event.events & EPOLLOUT) {
379                             std::lock_guard<std::mutex> lock(mutex_);
380                             while (SendPacket()) {
381                                 continue;
382                             }
383                             UpdateFrameworkWritable();
384                         }
385 
386                         break;
387                     }
388                 }
389             }
390         }
391     }
392 
393     static constexpr std::pair<const char*, bool> key_paths[] = {
394         {"/adb_keys",               true  /* follow symlinks */       },
395         {"/data/misc/adb/adb_keys", false /* don't follow symlinks */ },
396     };
IteratePublicKeysAdbdAuthContext397     void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
398         for (const auto& [path, follow_symlinks] : key_paths) {
399             if (access(path, R_OK) == 0) {
400                 LOG(INFO) << "adbd_auth: loading keys from " << path;
401                 std::string content;
402                 if (!android::base::ReadFileToString(path, &content, follow_symlinks)) {
403                     PLOG(ERROR) << "adbd_auth: couldn't read " << path;
404                     continue;
405                 }
406                 for (const auto& line : android::base::Split(content, "\n")) {
407                     if (!callback(opaque, line.data(), line.size())) {
408                         return;
409                     }
410                 }
411             }
412         }
413     }
414 
PromptUserAdbdAuthContext415     uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
416         uint64_t id = NextId();
417 
418         std::lock_guard<std::mutex> lock(mutex_);
419         LOG(INFO) << "adbd_auth: sending prompt with id " << id;
420         pending_prompts_.emplace_back(id, public_key, arg);
421         DispatchPendingPrompt();
422         return id;
423     }
424 
NotifyAuthenticatedAdbdAuthContext425     uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
426         uint64_t id = NextId();
427         std::lock_guard<std::mutex> lock(mutex_);
428         keys_.emplace(id, public_key);
429         output_queue_.emplace_back(
430                 AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
431         return id;
432     }
433 
NotifyDisconnectedAdbdAuthContext434     void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
435         std::lock_guard<std::mutex> lock(mutex_);
436         auto it = keys_.find(id);
437         if (it == keys_.end()) {
438             LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
439             return;
440         }
441         output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
442         keys_.erase(it);
443     }
444 
NotifyTlsDeviceConnectedAdbdAuthContext445     uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
446                                       std::string_view public_key) EXCLUDES(mutex_) {
447         uint64_t id = NextId();
448         std::lock_guard<std::mutex> lock(mutex_);
449         keys_.emplace(id, public_key);
450         output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
451                 .transport_type = static_cast<uint8_t>(type),
452                 .public_key = std::string(public_key)});
453         Interrupt();
454         return id;
455     }
456 
NotifyTlsDeviceDisconnectedAdbdAuthContext457     void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
458         std::lock_guard<std::mutex> lock(mutex_);
459         auto it = keys_.find(id);
460         if (it == keys_.end()) {
461             LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
462                           "device, skipping";
463             return;
464         }
465         output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
466                 .transport_type = static_cast<uint8_t>(type),
467                 .public_key = std::move(it->second)});
468         keys_.erase(it);
469         Interrupt();
470     }
471 
472     // Interrupt the worker thread to do some work.
InterruptAdbdAuthContext473     void Interrupt() {
474         uint64_t value = 1;
475         ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
476         if (rc == -1) {
477             PLOG(FATAL) << "adbd_auth: write to eventfd failed";
478         } else if (rc != sizeof(value)) {
479             LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
480         }
481     }
482 
InitFrameworkHandlersAdbdAuthContext483     void InitFrameworkHandlers() {
484         // Framework wants to disconnect from a secured wifi device
485         framework_handlers_.emplace_back(
486                 FrameworkPktHandler{
487                     .code = "DD",
488                     .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
489         // Framework allows USB debugging for the device
490         framework_handlers_.emplace_back(
491                 FrameworkPktHandler{
492                     .code = "OK",
493                     .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
494         // Framework denies USB debugging for the device
495         framework_handlers_.emplace_back(
496                 FrameworkPktHandler{
497                     .code = "NO",
498                     .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
499     }
500 
501     unique_fd epoll_fd_;
502     unique_fd event_fd_;
503     unique_fd sock_fd_;
504     unique_fd framework_fd_;
505 
506     std::atomic<uint64_t> next_id_;
507     AdbdAuthCallbacksV1 callbacks_;
508 
509     std::mutex mutex_;
510     std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
511 
512     // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
513     // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
514     std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
515 
516     std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
517     std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
518 
519     // This is a list of commands that the framework could send to us.
520     using FrameworkHandlerCb = std::function<void(std::string_view)>;
521     struct FrameworkPktHandler {
522         const char* code;
523         FrameworkHandlerCb cb;
524     };
525     std::vector<FrameworkPktHandler> framework_handlers_;
526 };
527 
adbd_auth_new(AdbdAuthCallbacks * callbacks)528 AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
529     if (callbacks->version == 1) {
530         return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
531     } else {
532         LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
533                    << callbacks->version;
534         return nullptr;
535     }
536 }
537 
adbd_auth_delete(AdbdAuthContext * ctx)538 void adbd_auth_delete(AdbdAuthContext* ctx) {
539     delete ctx;
540 }
541 
adbd_auth_run(AdbdAuthContext * ctx)542 void adbd_auth_run(AdbdAuthContext* ctx) {
543     return ctx->Run();
544 }
545 
adbd_auth_get_public_keys(AdbdAuthContext * ctx,bool (* callback)(void * opaque,const char * public_key,size_t len),void * opaque)546 void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
547                                bool (*callback)(void* opaque, const char* public_key, size_t len),
548                                void* opaque) {
549     ctx->IteratePublicKeys(callback, opaque);
550 }
551 
adbd_auth_notify_auth(AdbdAuthContext * ctx,const char * public_key,size_t len)552 uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
553     return ctx->NotifyAuthenticated(std::string_view(public_key, len));
554 }
555 
adbd_auth_notify_disconnect(AdbdAuthContext * ctx,uint64_t id)556 void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
557     return ctx->NotifyDisconnected(id);
558 }
559 
adbd_auth_prompt_user(AdbdAuthContext * ctx,const char * public_key,size_t len,void * opaque)560 void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
561                            void* opaque) {
562     adbd_auth_prompt_user_with_id(ctx, public_key, len, opaque);
563 }
564 
adbd_auth_prompt_user_with_id(AdbdAuthContext * ctx,const char * public_key,size_t len,void * opaque)565 uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx, const char* public_key, size_t len,
566                                        void* opaque) {
567     return ctx->PromptUser(std::string_view(public_key, len), opaque);
568 }
569 
adbd_auth_tls_device_connected(AdbdAuthContext * ctx,AdbTransportType type,const char * public_key,size_t len)570 uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
571                                         AdbTransportType type,
572                                         const char* public_key,
573                                         size_t len) {
574     return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
575 }
576 
adbd_auth_tls_device_disconnected(AdbdAuthContext * ctx,AdbTransportType type,uint64_t id)577 void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
578                                        AdbTransportType type,
579                                        uint64_t id) {
580     ctx->NotifyTlsDeviceDisconnected(type, id);
581 }
582 
adbd_auth_get_max_version()583 uint32_t adbd_auth_get_max_version() {
584     return kAuthVersion;
585 }
586 
adbd_auth_supports_feature(AdbdAuthFeature f)587 bool adbd_auth_supports_feature(AdbdAuthFeature f) {
588     UNUSED(f);
589     return false;
590 }
591