1 /*
2  * Copyright (C) 2012-2013 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 #pragma once
18 
19 #include <pthread.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <time.h>
23 
24 #include <chrono>
25 #include <condition_variable>
26 #include <list>
27 #include <memory>
28 
29 #include <log/log.h>
30 #include <sysutils/SocketClient.h>
31 
32 #include "LogBuffer.h"
33 #include "LogWriter.h"
34 
35 class LogReaderList;
36 
37 class LogReaderThread {
38   public:
39     LogReaderThread(LogBuffer* log_buffer, LogReaderList* reader_list,
40                     std::unique_ptr<LogWriter> writer, bool non_block, unsigned long tail,
41                     LogMask log_mask, pid_t pid, log_time start_time, uint64_t sequence,
42                     std::chrono::steady_clock::time_point deadline);
triggerReader_Locked()43     void triggerReader_Locked() { thread_triggered_condition_.notify_all(); }
44 
triggerSkip_Locked(log_id_t id,unsigned int skip)45     void triggerSkip_Locked(log_id_t id, unsigned int skip) { skip_ahead_[id] = skip; }
46     void cleanSkip_Locked();
47 
release_Locked()48     void release_Locked() {
49         // gracefully shut down the socket.
50         writer_->Shutdown();
51         release_ = true;
52         thread_triggered_condition_.notify_all();
53     }
54 
IsWatching(log_id_t id)55     bool IsWatching(log_id_t id) const { return flush_to_state_->log_mask() & (1 << id); }
IsWatchingMultiple(LogMask log_mask)56     bool IsWatchingMultiple(LogMask log_mask) const {
57         return flush_to_state_->log_mask() & log_mask;
58     }
59 
name()60     std::string name() const { return writer_->name(); }
start()61     uint64_t start() const { return flush_to_state_->start(); }
deadline()62     std::chrono::steady_clock::time_point deadline() const { return deadline_; }
flush_to_state()63     FlushToState& flush_to_state() { return *flush_to_state_; }
64 
65   private:
66     void ThreadFunction();
67     // flushTo filter callbacks
68     FilterResult FilterFirstPass(log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime);
69     FilterResult FilterSecondPass(log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime);
70 
71     std::condition_variable thread_triggered_condition_;
72     LogBuffer* log_buffer_;
73     LogReaderList* reader_list_;
74     std::unique_ptr<LogWriter> writer_;
75 
76     // Set to true to cause the thread to end and the LogReaderThread to delete itself.
77     bool release_ = false;
78 
79     // If set to non-zero, only pids equal to this are read by the reader.
80     const pid_t pid_;
81     // When a reader is referencing (via start_) old elements in the log buffer, and the log
82     // buffer's size grows past its memory limit, the log buffer may request the reader to skip
83     // ahead a specified number of logs.
84     unsigned int skip_ahead_[LOG_ID_MAX];
85     // LogBuffer::FlushTo() needs to store state across subsequent calls.
86     std::unique_ptr<FlushToState> flush_to_state_;
87 
88     // These next three variables are used for reading only the most recent lines aka `adb logcat
89     // -t` / `adb logcat -T`.
90     // tail_ is the number of most recent lines to print.
91     unsigned long tail_;
92     // count_ is the result of a first pass through the log buffer to determine how many total
93     // messages there are.
94     unsigned long count_;
95     // index_ is used along with count_ to only start sending lines once index_ > (count_ - tail_)
96     // and to disconnect the reader (if it is dumpAndClose, `adb logcat -t`), when index_ >= count_.
97     unsigned long index_;
98 
99     // When a reader requests logs starting from a given timestamp, its stored here for the first
100     // pass, such that logs before this time stamp that are accumulated in the buffer are ignored.
101     log_time start_time_;
102     // CLOCK_MONOTONIC based deadline used for log wrapping.  If this deadline expires before logs
103     // wrap, then wake up and send the logs to the reader anyway.
104     std::chrono::steady_clock::time_point deadline_;
105     // If this reader is 'dumpAndClose' and will disconnect once it has read its intended logs.
106     const bool non_block_;
107 };
108