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