1 /*
2 * Copyright (C) 2017 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 #define STATSD_DEBUG false // STOPSHIP if true
18 #include "Log.h"
19
20 #include <android/binder_ibinder.h>
21 #include <android/binder_ibinder_platform.h>
22 #include <android/binder_interface_utils.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25 #include <stdio.h>
26 #include <sys/random.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <utils/Looper.h>
31
32 #include "StatsService.h"
33 #include "flags/FlagProvider.h"
34 #include "packages/UidMap.h"
35 #include "socket/StatsSocketListener.h"
36
37 using namespace android;
38 using namespace android::os::statsd;
39 using ::ndk::SharedRefBase;
40 using std::shared_ptr;
41 using std::make_shared;
42
43 shared_ptr<StatsService> gStatsService = nullptr;
44 sp<StatsSocketListener> gSocketListener = nullptr;
45 int gCtrlPipe[2];
46
signalHandler(int sig)47 void signalHandler(int sig) {
48 ALOGW("statsd terminated on receiving signal %d.", sig);
49 const char c = 'q';
50 write(gCtrlPipe[1], &c, 1);
51 }
52
registerSignalHandlers()53 void registerSignalHandlers()
54 {
55 struct sigaction sa;
56 sigemptyset(&sa.sa_mask);
57 sa.sa_flags = 0;
58
59 sa.sa_handler = SIG_IGN;
60 // ShellSubscriber uses SIGPIPE as a signal to detect the end of the
61 // client process. Don't prematurely exit(1) here. Instead, ignore the
62 // signal and allow the write call to return EPIPE.
63 sigaction(SIGPIPE, &sa, nullptr);
64
65 pipe2(gCtrlPipe, O_CLOEXEC);
66 sa.sa_handler = signalHandler;
67 sigaction(SIGTERM, &sa, nullptr);
68 }
69
initSeedRandom()70 void initSeedRandom() {
71 unsigned int seed = 0;
72 // getrandom() reads bytes from urandom source into buf. If getrandom()
73 // is unable to read from urandom source, then it returns -1 and we set
74 // out seed to be time(nullptr) as a fallback.
75 if (TEMP_FAILURE_RETRY(
76 getrandom(static_cast<void*>(&seed), sizeof(unsigned int), GRND_NONBLOCK)) < 0) {
77 seed = time(nullptr);
78 }
79 srand(seed);
80 }
81
main(int,char **)82 int main(int /*argc*/, char** /*argv*/) {
83 // Set up the looper
84 sp<Looper> looper(Looper::prepare(0 /* opts */));
85
86 // Set up the binder
87 ABinderProcess_setThreadPoolMaxThreadCount(9);
88 ABinderProcess_startThreadPool();
89
90 // Initialize boot flags
91 FlagProvider::getInstance().initBootFlags({});
92
93 std::shared_ptr<LogEventQueue> eventQueue =
94 std::make_shared<LogEventQueue>(50000); /*buffer limit. Buffer is NOT pre-allocated*/
95
96 sp<UidMap> uidMap = UidMap::getInstance();
97
98 std::shared_ptr<LogEventFilter> logEventFilter = std::make_shared<LogEventFilter>();
99
100 initSeedRandom();
101
102 // Start reading events from the socket as early as possible.
103 // Processing from the queue is delayed until StatsService::startup to allow
104 // config initialization to occur before we start processing atoms.
105 gSocketListener = new StatsSocketListener(eventQueue, logEventFilter);
106
107 ALOGI("Statsd starts to listen to socket.");
108 // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
109 if (gSocketListener->startListener(600)) {
110 exit(1);
111 }
112
113 // Create the service
114 gStatsService = SharedRefBase::make<StatsService>(uidMap, eventQueue, logEventFilter);
115 auto binder = gStatsService->asBinder();
116
117 // We want to be able to ask for the selinux context of callers:
118 if (__builtin_available(android __ANDROID_API_U__, *)) {
119 AIBinder_setRequestingSid(binder.get(), true);
120 }
121
122 // TODO(b/149582373): Set DUMP_FLAG_PROTO once libbinder_ndk supports
123 // setting dumpsys priorities.
124 binder_status_t status = AServiceManager_addService(binder.get(), "stats");
125 if (status != STATUS_OK) {
126 ALOGE("Failed to add service as AIDL service");
127 return -1;
128 }
129
130 gStatsService->sayHiToStatsCompanion();
131
132 gStatsService->Startup();
133
134 // Enable the filter now since configs are initialized.
135 logEventFilter->setFilteringEnabled(true);
136
137 // Use self-pipe to notify this thread to gracefully quit
138 // when receiving SIGTERM
139 registerSignalHandlers();
140 std::thread([] {
141 while (true) {
142 char c;
143 int i = read(gCtrlPipe[0], &c, 1);
144 if (i < 0) {
145 if (errno == EINTR) continue;
146 }
147 gSocketListener->stopListener();
148 gStatsService->Terminate();
149 // return the signal handler to its default disposition, then raise the signal again
150 signal(SIGTERM, SIG_DFL);
151 // this is a sync call which leads to immediate process termination and
152 // no destructors are called, semantically similar to call exit(1) here
153 raise(SIGTERM);
154 }
155 }).detach();
156
157 // Loop forever -- the reports run on this thread in a handler, and the
158 // binder calls remain responsive in their pool of one thread.
159 while (true) {
160 looper->pollAll(-1 /* timeoutMillis */);
161 }
162 ALOGW("statsd escaped from its loop.");
163
164 return 1;
165 }
166