1 /*
2 * Copyright (C) 2020 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 #include "LogReaderList.h"
18
19 #include <android-base/logging.h>
20 #include <android/os/logcat/ILogcatManagerService.h>
21 #include <binder/IServiceManager.h>
22
23 using android::defaultServiceManager;
24 using android::sp;
25 using android::String16;
26 using android::os::logcat::ILogcatManagerService;
27
InitLogcatService()28 static sp<ILogcatManagerService> InitLogcatService() {
29 return android::interface_cast<ILogcatManagerService>(
30 defaultServiceManager()->waitForService(String16("logcat")));
31 }
32
GetLogcatService()33 static sp<ILogcatManagerService> GetLogcatService() {
34 static sp<ILogcatManagerService> logcat_service = InitLogcatService();
35
36 if (logcat_service == nullptr) {
37 LOG(ERROR) << "Permission problem or fatal error occurs to get logcat service";
38 }
39 return logcat_service;
40 }
41
42 // When we are notified a new log entry is available, inform
43 // listening sockets who are watching this entry's log id.
NotifyNewLog(LogMask log_mask) const44 void LogReaderList::NotifyNewLog(LogMask log_mask) const {
45 for (const auto& entry : running_reader_threads_) {
46 if (!entry->IsWatchingMultiple(log_mask)) {
47 continue;
48 }
49 if (entry->deadline().time_since_epoch().count() != 0) {
50 continue;
51 }
52 entry->TriggerReader();
53 }
54 }
55
HandlePendingThread(uid_t uid,gid_t gid,pid_t pid,int32_t fd,bool approve)56 bool LogReaderList::HandlePendingThread(uid_t uid, gid_t gid, pid_t pid, int32_t fd, bool approve) {
57 auto lock = std::lock_guard{logd_lock};
58 PendingReaderThreadKey key = {
59 .uid = uid,
60 .gid = gid,
61 .pid = pid,
62 .fd = fd,
63 };
64 auto iter = std::find_if(pending_reader_threads_.begin(), pending_reader_threads_.end(),
65 [&key](const auto& other) REQUIRES(logd_lock) {
66 return other->pending_reader_thread_key() == key;
67 });
68 if (iter == pending_reader_threads_.end()) {
69 return false;
70 }
71
72 auto entry = std::move(*iter);
73 pending_reader_threads_.erase(iter);
74 if (!approve) {
75 entry->Revoke();
76 } else {
77 entry->set_track_flag();
78 }
79 AddAndRunThread(std::move(entry));
80 return true;
81 }
82
AddAndRunThread(std::unique_ptr<LogReaderThread> thread)83 void LogReaderList::AddAndRunThread(std::unique_ptr<LogReaderThread> thread) {
84 thread->Run();
85 running_reader_threads_.emplace_front(std::move(thread));
86 }
87
RemoveRunningThread(LogReaderThread * thread)88 void LogReaderList::RemoveRunningThread(LogReaderThread* thread) {
89 auto iter = std::find_if(running_reader_threads_.begin(), running_reader_threads_.end(),
90 [thread](const auto& other)
91 REQUIRES(logd_lock) { return other.get() == thread; });
92 if (iter == running_reader_threads_.end()) {
93 return;
94 }
95
96 // If the track_flag is false, we don't need to notify LogcatManagerService.
97 // All the native processes are in this category, so we can remove the
98 // dependency on system_server for the native processes.
99 if (!thread->track_flag()) {
100 running_reader_threads_.erase(iter);
101 return;
102 }
103
104 auto service = GetLogcatService();
105 if (service != nullptr) {
106 const PendingReaderThreadKey key = thread->pending_reader_thread_key();
107 service->finishThread(key.uid, key.gid, key.pid, key.fd);
108 }
109 running_reader_threads_.erase(iter);
110 }
111
AddPendingThread(std::unique_ptr<LogReaderThread> thread)112 void LogReaderList::AddPendingThread(std::unique_ptr<LogReaderThread> thread) {
113 auto service = GetLogcatService();
114
115 // If the logcat binder service is not available, we will be not able to
116 // check the user consent. So we revoke the privileges.
117 if (service == nullptr) {
118 thread->Revoke();
119 AddAndRunThread(std::move(thread));
120 return;
121 }
122
123 const PendingReaderThreadKey key = thread->pending_reader_thread_key();
124 service->startThread(key.uid, key.gid, key.pid, key.fd);
125 pending_reader_threads_.emplace_back(std::move(thread));
126 }
127
ReleaseThreadByName(const std::string & cli_name)128 bool LogReaderList::ReleaseThreadByName(const std::string& cli_name) REQUIRES(logd_lock) {
129 for (const auto& reader : running_reader_threads_) {
130 if (reader->name() == cli_name) {
131 reader->Release();
132 return true;
133 }
134 }
135
136 for (const auto& reader : pending_reader_threads_) {
137 if (reader->name() == cli_name) {
138 reader->Release();
139 return true;
140 }
141 }
142 return false;
143 }
144