Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/device/device/generic/goldfish/hals/gnss/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 5 kB image not shown  

Quelle  GnssHwConn.cpp

  Sprache: C
 

/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <log/log.h>
#include <fcntl.h>
#include <qemud.h>
#include <qemu_pipe_bp.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <debug.h>
#include "GnssHwConn.h"
#include "GnssHwListener.h"

namespace aidl {
namespace android {
namespace hardware {
namespace gnss {
namespace implementation {
namespace {
constexpr char kCMD_QUIT = 'q';

int epollCtlAdd(int epollFd, int fd) {
    int ret;

    /* make the fd non-blocking */
    ret = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
    if (ret < 0) {
        return FAILURE(ret);
    }
    ret = TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, ret | O_NONBLOCK));
    if (ret < 0) {
        return FAILURE(ret);
    }

    struct epoll_event ev;
    ev.events  = EPOLLIN;
    ev.data.fd = fd;

    ret = TEMP_FAILURE_RETRY(epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ev));
    if (ret < 0) {
        return FAILURE(ret);
    }

    return 0;
}

int workerThreadRcvCommand(const int fd) {
    char buf;
    if (TEMP_FAILURE_RETRY(read(fd, &buf, 1)) == 1) {
        return buf;
    } else {
        return FAILURE(-1);
    }
}

void workerThread(const int devFd, const int threadsFd, GnssHwListener& listener) {
    const unique_fd epollFd(epoll_create1(0));
    LOG_ALWAYS_FATAL_IF(!epollFd.ok(), "%s:%d: epoll_create1 failed",
                        __func__, __LINE__);

    epollCtlAdd(epollFd.get(), devFd);
    epollCtlAdd(epollFd.get(), threadsFd);

    while (true) {
        struct epoll_event events[2];
        const int kTimeoutMs = 60000;
        const int n = TEMP_FAILURE_RETRY(epoll_wait(epollFd.get(),
                                                    events, 2,
                                                    kTimeoutMs));
        if (n < 0) {
            ALOGE("%s:%d: epoll_wait failed with '%s'",
                  __func__, __LINE__, strerror(errno));
            continue;
        }

        for (int i = 0; i < n; ++i) {
            const struct epoll_event* ev = &events[i];
            const int fd = ev->data.fd;
            const int ev_events = ev->events;

            if (fd == devFd) {
                if (ev_events & (EPOLLERR | EPOLLHUP)) {
                    LOG_ALWAYS_FATAL("%s:%d: epoll_wait: devFd has an error, "
                                     "ev_events=%x", __func__, __LINE__, ev_events);
                } else if (ev_events & EPOLLIN) {
                    char buf[64];
                    while (true) {
                        int n = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
                        if (n > 0) {
                            listener.consume(buf, n);
                        } else {
                            break;
                        }
                    }
                }
            } else if (fd == threadsFd) {
                if (ev_events & (EPOLLERR | EPOLLHUP)) {
                    LOG_ALWAYS_FATAL("%s:%d: epoll_wait: threadsFd has an error, "
                                     "ev_events=%x", __func__, __LINE__, ev_events);
                } else if (ev_events & EPOLLIN) {
                    const int cmd = workerThreadRcvCommand(fd);
                    switch (cmd) {
                        case kCMD_QUIT:
                            return;

                        default:
                            LOG_ALWAYS_FATAL("%s:%d: workerThreadRcvCommand returned "
                                             "unexpected command, cmd=%d",
                                             __func__, __LINE__, cmd);
                            break;
                    }
                }
            } else {
                ALOGE("%s:%d: epoll_wait() returned unexpected fd",
                      __func__, __LINE__);
            }
        }
    }
}

}  // namespace

GnssHwConn::GnssHwConn(IDataSink& sink) {
    mDevFd.reset(qemu_pipe_open_ns("qemud""gps", O_RDWR));
    if (!mDevFd.ok()) {
        ALOGE("%s:%d: qemu_pipe_open_ns failed", __func__, __LINE__);
        return;
    }

    unique_fd threadsFd;
    if (!::android::base::Socketpair(AF_LOCAL, SOCK_STREAM, 0,
                                     &mCallersFd, &threadsFd)) {
        ALOGE("%s:%d: Socketpair failed", __func__, __LINE__);
        mDevFd.reset();
        return;
    }

    std::promise<void> isReadyPromise;
    const int devFd = mDevFd.get();
    mThread = std::thread([devFd, threadsFd = std::move(threadsFd), &sink,
                           &isReadyPromise]() {
        GnssHwListener listener(sink);
        isReadyPromise.set_value();
        workerThread(devFd, threadsFd.get(), listener);
    });

    isReadyPromise.get_future().wait();
}

GnssHwConn::~GnssHwConn() {
    if (mThread.joinable()) {
        sendWorkerThreadCommand(kCMD_QUIT);
        mThread.join();
    }
}

bool GnssHwConn::ok() const {
    return mThread.joinable();
}

bool GnssHwConn::sendWorkerThreadCommand(char cmd) const {
    return (TEMP_FAILURE_RETRY(write(mCallersFd.get(), &cmd, 1)) == 1) ?
        true : FAILURE(false);
}

}  // namespace implementation
}  // namespace gnss
}  // namespace hardware
}  // namespace android
}  // namespace aidl

Messung V0.5 in Prozent
C=91 H=87 G=88

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.