10175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn/*
20175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Copyright (C) 2012-2013 The Android Open Source Project
30175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
40175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
50175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * you may not use this file except in compliance with the License.
60175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * You may obtain a copy of the License at
70175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
80175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
90175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
110175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
120175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * See the License for the specific language governing permissions and
140175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * limitations under the License.
150175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn */
160175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
17fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <ctype.h>
18fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn#include <inttypes.h>
190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <poll.h>
208daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn#include <sys/prctl.h>
210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/socket.h>
225c77ad55d0cdee84cd45fd5d0d066f3c61d76ce6Mark Salyzyn#include <sys/types.h>
23dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <cutils/sockets.h>
25aeaaf81c2cc8366ac4f66eb3d2fc85f9b8194982Mark Salyzyn#include <private/android_logger.h>
260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
270175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "FlushCommand.h"
282ad0bd0a9b594bbe2560b405b0008b7bc742cfcaMark Salyzyn#include "LogBuffer.h"
292ad0bd0a9b594bbe2560b405b0008b7bc742cfcaMark Salyzyn#include "LogBufferElement.h"
302ad0bd0a9b594bbe2560b405b0008b7bc742cfcaMark Salyzyn#include "LogReader.h"
312ad0bd0a9b594bbe2560b405b0008b7bc742cfcaMark Salyzyn#include "LogUtils.h"
320175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
33501c373916e292764400dbae735f44b33378400fMark SalyzynLogReader::LogReader(LogBuffer* logbuf)
34501c373916e292764400dbae735f44b33378400fMark Salyzyn    : SocketListener(getLogSocket(), true), mLogbuf(*logbuf) {
357718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn}
360175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// When we are notified a new log entry is available, inform
38f6e229695375bda653a7f1b6f2470e054dc2d6bfHao Wang// listening sockets who are watching this entry's log id.
39f6e229695375bda653a7f1b6f2470e054dc2d6bfHao Wangvoid LogReader::notifyNewLog(log_mask_t logMask) {
40f6e229695375bda653a7f1b6f2470e054dc2d6bfHao Wang    FlushCommand command(*this, logMask);
410175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    runOnEachSocket(&command);
420175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
430175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
44501c373916e292764400dbae735f44b33378400fMark Salyzynbool LogReader::onDataAvailable(SocketClient* cli) {
45e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    static bool name_set;
46e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    if (!name_set) {
47e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn        prctl(PR_SET_NAME, "logd.reader");
48e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn        name_set = true;
49e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    }
508daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn
510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    char buffer[255];
520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1);
540175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (len <= 0) {
550175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        doSocketDelete(cli);
560175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return false;
570175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
580175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    buffer[len] = '\0';
590175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
600175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    unsigned long tail = 0;
610175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    static const char _tail[] = " tail=";
62501c373916e292764400dbae735f44b33378400fMark Salyzyn    char* cp = strstr(buffer, _tail);
630175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (cp) {
640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        tail = atol(cp + sizeof(_tail) - 1);
650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
67fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    log_time start(log_time::EPOCH);
68fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    static const char _start[] = " start=";
69fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    cp = strstr(buffer, _start);
70fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    if (cp) {
71fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn        // Parse errors will result in current time
72fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn        start.strptime(cp + sizeof(_start) - 1, "%s.%q");
73fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    }
74fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
75b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    uint64_t timeout = 0;
76b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    static const char _timeout[] = " timeout=";
77b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    cp = strstr(buffer, _timeout);
78b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    if (cp) {
79b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn        timeout = atol(cp + sizeof(_timeout) - 1) * NS_PER_SEC +
80b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn                  log_time(CLOCK_REALTIME).nsec();
81b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    }
82b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn
830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    unsigned int logMask = -1;
840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    static const char _logIds[] = " lids=";
850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    cp = strstr(buffer, _logIds);
860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (cp) {
870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        logMask = 0;
880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        cp += sizeof(_logIds) - 1;
890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        while (*cp && *cp != '\0') {
900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            int val = 0;
91fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn            while (isdigit(*cp)) {
92fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn                val = val * 10 + *cp - '0';
930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn                ++cp;
940175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            }
950175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            logMask |= 1 << val;
960175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            if (*cp != ',') {
970175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn                break;
980175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            }
990175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            ++cp;
1000175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        }
1010175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
1020175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1030175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    pid_t pid = 0;
1040175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    static const char _pid[] = " pid=";
1050175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    cp = strstr(buffer, _pid);
1060175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (cp) {
1070175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        pid = atol(cp + sizeof(_pid) - 1);
1080175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
1090175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    bool nonBlock = false;
1110eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn    if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
112f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn        // Allow writer to get some cycles, and wait for pending notifications
113f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn        sched_yield();
1143c501b50b41086cde59a6811f4aa5cd3e736f5f2Mark Salyzyn        LogTimeEntry::wrlock();
115f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn        LogTimeEntry::unlock();
116f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn        sched_yield();
1170175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        nonBlock = true;
1180175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
1190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1205a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    log_time sequence = start;
1215a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    //
1225a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // This somewhat expensive data validation operation is required
1235a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // for non-blocking, with timeout.  The incoming timestamp must be
1245a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // in range of the list, if not, return immediately.  This is
1255a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // used to prevent us from from getting stuck in timeout processing
1265a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // with an invalid time.
1275a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    //
1285a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // Find if time is really present in the logs, monotonic or real, implicit
1295a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // conversion from monotonic or real as necessary to perform the check.
1305a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // Exit in the check loop ASAP as you find a transition from older to
1315a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    // newer, but use the last entry found to ensure overlap.
1325a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    //
1335a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn    if (nonBlock && (sequence != log_time::EPOCH) && timeout) {
1345a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn        class LogFindStart {  // A lambda by another name
1355a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn           private:
136a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            const pid_t mPid;
137a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            const unsigned mLogMask;
1385a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            bool mStartTimeSet;
1395a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            log_time mStart;
1405a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            log_time& mSequence;
1415a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            log_time mLast;
1425a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            bool mIsMonotonic;
143a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
144501c373916e292764400dbae735f44b33378400fMark Salyzyn           public:
1455a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            LogFindStart(pid_t pid, unsigned logMask, log_time& sequence,
1465a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                         bool isMonotonic)
147501c373916e292764400dbae735f44b33378400fMark Salyzyn                : mPid(pid),
148501c373916e292764400dbae735f44b33378400fMark Salyzyn                  mLogMask(logMask),
1495a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                  mStartTimeSet(false),
1505a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                  mStart(sequence),
1515a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                  mSequence(sequence),
1525a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                  mLast(sequence),
1535a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                  mIsMonotonic(isMonotonic) {
1547718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn            }
155a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
156501c373916e292764400dbae735f44b33378400fMark Salyzyn            static int callback(const LogBufferElement* element, void* obj) {
157501c373916e292764400dbae735f44b33378400fMark Salyzyn                LogFindStart* me = reinterpret_cast<LogFindStart*>(obj);
158501c373916e292764400dbae735f44b33378400fMark Salyzyn                if ((!me->mPid || (me->mPid == element->getPid())) &&
159501c373916e292764400dbae735f44b33378400fMark Salyzyn                    (me->mLogMask & (1 << element->getLogId()))) {
1605a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                    log_time real = element->getRealTime();
1615a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                    if (me->mStart == real) {
1625a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                        me->mSequence = real;
1635a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                        me->mStartTimeSet = true;
164f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                        return -1;
1655a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                    } else if (!me->mIsMonotonic || android::isMonotonic(real)) {
1665a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                        if (me->mStart < real) {
1675a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                            me->mSequence = me->mLast;
1685a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                            me->mStartTimeSet = true;
169f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                            return -1;
170a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                        }
1715a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                        me->mLast = real;
172b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn                    } else {
1735a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                        me->mLast = real;
174a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                    }
175a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                }
176a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                return false;
177a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            }
178a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
179501c373916e292764400dbae735f44b33378400fMark Salyzyn            bool found() {
1805a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn                return mStartTimeSet;
181501c373916e292764400dbae735f44b33378400fMark Salyzyn            }
1825a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn
1835a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn        } logFindStart(pid, logMask, sequence,
184b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn                       logbuf().isMonotonic() && android::isMonotonic(start));
185a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
186ae2abf112ca8555dfc09eb1fc4b8bd637e4bc7ccMark Salyzyn        logbuf().flushTo(cli, sequence, nullptr, FlushCommand::hasReadLogs(cli),
1878fa8896d2ed97eb274c62f0e386dabf2e2a82a45Mark Salyzyn                         FlushCommand::hasSecurityLogs(cli),
188a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                         logFindStart.callback, &logFindStart);
189a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
190a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn        if (!logFindStart.found()) {
1915a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            doSocketDelete(cli);
1925a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531Mark Salyzyn            return false;
193a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn        }
194fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    }
195fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
196fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn    android::prdebug(
197fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn        "logdr: UID=%d GID=%d PID=%d %c tail=%lu logMask=%x pid=%d "
198fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn        "start=%" PRIu64 "ns timeout=%" PRIu64 "ns\n",
199fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn        cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail,
200fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn        logMask, (int)pid, sequence.nsec(), timeout);
201fa3add33644eb0e0335fefafef41de5e2d3c0b3cMark Salyzyn
202b75cce0389748bea111ca62af623645117e12d9dMark Salyzyn    FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence, timeout);
2035c77ad55d0cdee84cd45fd5d0d066f3c61d76ce6Mark Salyzyn
2045c77ad55d0cdee84cd45fd5d0d066f3c61d76ce6Mark Salyzyn    // Set acceptable upper limit to wait for slow reader processing b/27242723
2055c77ad55d0cdee84cd45fd5d0d066f3c61d76ce6Mark Salyzyn    struct timeval t = { LOGD_SNDTIMEO, 0 };
206501c373916e292764400dbae735f44b33378400fMark Salyzyn    setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&t,
207501c373916e292764400dbae735f44b33378400fMark Salyzyn               sizeof(t));
2085c77ad55d0cdee84cd45fd5d0d066f3c61d76ce6Mark Salyzyn
2090175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    command.runSocketCommand(cli);
2100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    return true;
2110175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
2120175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
213501c373916e292764400dbae735f44b33378400fMark Salyzynvoid LogReader::doSocketDelete(SocketClient* cli) {
214501c373916e292764400dbae735f44b33378400fMark Salyzyn    LastLogTimes& times = mLogbuf.mTimes;
2153c501b50b41086cde59a6811f4aa5cd3e736f5f2Mark Salyzyn    LogTimeEntry::wrlock();
2160175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LastLogTimes::iterator it = times.begin();
217501c373916e292764400dbae735f44b33378400fMark Salyzyn    while (it != times.end()) {
218501c373916e292764400dbae735f44b33378400fMark Salyzyn        LogTimeEntry* entry = (*it);
2190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        if (entry->mClient == cli) {
2200175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            times.erase(it);
2210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            entry->release_Locked();
2220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            break;
2230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        }
2240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        it++;
2250175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
2260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LogTimeEntry::unlock();
2270175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
228dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
229dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzynint LogReader::getLogSocket() {
230dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    static const char socketName[] = "logdr";
231dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    int sock = android_get_control_socket(socketName);
232dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
233dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    if (sock < 0) {
234501c373916e292764400dbae735f44b33378400fMark Salyzyn        sock = socket_local_server(
235501c373916e292764400dbae735f44b33378400fMark Salyzyn            socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
236dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    }
237dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
238dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    return sock;
239dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn}
240