16c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen/*
26c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Copyright (C) 2011 The Android Open Source Project
36c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
46c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Licensed under the Apache License, Version 2.0 (the "License");
56c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * you may not use this file except in compliance with the License.
66c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * You may obtain a copy of the License at
76c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
86c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *      http://www.apache.org/licenses/LICENSE-2.0
96c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Unless required by applicable law or agreed to in writing, software
116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * distributed under the License is distributed on an "AS IS" BASIS,
126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * See the License for the specific language governing permissions and
146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * limitations under the License.
156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen */
166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define LOG_TAG "common_time"
186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/Log.h>
196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <fcntl.h>
216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <linux/in.h>
226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <linux/tcp.h>
236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <poll.h>
246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <sys/socket.h>
256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <sys/types.h>
266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <unistd.h>
276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/Errors.h>
286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/misc.h>
296c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
306c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <common_time/local_clock.h>
316c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include "common_clock.h"
336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include "diag_thread.h"
346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define kMaxEvents 16
366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define kListenPort 9876
376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatic bool setNonblocking(int fd) {
396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int flags = fcntl(fd, F_GETFL);
406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Failed to set socket (%d) to non-blocking mode (errno %d)",
426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen             fd, errno);
436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return false;
446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return true;
476c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
486c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
496c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatic bool setNodelay(int fd) {
506c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int tmp = 1;
516c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &tmp, sizeof(tmp)) < 0) {
526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Failed to set socket (%d) to no-delay mode (errno %d)",
536c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen             fd, errno);
546c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return false;
556c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
566c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
576c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return true;
586c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
596c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
606c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chennamespace android {
616c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
626c929510474caa14dc9d56826b2c65552861d6b3Mike J. ChenDiagThread::DiagThread(CommonClock* common_clock, LocalClock* local_clock) {
636c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    common_clock_ = common_clock;
646c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    local_clock_ = local_clock;
656c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    listen_fd_ = -1;
666c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    data_fd_ = -1;
676c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    kernel_logID_basis_known_ = false;
686c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    discipline_log_ID_ = 0;
696c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
706c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
716c929510474caa14dc9d56826b2c65552861d6b3Mike J. ChenDiagThread::~DiagThread() {
726c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
736c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
746c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatus_t DiagThread::startWorkThread() {
756c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    status_t res;
766c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    stopWorkThread();
776c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    res = run("Diag");
786c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
796c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (res != OK)
806c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Failed to start work thread (res = %d)", res);
816c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
826c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return res;
836c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
846c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
856c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid DiagThread::stopWorkThread() {
866c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    status_t res;
876c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    res = requestExitAndWait(); // block until thread exit.
886c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (res != OK)
896c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Failed to stop work thread (res = %d)", res);
906c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
916c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
926c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenbool DiagThread::openListenSocket() {
936c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    bool ret = false;
946c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int flags;
956c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cleanupListenSocket();
966c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
976c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
986c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Socket failed.");
996c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        goto bailout;
1006c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1016c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1026c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    // Set non-blocking operation
1036c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!setNonblocking(listen_fd_))
1046c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        goto bailout;
1056c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1066c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    struct sockaddr_in addr;
1076c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    memset(&addr, 0, sizeof(addr));
1086c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    addr.sin_family = AF_INET;
1096c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    addr.sin_addr.s_addr = INADDR_ANY;
1106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    addr.sin_port = htons(kListenPort);
1116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (bind(listen_fd_, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
1136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Bind failed.");
1146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        goto bailout;
1156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (listen(listen_fd_, 1) < 0) {
1186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Listen failed.");
1196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        goto bailout;
1206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    ret = true;
1236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenbailout:
1246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!ret)
1256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        cleanupListenSocket();
1266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return ret;
1286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1296c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1306c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid DiagThread::cleanupListenSocket() {
1316c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (listen_fd_ >= 0) {
1326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        int res;
1336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        struct linger l;
1356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        l.l_onoff  = 1;
1366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        l.l_linger = 0;
1376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        setsockopt(listen_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
1396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        shutdown(listen_fd_, SHUT_RDWR);
1406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        close(listen_fd_);
1416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        listen_fd_ = -1;
1426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid DiagThread::cleanupDataSocket() {
1466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (data_fd_ >= 0) {
1476c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        int res;
1486c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1496c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        struct linger l;
1506c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        l.l_onoff  = 1;
1516c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        l.l_linger = 0;
1526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1536c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        setsockopt(data_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
1546c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        shutdown(data_fd_, SHUT_RDWR);
1556c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        close(data_fd_);
1566c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        data_fd_ = -1;
1576c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1586c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1596c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1606c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid DiagThread::resetLogIDs() {
1616c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    // Drain and discard all of the events from the kernel
1626c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    struct local_time_debug_event events[kMaxEvents];
1636c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    while(local_clock_->getDebugLog(events, kMaxEvents) > 0)
1646c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ;
1656c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1666c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    {
1676c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        Mutex::Autolock lock(&discipline_log_lock_);
1686c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        discipline_log_.clear();
1696c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        discipline_log_ID_ = 0;
1706c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1716c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1726c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    kernel_logID_basis_known_ = false;
1736c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1746c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1756c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid DiagThread::pushDisciplineEvent(int64_t observed_local_time,
1766c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                     int64_t observed_common_time,
1776c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                     int64_t nominal_common_time,
1786c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                     int32_t total_correction,
17911bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk                                     int32_t rtt) {
1806c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&discipline_log_lock_);
1816c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1826c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    DisciplineEventRecord evt;
1836c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1846c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.event_id = discipline_log_ID_++;
1856c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1866c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.action_local_time = local_clock_->getLocalTime();
1876c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    common_clock_->localToCommon(evt.action_local_time,
1886c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            &evt.action_common_time);
1896c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1906c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.observed_local_time  = observed_local_time;
1916c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.observed_common_time = observed_common_time;
1926c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.nominal_common_time  = nominal_common_time;
1936c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    evt.total_correction     = total_correction;
19411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk    evt.rtt                  = rtt;
1956c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1966c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    discipline_log_.push_back(evt);
1976c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    while (discipline_log_.size() > kMaxDisciplineLogSize)
1986c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        discipline_log_.erase(discipline_log_.begin());
1996c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
2006c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2016c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenbool DiagThread::threadLoop() {
2026c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    struct pollfd poll_fds[1];
2036c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2046c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!openListenSocket()) {
2056c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Failed to open listen socket");
2066c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        goto bailout;
2076c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
2086c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2096c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    while (!exitPending()) {
2106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        memset(&poll_fds, 0, sizeof(poll_fds));
2116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (data_fd_ < 0) {
2136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            poll_fds[0].fd     = listen_fd_;
2146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            poll_fds[0].events = POLLIN;
2156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        } else {
2166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            poll_fds[0].fd     = data_fd_;
2176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            poll_fds[0].events = POLLRDHUP | POLLIN;
2186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
2196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        int poll_res = poll(poll_fds, NELEM(poll_fds), 50);
2216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (poll_res < 0) {
2226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            ALOGE("Fatal error (%d,%d) while waiting on events",
2236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                 poll_res, errno);
2246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            goto bailout;
2256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
2266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (exitPending())
2286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            break;
2296c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2306c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (poll_fds[0].revents) {
2316c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            if (poll_fds[0].fd == listen_fd_) {
2326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                data_fd_ = accept(listen_fd_, NULL, NULL);
2336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                if (data_fd_ < 0) {
2356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    ALOGW("Failed accept on socket %d with err %d",
2366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         listen_fd_, errno);
2376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                } else {
2386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    if (!setNonblocking(data_fd_))
2396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        cleanupDataSocket();
2406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    if (!setNodelay(data_fd_))
2416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        cleanupDataSocket();
2426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                }
2436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            } else
2446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                if (poll_fds[0].fd == data_fd_) {
2456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    if (poll_fds[0].revents & POLLRDHUP) {
2466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        // Connection hung up; time to clean up.
2476c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        cleanupDataSocket();
2486c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    } else
2496c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        if (poll_fds[0].revents & POLLIN) {
2506c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                            uint8_t cmd;
2516c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                            if (read(data_fd_, &cmd, sizeof(cmd)) > 0) {
2526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                switch(cmd) {
2536c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                    case 'r':
2546c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                    case 'R':
2556c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                        resetLogIDs();
2566c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                        break;
2576c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                }
2586c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                            }
2596c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                        }
2606c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                }
2616c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
2626c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2636c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        struct local_time_debug_event events[kMaxEvents];
2646c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        int amt = local_clock_->getDebugLog(events, kMaxEvents);
2656c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2666c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (amt > 0) {
2676c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            for (int i = 0; i < amt; i++) {
2686c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                struct local_time_debug_event& e = events[i];
2696c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2706c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                if (!kernel_logID_basis_known_) {
2716c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    kernel_logID_basis_ = e.local_timesync_event_id;
2726c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    kernel_logID_basis_known_ = true;
2736c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                }
2746c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2756c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                char buf[1024];
2766c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                int64_t common_time;
2776c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                status_t res = common_clock_->localToCommon(e.local_time,
2786c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                                                            &common_time);
2796c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                snprintf(buf, sizeof(buf), "E,%lld,%lld,%lld,%d\n",
2806c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.local_timesync_event_id - kernel_logID_basis_,
2816c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.local_time,
2826c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         common_time,
2836c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         (OK == res) ? 1 : 0);
2846c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                buf[sizeof(buf) - 1] = 0;
2856c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2866c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                if (data_fd_ >= 0)
2876c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    write(data_fd_, buf, strlen(buf));
2886c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            }
2896c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
2906c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2916c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        { // scope for autolock pattern
2926c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            Mutex::Autolock lock(&discipline_log_lock_);
2936c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
2946c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            while (discipline_log_.size() > 0) {
2956c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                char buf[1024];
2966c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                DisciplineEventRecord& e = *discipline_log_.begin();
2976c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                snprintf(buf, sizeof(buf),
29811bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk                         "D,%lld,%lld,%lld,%lld,%lld,%lld,%d,%d\n",
2996c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.event_id,
3006c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.action_local_time,
3016c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.action_common_time,
3026c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.observed_local_time,
3036c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.observed_common_time,
3046c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.nominal_common_time,
3056c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                         e.total_correction,
30611bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk                         e.rtt);
3076c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                buf[sizeof(buf) - 1] = 0;
3086c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
3096c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                if (data_fd_ >= 0)
3106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                    write(data_fd_, buf, strlen(buf));
3116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
3126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen                discipline_log_.erase(discipline_log_.begin());
3136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            }
3146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
3156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
3166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
3176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenbailout:
3186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cleanupDataSocket();
319