• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <utils/Looper.h>
30 
31 #include "StatsService.h"
32 #include "flags/FlagProvider.h"
33 #include "packages/UidMap.h"
34 #include "socket/StatsSocketListener.h"
35 
36 using namespace android;
37 using namespace android::os::statsd;
38 using ::ndk::SharedRefBase;
39 using std::shared_ptr;
40 using std::make_shared;
41 
42 shared_ptr<StatsService> gStatsService = nullptr;
43 sp<StatsSocketListener> gSocketListener = nullptr;
44 int gCtrlPipe[2];
45 
signalHandler(int sig)46 void signalHandler(int sig) {
47     ALOGW("statsd terminated on receiving signal %d.", sig);
48     const char c = 'q';
49     write(gCtrlPipe[1], &c, 1);
50 }
51 
registerSignalHandlers()52 void registerSignalHandlers()
53 {
54     struct sigaction sa;
55     sigemptyset(&sa.sa_mask);
56     sa.sa_flags = 0;
57 
58     sa.sa_handler = SIG_IGN;
59     // ShellSubscriber uses SIGPIPE as a signal to detect the end of the
60     // client process. Don't prematurely exit(1) here. Instead, ignore the
61     // signal and allow the write call to return EPIPE.
62     sigaction(SIGPIPE, &sa, nullptr);
63 
64     pipe2(gCtrlPipe, O_CLOEXEC);
65     sa.sa_handler = signalHandler;
66     sigaction(SIGTERM, &sa, nullptr);
67 }
68 
main(int,char **)69 int main(int /*argc*/, char** /*argv*/) {
70     // Set up the looper
71     sp<Looper> looper(Looper::prepare(0 /* opts */));
72 
73     // Set up the binder
74     ABinderProcess_setThreadPoolMaxThreadCount(9);
75     ABinderProcess_startThreadPool();
76 
77     std::shared_ptr<LogEventQueue> eventQueue =
78             std::make_shared<LogEventQueue>(8000 /*buffer limit. Buffer is NOT pre-allocated*/);
79 
80     // Initialize boot flags
81     FlagProvider::getInstance().initBootFlags(
82             {OPTIMIZATION_SOCKET_PARSING_FLAG, STATSD_INIT_COMPLETED_NO_DELAY_FLAG});
83 
84     sp<UidMap> uidMap = UidMap::getInstance();
85 
86     const bool logsFilteringEnabled = FlagProvider::getInstance().getBootFlagBool(
87             OPTIMIZATION_SOCKET_PARSING_FLAG, FLAG_FALSE);
88     std::shared_ptr<LogEventFilter> logEventFilter =
89             logsFilteringEnabled ? std::make_shared<LogEventFilter>() : nullptr;
90 
91     const int initEventDelay = FlagProvider::getInstance().getBootFlagBool(
92                                        STATSD_INIT_COMPLETED_NO_DELAY_FLAG, FLAG_FALSE)
93                                        ? 0
94                                        : StatsService::kStatsdInitDelaySecs;
95     // Create the service
96     gStatsService =
97             SharedRefBase::make<StatsService>(uidMap, eventQueue, logEventFilter, initEventDelay);
98     auto binder = gStatsService->asBinder();
99 
100     // We want to be able to ask for the selinux context of callers:
101     if (__builtin_available(android __ANDROID_API_U__, *)) {
102         AIBinder_setRequestingSid(binder.get(), true);
103     }
104 
105     // TODO(b/149582373): Set DUMP_FLAG_PROTO once libbinder_ndk supports
106     // setting dumpsys priorities.
107     binder_status_t status = AServiceManager_addService(binder.get(), "stats");
108     if (status != STATUS_OK) {
109         ALOGE("Failed to add service as AIDL service");
110         return -1;
111     }
112 
113     gStatsService->sayHiToStatsCompanion();
114 
115     gStatsService->Startup();
116 
117     gSocketListener = new StatsSocketListener(eventQueue, logEventFilter);
118 
119     ALOGI("Statsd starts to listen to socket.");
120     // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
121     if (gSocketListener->startListener(600)) {
122         exit(1);
123     }
124 
125     // Use self-pipe to notify this thread to gracefully quit
126     // when receiving SIGTERM
127     registerSignalHandlers();
128     std::thread([] {
129         while (true) {
130             char c;
131             int i = read(gCtrlPipe[0], &c, 1);
132             if (i < 0) {
133                 if (errno == EINTR) continue;
134             }
135             gSocketListener->stopListener();
136             gStatsService->Terminate();
137             exit(1);
138         }
139     }).detach();
140 
141     // Loop forever -- the reports run on this thread in a handler, and the
142     // binder calls remain responsive in their pool of one thread.
143     while (true) {
144         looper->pollAll(-1 /* timeoutMillis */);
145     }
146     ALOGW("statsd escaped from its loop.");
147 
148     return 1;
149 }
150