• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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