• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "AndroidPipe.h"
16 #include "android_pipe_base.h"
17 
18 #include "base/Optional.h"
19 #include "base/StringFormat.h"
20 #include "base/MemStream.h"
21 #include "base/Lock.h"
22 #include "android_pipe_device.h"
23 #include "android_pipe_host.h"
24 #include "host-common/GfxstreamFatalError.h"
25 #include "DeviceContextRunner.h"
26 #include "VmLock.h"
27 
28 #include <algorithm>
29 #include <memory>
30 #include <string>
31 #include <vector>
32 #include <unordered_set>
33 
34 #include <assert.h>
35 #include <string.h>
36 
37 #define DEBUG 0
38 
39 #if DEBUG >= 1
40 #include <stdio.h>
41 #define D(...) fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")
42 #else
43 #define D(...) (void)0
44 #endif
45 
46 #if DEBUG >= 2
47 #define DD(...) fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")
48 #else
49 #define DD(...) (void)0
50 #endif
51 
52 #define E(...) fprintf(stderr, "ERROR:" __VA_ARGS__), fprintf(stderr, "\n")
53 
getPipeHwFuncs(const void * hwPipe)54 static const AndroidPipeHwFuncs* getPipeHwFuncs(const void* hwPipe) {
55     return *static_cast<const AndroidPipeHwFuncs* const *>(hwPipe);
56 }
57 
58 using namespace android::base;
59 
60 using AndroidPipe = android::AndroidPipe;
61 using BaseStream = android::base::Stream;
62 using CStream = ::Stream;
63 using OptionalString = android::base::Optional<std::string>;
64 using Service = android::AndroidPipe::Service;
65 using ServiceList = std::vector<std::unique_ptr<Service>>;
66 using VmLock = android::VmLock;
67 using android::base::MemStream;
68 using android::base::StringFormat;
69 using emugl::ABORT_REASON_OTHER;
70 using emugl::FatalError;
71 
asBaseStream(CStream * stream)72 static BaseStream* asBaseStream(CStream* stream) {
73     return reinterpret_cast<BaseStream*>(stream);
74 }
75 
76 #define CHECK_VM_STATE_LOCK() (void)0
77 
78 namespace android {
79 
80 namespace {
81 
isPipeOptional(const std::string & name)82 static bool isPipeOptional(const std::string& name) {
83     return name == "OffworldPipe";
84 }
85 
86 // Write an optional string |str| to |stream|. |str| can be null. Use
87 // readOptionalString() to read it back later.
writeOptionalString(BaseStream * stream,const char * str)88 static void writeOptionalString(BaseStream* stream, const char* str) {
89     if (str) {
90         stream->putByte(1);
91         stream->putString(str);
92     } else {
93         stream->putByte(0);
94     }
95 }
96 
97 // Read an optional string from |stream|. If the result is not constructed
98 // (i.e. equals to false), this means the original |str| parameter was null.
readOptionalString(BaseStream * stream)99 static OptionalString readOptionalString(BaseStream* stream) {
100     if (stream->getByte()) {
101         return OptionalString(stream->getString());
102     }
103     return OptionalString();
104 }
105 
106 // forward
107 Service* findServiceByName(const char* name);
108 
109 // Implementation of a special AndroidPipe class used to model the state
110 // of a pipe connection before the service name has been written to the
111 // file descriptor by the guest. The most important method is onGuestSend()
112 // which will detect when this happens.
113 class ConnectorPipe : public AndroidPipe {
114 public:
ConnectorPipe(void * hwPipe,Service * service)115     ConnectorPipe(void* hwPipe, Service* service)
116         : AndroidPipe(hwPipe, service) {
117         DD("%s: Creating new ConnectorPipe hwpipe=%p", __FUNCTION__, mHwPipe);
118     }
119 
onGuestClose(PipeCloseReason reason)120     virtual void onGuestClose(PipeCloseReason reason) override {
121         // nothing to do here
122         DD("%s: closing ConnectorPipe hwpipe=%p prematurily (reason=%d)!",
123            __func__, mHwPipe, (int)reason);
124     }
125 
onGuestPoll() const126     virtual unsigned onGuestPoll() const override {
127         // A connector always want to receive data.
128         DD("%s: polling hwpipe=%p", __FUNCTION__, mHwPipe);
129         return PIPE_POLL_OUT;
130     }
131 
onGuestRecv(AndroidPipeBuffer * buffers,int numBuffers)132     virtual int onGuestRecv(AndroidPipeBuffer* buffers,
133                             int numBuffers) override {
134         // This pipe never wants to write to the guest, so getting there
135         // is an error since PIPE_WAKE_IN is never signaled.
136         DD("%s: trying to receive data from hwpipe=%p", __FUNCTION__, mHwPipe);
137         return PIPE_ERROR_IO;
138     }
139 
140     // TECHNICAL NOTE: This function reads data from the guest until it
141     // finds a zero-terminated C-string. After that it parses it to find
142     // a registered service corresponding to one of the allowed formats
143     // (see below). In case of success, this creates a new AndroidPipe
144     // instance and calls AndroidPipeHwFuncs::resetPipe() to associate it with
145     // the current hardware-side |mHwPipe|, then *deletes* the current
146     // instance! In case of error (e.g. invalid service name, or error during
147     // initialization), PIPE_ERROR_INVAL will be returned, otherwise, the
148     // number of bytes accepted from the guest is returned.
onGuestSend(const AndroidPipeBuffer * buffers,int numBuffers,void ** newPipePtr)149     virtual int onGuestSend(const AndroidPipeBuffer* buffers,
150                             int numBuffers,
151                             void** newPipePtr) override {
152         int result = 0;
153         size_t avail = kBufferSize - mPos;
154         bool foundZero = false;
155         for (; !foundZero && avail > 0 && numBuffers > 0;
156              buffers++, numBuffers--) {
157             const uint8_t* data = buffers[0].data;
158             size_t count = std::min(avail, buffers[0].size);
159             // Read up to |count| bytes, stopping after the first zero.
160             size_t n = 0;
161             while (n < count) {
162                 uint8_t byte = data[n++];
163                 mBuffer[mPos++] = (char) byte;
164                 if (!byte) {
165                     foundZero = true;
166                     break;
167                 }
168             }
169             result += static_cast<int>(n);
170             avail -= n;
171         }
172         DD("%s: receiving %d connection bytes from hwpipe=%p", __FUNCTION__,
173            result, mHwPipe);
174 
175         if (!foundZero) {
176             if (avail == 0) {
177                 DD("%s: service name buffer full, force-closing connection",
178                    __FUNCTION__);
179                 return PIPE_ERROR_IO;
180             }
181             // Still waiting for terminating zero.
182             DD("%s: still waiting for terminating zero!", __FUNCTION__);
183             return result;
184         }
185 
186         // Acceptable formats for the connection string are:
187         //
188         //    pipe:<name>
189         //    pipe:<name>:<arguments>
190         //
191         char* pipeName;
192         char* pipeArgs;
193 
194         D("%s: connector: '%s'", __FUNCTION__, mBuffer);
195         if (memcmp(mBuffer, "pipe:", 5) != 0) {
196             // Nope, we don't handle these for now.
197             D("%s: Unknown pipe connection: '%s'", __FUNCTION__, mBuffer);
198             return PIPE_ERROR_INVAL;
199         }
200 
201         pipeName = mBuffer + 5;
202         pipeArgs = strchr(pipeName, ':');
203 
204         Service* svc = nullptr;
205 
206         // As a special case, if the service name is as:
207         //    qemud:<name>
208         //    qemud:<name>:args
209         //
210         // First look for a registered pipe service named "qemud:<name>"
211         // and if not found, fallback to "qemud" only.
212         //
213         // This is useful to support qemud services that are now served
214         // by a dedicated (and faster) pipe service, e.g. 'qemud:adb'
215         // as currently implemented by QEMU2 (and soon by QEMU1).
216         static const char kQemudPrefix[] = "qemud:";
217         const size_t kQemudPrefixSize = sizeof(kQemudPrefix) - 1U;
218 
219         if (!::strncmp(pipeName, kQemudPrefix, kQemudPrefixSize)) {
220             assert(pipeArgs == pipeName + kQemudPrefixSize - 1);
221             char* pipeArgs2 = strchr(pipeArgs + 1, ':');
222             if (pipeArgs2) {
223                 *pipeArgs2 = '\0';
224             }
225             svc = findServiceByName(pipeName);
226             if (svc) {
227                 pipeArgs = pipeArgs2;
228             } else if (pipeArgs2) {
229                 // Restore colon.
230                 *pipeArgs2 = ':';
231             }
232         }
233         if (pipeArgs) {
234             *pipeArgs++ = '\0';
235             if (!pipeArgs) {
236                 pipeArgs = NULL;
237             }
238         }
239 
240         if (!svc) {
241             svc = findServiceByName(pipeName);
242         }
243 
244         if (!svc) {
245             D("%s: Unknown server with name %s!", __FUNCTION__, pipeName);
246             return PIPE_ERROR_INVAL;
247         }
248 
249         AndroidPipe* newPipe = svc->create(mHwPipe, pipeArgs, mFlags);
250         if (!newPipe) {
251             D("%s: Initialization failed for %s pipe!", __FUNCTION__, pipeName);
252             return PIPE_ERROR_INVAL;
253         }
254 
255         // Swap your host-side pipe instance with this one weird trick!
256         D("%s: starting new pipe %p (swapping %p) for service %s",
257           __FUNCTION__,
258           newPipe,
259           mHwPipe,
260           pipeName);
261 
262         newPipe->setFlags(mFlags);
263         *newPipePtr = newPipe;
264         delete this;
265 
266         return result;
267     }
268 
onGuestWantWakeOn(int wakeFlags)269     virtual void onGuestWantWakeOn(int wakeFlags) override {
270         // nothing to do here
271         DD("%s: signaling wakeFlags=%d for hwpipe=%p", __FUNCTION__, wakeFlags,
272            mHwPipe);
273     }
274 
onSave(BaseStream * stream)275     virtual void onSave(BaseStream* stream) override {
276         DD("%s: saving connector state for hwpipe=%p", __FUNCTION__, mHwPipe);
277         stream->putBe32(mPos);
278         stream->write(mBuffer, mPos);
279     }
280 
onLoad(BaseStream * stream)281     bool onLoad(BaseStream* stream) {
282         DD("%s: loading connector state for hwpipe=%p", __FUNCTION__, mHwPipe);
283         int32_t len = stream->getBe32();
284         if (len < 0 || len > kBufferSize) {
285             D("%s: invalid length %d (expected 0 <= len <= %d)", __FUNCTION__,
286               static_cast<int>(len), kBufferSize);
287             return false;
288         }
289         mPos = (int)len;
290         int ret = (int)stream->read(mBuffer, mPos);
291         DD("%s: read %d bytes (%d expected)", __FUNCTION__, ret, mPos);
292         return (ret == mPos);
293     }
294 
295 private:
296     static constexpr int kBufferSize = 128;
297     char mBuffer[kBufferSize];
298     int mPos = 0;
299 };
300 
301 // Associated AndroidPipe::Service class for ConnectorPipe instances.
302 class ConnectorService : public Service {
303 public:
ConnectorService()304     ConnectorService() : Service("<connector>") {}
305 
create(void * hwPipe,const char * args,enum AndroidPipeFlags flags)306     virtual AndroidPipe* create(void* hwPipe, const char* args,
307                                 enum AndroidPipeFlags flags) override {
308         return new ConnectorPipe(hwPipe, this);
309     }
310 
canLoad() const311     virtual bool canLoad() const override { return true; }
312 
load(void * hwPipe,const char * args,BaseStream * stream)313     virtual AndroidPipe* load(void* hwPipe,
314                               const char* args,
315                               BaseStream* stream) override {
316         ConnectorPipe* pipe = new ConnectorPipe(hwPipe, this);
317         if (!pipe->onLoad(stream)) {
318             delete pipe;
319             return nullptr;
320         }
321         return pipe;
322     }
323 };
324 
325 // A helper class used to send signalWake() and closeFromHost() commands to
326 // the device thread, depending on the threading mode setup by the emulation
327 // engine.
328 struct PipeWakeCommand {
329     void* hwPipe;
330     int wakeFlags;
331 };
332 
333 class PipeWaker final : public DeviceContextRunner<PipeWakeCommand> {
334 public:
signalWake(void * hwPipe,int wakeFlags)335     void signalWake(void* hwPipe, int wakeFlags) {
336         queueDeviceOperation({ hwPipe, wakeFlags });
337     }
closeFromHost(void * hwPipe)338     void closeFromHost(void* hwPipe) {
339         signalWake(hwPipe, PIPE_WAKE_CLOSED);
340     }
abortPending(void * hwPipe)341     void abortPending(void* hwPipe) {
342         removeAllPendingOperations([hwPipe](const PipeWakeCommand& cmd) {
343             return cmd.hwPipe == hwPipe;
344         });
345     }
abortAllPending()346     void abortAllPending() {
347         removeAllPendingOperations([](const PipeWakeCommand& cmd) {
348             return true;
349         });
350     }
351 
getPendingFlags(void * hwPipe) const352     int getPendingFlags(void* hwPipe) const {
353         int flags = 0;
354         forEachPendingOperation([hwPipe, &flags](const PipeWakeCommand& cmd) {
355             if (cmd.hwPipe == hwPipe) {
356                 flags |= cmd.wakeFlags;
357             }
358         });
359         return flags;
360     }
361 
362 private:
performDeviceOperation(const PipeWakeCommand & wake_cmd)363     virtual void performDeviceOperation(const PipeWakeCommand& wake_cmd) {
364         void* hwPipe = wake_cmd.hwPipe;
365         int flags = wake_cmd.wakeFlags;
366 
367         // Not used when in virtio mode.
368         if (flags & PIPE_WAKE_CLOSED) {
369             getPipeHwFuncs(hwPipe)->closeFromHost(hwPipe);
370         } else {
371             getPipeHwFuncs(hwPipe)->signalWake(hwPipe, flags);
372         }
373     }
374 };
375 
376 struct Globals {
377     ServiceList services;
378     ConnectorService connectorService;
379     PipeWaker pipeWaker;
380 
381     // Searches for a service position in the |services| list and returns the
382     // index. |startPosHint| is a _hint_ and suggests where to start from.
383     // Returns the index of the service or -1 if there's no |name| service.
findServicePositionByNameandroid::__anon0538e7f20111::Globals384     int findServicePositionByName(const char* name,
385                                   const int startPosHint = 0) const {
386         const auto searchByNameFunc =
387                 [name](const std::unique_ptr<Service>& service) {
388                     return service->name() == name;
389                 };
390 
391         // First, try to search starting from the hint position.
392         auto end = services.end();
393         auto it = std::find_if(services.begin() + startPosHint, end,
394                                searchByNameFunc);
395 
396         // If there was a hint that didn't help, continue searching from the
397         // beginning of the contatiner to check the rest of it.
398         if (it == end && startPosHint > 0) {
399             end = services.begin() + startPosHint;
400             it = std::find_if(services.begin(), end, searchByNameFunc);
401         }
402 
403         return it == end ? -1 : it - services.begin();
404     }
405 
loadServiceByNameandroid::__anon0538e7f20111::Globals406     Service* loadServiceByName(BaseStream* stream) {
407         OptionalString serviceName = readOptionalString(stream);
408         if (!serviceName) {
409             DD("%s: no name (assuming connector state)", __FUNCTION__);
410             return &connectorService;
411         }
412         DD("%s: found [%s]", __FUNCTION__, serviceName->c_str());
413         return findServiceByName(serviceName->c_str());
414     }
415 };
416 
sGlobals()417 static Globals* sGlobals() { static Globals* g = new Globals; return g; }
418 
findServiceByName(const char * name)419 Service* findServiceByName(const char* name) {
420     const int pos = sGlobals()->findServicePositionByName(name);
421     return pos < 0 ? nullptr : sGlobals()->services[pos].get();
422 }
423 
loadPipeFromStreamCommon(BaseStream * stream,void * hwPipe,Service * service,char * pForceClose)424 AndroidPipe* loadPipeFromStreamCommon(BaseStream* stream,
425                                       void* hwPipe,
426                                       Service* service,
427                                       char* pForceClose) {
428     *pForceClose = 0;
429 
430     OptionalString args = readOptionalString(stream);
431     AndroidPipe* pipe = nullptr;
432     if (service->canLoad()) {
433         DD("%s: loading state for [%s] hwpipe=%p", __FUNCTION__,
434            service->name().c_str(), hwPipe);
435         pipe = service->load(hwPipe, args ? args->c_str() : nullptr, stream);
436         if (!pipe) {
437             *pForceClose = 1;
438         }
439     } else {
440         DD("%s: force-closing hwpipe=%p", __FUNCTION__, hwPipe);
441         *pForceClose = 1;
442     }
443 
444     const int pendingFlags = stream->getBe32();
445     if (pendingFlags && pipe && !*pForceClose) {
446         if (!hwPipe) {
447             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
448                 << "fatal: AndroidPipe [" << pipe->name() << "] hwPipe is NULL(flags = 0x"
449                 << std::hex << unsigned(pendingFlags) << " )";
450         }
451         sGlobals()->pipeWaker.signalWake(hwPipe, pendingFlags);
452         DD("%s: singalled wake flags %d for pipe hwpipe=%p", __func__,
453            pendingFlags, hwPipe);
454     }
455 
456     return pipe;
457 }
458 
459 }  // namespace
460 
461 // static
initThreading(VmLock * vmLock)462 void AndroidPipe::initThreading(VmLock* vmLock) {
463     // TODO: Make this work in qemu with the actual goldfish pipe device.
464     // In virtio land, this won't be needed, so include trivial timer interface.
465     sGlobals()->pipeWaker.init(vmLock, {
466         // installFunc
467         [](DeviceContextRunner<PipeWakeCommand>* dcr, std::function<void()> installedFunc) {
468             (void)dcr;
469             (void)installedFunc;
470         },
471         // uninstallFunc
472         [](DeviceContextRunner<PipeWakeCommand>* dcr) {
473             (void)dcr;
474         },
475         // startWithTimeoutFunc
476         [](DeviceContextRunner<PipeWakeCommand>* dcr, uint64_t timeout) {
477             (void)dcr;
478             (void)timeout;
479         }
480     });
481 }
482 
~AndroidPipe()483 AndroidPipe::~AndroidPipe() {
484     DD("%s: for hwpipe=%p (host %p '%s')", __FUNCTION__, mHwPipe, this,
485        mService->name().c_str());
486 }
487 
488 // static
add(std::unique_ptr<Service> service)489 void AndroidPipe::Service::add(std::unique_ptr<Service> service) {
490     DD("Adding new pipe service '%s' this=%p", service->name().c_str(),
491        service.get());
492     sGlobals()->services.push_back(std::move(service));
493 }
494 
495 // static
resetAll()496 void AndroidPipe::Service::resetAll() {
497     DD("Resetting all pipe services");
498     sGlobals()->services.clear();
499 }
500 
signalWake(int wakeFlags)501 void AndroidPipe::signalWake(int wakeFlags) {
502     // i.e., pipe not using normal pipe device
503     if (mFlags) return;
504     if (!mHwPipe) {
505         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
506             << "AndroidPipe [" << name() << "]: hwPipe is NULL (flags = 0x" << std::hex
507             << unsigned(wakeFlags) << ")";
508     }
509     sGlobals()->pipeWaker.signalWake(mHwPipe, wakeFlags);
510 }
511 
closeFromHost()512 void AndroidPipe::closeFromHost() {
513     // i.e., pipe not using normal pipe device
514     if (mFlags) return;
515     if (!mHwPipe) {
516         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
517             << "AndroidPipe [" << name() << "]: hwPipe is NULL";
518     }
519     sGlobals()->pipeWaker.closeFromHost(mHwPipe);
520 }
521 
abortPendingOperation()522 void AndroidPipe::abortPendingOperation() {
523     // i.e., pipe not using normal pipe device
524     if (mFlags) return;
525 
526     if (!mHwPipe) {
527         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
528             << "AndroidPipe [" << name() << "]: hwPipe is NULL";
529     }
530     sGlobals()->pipeWaker.abortPending(mHwPipe);
531 }
532 
saveToStream(BaseStream * stream)533 void AndroidPipe::saveToStream(BaseStream* stream) {
534     // First, write service name.
535     if (mService == &sGlobals()->connectorService) {
536         // A connector pipe
537         stream->putByte(0);
538     } else {
539         // A regular service pipe.
540         stream->putByte(1);
541         stream->putString(mService->name());
542     }
543 
544     MemStream pipeStream;
545     writeOptionalString(&pipeStream, mArgs.c_str());
546 
547     // Save pipe-specific state now.
548     if (mService->canLoad()) {
549         mService->savePipe(this, &pipeStream);
550     }
551 
552     // Save the pending wake or close operations as well.
553     const int pendingFlags = sGlobals()->pipeWaker.getPendingFlags(mHwPipe);
554     pipeStream.putBe32(pendingFlags);
555 
556     pipeStream.save(stream);
557 }
558 
559 // static
loadFromStream(BaseStream * stream,void * hwPipe,char * pForceClose)560 AndroidPipe* AndroidPipe::loadFromStream(BaseStream* stream,
561                                          void* hwPipe,
562                                          char* pForceClose) {
563     Service* service = sGlobals()->loadServiceByName(stream);
564     // Always load the pipeStream, it allows us to safely skip loading streams.
565     MemStream pipeStream;
566     pipeStream.load(stream);
567 
568     if (!service) {
569         return nullptr;
570     }
571     return loadPipeFromStreamCommon(&pipeStream, hwPipe, service, pForceClose);
572 }
573 
574 // static
loadFromStreamLegacy(BaseStream * stream,void * hwPipe,uint64_t * pChannel,unsigned char * pWakes,unsigned char * pClosed,char * pForceClose)575 AndroidPipe* AndroidPipe::loadFromStreamLegacy(BaseStream* stream,
576                                                void* hwPipe,
577                                                uint64_t* pChannel,
578                                                unsigned char* pWakes,
579                                                unsigned char* pClosed,
580                                                char* pForceClose) {
581     Service* service = sGlobals()->loadServiceByName(stream);
582     // Always load the pipeStream, it allows us to safely skip loading streams.
583     MemStream pipeStream;
584     pipeStream.load(stream);
585 
586     if (!service) {
587         return nullptr;
588     }
589     *pChannel = pipeStream.getBe64();
590     *pWakes = pipeStream.getByte();
591     *pClosed = pipeStream.getByte();
592 
593     return loadPipeFromStreamCommon(&pipeStream, hwPipe, service, pForceClose);
594 }
595 
596 }  // namespace android
597 
598 // API for the virtual device.
599 
android_pipe_reset_services()600 void android_pipe_reset_services() {
601     AndroidPipe::Service::resetAll();
602 }
603 
android_pipe_guest_open(void * hwpipe)604 void* android_pipe_guest_open(void* hwpipe) {
605     CHECK_VM_STATE_LOCK();
606     DD("%s: Creating new connector pipe for hwpipe=%p", __FUNCTION__, hwpipe);
607     return android::sGlobals()->connectorService.create(hwpipe, nullptr, (AndroidPipeFlags)0);
608 }
609 
android_pipe_guest_open_with_flags(void * hwpipe,uint32_t flags)610 void* android_pipe_guest_open_with_flags(void* hwpipe, uint32_t flags) {
611     CHECK_VM_STATE_LOCK();
612     DD("%s: Creating new connector pipe for hwpipe=%p", __FUNCTION__, hwpipe);
613     auto pipe =
614         android::sGlobals()->connectorService.create(hwpipe, nullptr, (AndroidPipeFlags)flags);
615     pipe->setFlags((AndroidPipeFlags)flags);
616     return pipe;
617 }
618 
android_pipe_guest_close(void * internalPipe,PipeCloseReason reason)619 void android_pipe_guest_close(void* internalPipe, PipeCloseReason reason) {
620     CHECK_VM_STATE_LOCK();
621     auto pipe = static_cast<android::AndroidPipe*>(internalPipe);
622     if (pipe) {
623         D("%s: host=%p [%s] reason=%d", __FUNCTION__, pipe, pipe->name(),
624             (int)reason);
625         pipe->abortPendingOperation();
626         pipe->onGuestClose(reason);
627     }
628 }
629 
630 template <class Func>
forEachServiceToStream(CStream * stream,Func && func)631 static void forEachServiceToStream(CStream* stream, Func&& func) {
632     BaseStream* const bs = asBaseStream(stream);
633     bs->putBe16(android::sGlobals()->services.size());
634     for (const auto& service : android::sGlobals()->services) {
635         bs->putString(service->name());
636 
637         // Write to the pipeStream first so that we know the length and can
638         // enable skipping loading specific pipes on load, see isPipeOptional.
639         MemStream pipeStream;
640         func(service.get(), &pipeStream);
641         pipeStream.save(bs);
642     }
643 }
644 
645 template <class Func>
forEachServiceFromStream(CStream * stream,Func && func)646 static void forEachServiceFromStream(CStream* stream, Func&& func) {
647     const auto& services = android::sGlobals()->services;
648     BaseStream* const bs = asBaseStream(stream);
649     const int count = bs->getBe16();
650     int servicePos = -1;
651     std::unordered_set<Service*> missingServices;
652     for (const auto& service : services) {
653         missingServices.insert(service.get());
654     }
655     for (int i = 0; i < count; ++i) {
656         const auto name = bs->getString();
657         servicePos = android::sGlobals()->findServicePositionByName(
658                                  name.c_str(), servicePos + 1);
659 
660         // Always load the pipeStream, so that if the pipe is missing it does
661         // not corrupt the next pipe.
662         MemStream pipeStream;
663         pipeStream.load(bs);
664 
665         if (servicePos >= 0) {
666             const auto& service = services[servicePos];
667             func(service.get(), &pipeStream);
668             missingServices.erase(service.get());
669         } else if (android::isPipeOptional(name)) {
670             D("%s: Skipping optional pipe %s\n", __FUNCTION__, name.c_str());
671         } else {
672             assert(false && "Service for snapshot pipe does not exist");
673             E("%s: Could not load pipe %s, service does not exist\n",
674               __FUNCTION__, name.c_str());
675         }
676     }
677 
678     // Now call the same function for all services that weren't in the snapshot.
679     // Pass |nullptr| instead of the stream pointer to make sure they know
680     // that while we're loading from a snapshot these services aren't part
681     // of it.
682     for (const auto service : missingServices) {
683         func(service, nullptr);
684     }
685 }
686 
android_pipe_guest_pre_load(CStream * stream)687 void android_pipe_guest_pre_load(CStream* stream) {
688     CHECK_VM_STATE_LOCK();
689     // We may not call qemu_set_irq() until the snapshot is loaded.
690     android::sGlobals()->pipeWaker.abortAllPending();
691     android::sGlobals()->pipeWaker.setContextRunMode(
692                 android::ContextRunMode::DeferAlways);
693     forEachServiceFromStream(stream, [](Service* service, BaseStream* bs) {
694         if (service->canLoad()) {
695             service->preLoad(bs);
696         }
697     });
698 }
699 
android_pipe_guest_post_load(CStream * stream)700 void android_pipe_guest_post_load(CStream* stream) {
701     CHECK_VM_STATE_LOCK();
702     forEachServiceFromStream(stream, [](Service* service, BaseStream* bs) {
703         if (service->canLoad()) {
704             service->postLoad(bs);
705         }
706     });
707     // Restore the regular handling of pipe interrupt requests.
708     android::sGlobals()->pipeWaker.setContextRunMode(
709                 android::ContextRunMode::DeferIfNotLocked);
710 }
711 
android_pipe_guest_pre_save(CStream * stream)712 void android_pipe_guest_pre_save(CStream* stream) {
713     CHECK_VM_STATE_LOCK();
714     forEachServiceToStream(stream, [](Service* service, BaseStream* bs) {
715         if (service->canLoad()) {
716             service->preSave(bs);
717         }
718     });
719 }
720 
android_pipe_guest_post_save(CStream * stream)721 void android_pipe_guest_post_save(CStream* stream) {
722     CHECK_VM_STATE_LOCK();
723     forEachServiceToStream(stream, [](Service* service, BaseStream* bs) {
724         if (service->canLoad()) {
725             service->postSave(bs);
726         }
727     });
728 }
729 
android_pipe_guest_save(void * internalPipe,CStream * stream)730 void android_pipe_guest_save(void* internalPipe, CStream* stream) {
731     CHECK_VM_STATE_LOCK();
732     auto pipe = static_cast<android::AndroidPipe*>(internalPipe);
733     DD("%s: host=%p [%s]", __FUNCTION__, pipe, pipe->name());
734     pipe->saveToStream(asBaseStream(stream));
735 }
736 
android_pipe_guest_load(CStream * stream,void * hwPipe,char * pForceClose)737 void* android_pipe_guest_load(CStream* stream,
738                               void* hwPipe,
739                               char* pForceClose) {
740     CHECK_VM_STATE_LOCK();
741     DD("%s: hwpipe=%p", __FUNCTION__, hwPipe);
742     return AndroidPipe::loadFromStream(asBaseStream(stream), hwPipe,
743                                        pForceClose);
744 }
745 
android_pipe_guest_load_legacy(CStream * stream,void * hwPipe,uint64_t * pChannel,unsigned char * pWakes,unsigned char * pClosed,char * pForceClose)746 void* android_pipe_guest_load_legacy(CStream* stream,
747                                      void* hwPipe,
748                                      uint64_t* pChannel,
749                                      unsigned char* pWakes,
750                                      unsigned char* pClosed,
751                                      char* pForceClose) {
752     CHECK_VM_STATE_LOCK();
753     DD("%s: hwpipe=%p", __FUNCTION__, hwPipe);
754     return android::AndroidPipe::loadFromStreamLegacy(asBaseStream(stream),
755                                                       hwPipe, pChannel, pWakes,
756                                                       pClosed, pForceClose);
757 }
758 
android_pipe_guest_poll(void * internalPipe)759 unsigned android_pipe_guest_poll(void* internalPipe) {
760     CHECK_VM_STATE_LOCK();
761     auto pipe = static_cast<AndroidPipe*>(internalPipe);
762     DD("%s: host=%p [%s]", __FUNCTION__, pipe, pipe->name());
763     return pipe->onGuestPoll();
764 }
765 
android_pipe_guest_recv(void * internalPipe,AndroidPipeBuffer * buffers,int numBuffers)766 int android_pipe_guest_recv(void* internalPipe,
767                             AndroidPipeBuffer* buffers,
768                             int numBuffers) {
769     CHECK_VM_STATE_LOCK();
770     auto pipe = static_cast<AndroidPipe*>(internalPipe);
771     // Note that pipe may be deleted during this call, so it's not safe to
772     // access pipe after this point.
773     return pipe->onGuestRecv(buffers, numBuffers);
774 }
775 
android_pipe_guest_send(void ** internalPipe,const AndroidPipeBuffer * buffers,int numBuffers)776 int android_pipe_guest_send(void** internalPipe,
777                             const AndroidPipeBuffer* buffers,
778                             int numBuffers) {
779     CHECK_VM_STATE_LOCK();
780     auto pipe = static_cast<AndroidPipe*>(*internalPipe);
781     // Note that pipe may be deleted during this call, so it's not safe to
782     // access pipe after this point.
783     return pipe->onGuestSend(buffers, numBuffers, internalPipe);
784 }
785 
android_pipe_guest_wake_on(void * internalPipe,unsigned wakes)786 void android_pipe_guest_wake_on(void* internalPipe, unsigned wakes) {
787     CHECK_VM_STATE_LOCK();
788     auto pipe = static_cast<AndroidPipe*>(internalPipe);
789     pipe->onGuestWantWakeOn(wakes);
790 }
791 
792 // API implemented by the virtual device.
android_pipe_host_close(void * hwpipe)793 void android_pipe_host_close(void* hwpipe) {
794     auto pipe = static_cast<android::AndroidPipe*>(hwpipe);
795     D("%s: host=%p [%s]", __FUNCTION__, pipe, pipe->name());
796     android::sGlobals()->pipeWaker.closeFromHost(pipe);
797 }
798 
android_pipe_host_signal_wake(void * hwpipe,unsigned flags)799 void android_pipe_host_signal_wake(void* hwpipe, unsigned flags) {
800     android::sGlobals()->pipeWaker.signalWake(hwpipe, flags);
801 }
802 
803 // Not used when in virtio mode.
android_pipe_get_id(void * hwpipe)804 int android_pipe_get_id(void* hwpipe) {
805     return getPipeHwFuncs(hwpipe)->getPipeId(hwpipe);
806 }
807 
808 static std::vector<std::pair<void*(*)(int), const char*>> lookup_by_id_callbacks;
809 
android_pipe_append_lookup_by_id_callback(void * (* cb)(int),const char * tag)810 void android_pipe_append_lookup_by_id_callback(void*(*cb)(int), const char* tag) {
811     lookup_by_id_callbacks.push_back({cb, tag});
812 }
813 
android_pipe_lookup_by_id(const int id)814 void* android_pipe_lookup_by_id(const int id) {
815     void* hwPipeFound = nullptr;
816     const char* tagFound = "(null)";
817 
818     for (const auto &cb : lookup_by_id_callbacks) {
819         void* hwPipe = (*cb.first)(id);
820         if (hwPipe) {
821             if (hwPipeFound) {
822                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
823                     << "Pipe id (" << id << ") is not unique, at least two pipes are found: `"
824                     << tagFound << "` and `" << cb.second << "`";
825             } else {
826                 hwPipeFound = hwPipe;
827                 tagFound = cb.second;
828             }
829         }
830     }
831 
832     return hwPipeFound;
833 }
834