xref: /aosp_15_r20/frameworks/native/cmds/dumpstate/dumpstate.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "dumpstate"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_ALWAYS
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker #include "dumpstate.h"
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker #include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <android-base/file.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/properties.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <android-base/strings.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_manager.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_process.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <android/content/pm/IPackageManagerNative.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <android/hardware/dumpstate/1.1/types.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <android/hidl/manager/1.0/IServiceManager.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <android/os/IIncidentCompanion.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <android_app_admin_flags.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <android_tracing.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <cutils/multiuser.h>
41*38e8c45fSAndroid Build Coastguard Worker #include <cutils/native_handle.h>
42*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
43*38e8c45fSAndroid Build Coastguard Worker #include <cutils/sockets.h>
44*38e8c45fSAndroid Build Coastguard Worker #include <cutils/trace.h>
45*38e8c45fSAndroid Build Coastguard Worker #include <debuggerd/client.h>
46*38e8c45fSAndroid Build Coastguard Worker #include <dirent.h>
47*38e8c45fSAndroid Build Coastguard Worker #include <dumpsys.h>
48*38e8c45fSAndroid Build Coastguard Worker #include <dumputils/dump_utils.h>
49*38e8c45fSAndroid Build Coastguard Worker #include <errno.h>
50*38e8c45fSAndroid Build Coastguard Worker #include <fcntl.h>
51*38e8c45fSAndroid Build Coastguard Worker #include <hardware_legacy/power.h>
52*38e8c45fSAndroid Build Coastguard Worker #include <hidl/ServiceManagement.h>
53*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
54*38e8c45fSAndroid Build Coastguard Worker #include <libgen.h>
55*38e8c45fSAndroid Build Coastguard Worker #include <limits.h>
56*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
57*38e8c45fSAndroid Build Coastguard Worker #include <log/log_read.h>
58*38e8c45fSAndroid Build Coastguard Worker #include <math.h>
59*38e8c45fSAndroid Build Coastguard Worker #include <openssl/sha.h>
60*38e8c45fSAndroid Build Coastguard Worker #include <poll.h>
61*38e8c45fSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
62*38e8c45fSAndroid Build Coastguard Worker #include <private/android_logger.h>
63*38e8c45fSAndroid Build Coastguard Worker #include <serviceutils/PriorityDumper.h>
64*38e8c45fSAndroid Build Coastguard Worker #include <signal.h>
65*38e8c45fSAndroid Build Coastguard Worker #include <stdarg.h>
66*38e8c45fSAndroid Build Coastguard Worker #include <stdbool.h>
67*38e8c45fSAndroid Build Coastguard Worker #include <stdio.h>
68*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
69*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
70*38e8c45fSAndroid Build Coastguard Worker #include <sys/capability.h>
71*38e8c45fSAndroid Build Coastguard Worker #include <sys/inotify.h>
72*38e8c45fSAndroid Build Coastguard Worker #include <sys/klog.h>
73*38e8c45fSAndroid Build Coastguard Worker #include <sys/mount.h>
74*38e8c45fSAndroid Build Coastguard Worker #include <sys/poll.h>
75*38e8c45fSAndroid Build Coastguard Worker #include <sys/prctl.h>
76*38e8c45fSAndroid Build Coastguard Worker #include <sys/resource.h>
77*38e8c45fSAndroid Build Coastguard Worker #include <sys/stat.h>
78*38e8c45fSAndroid Build Coastguard Worker #include <sys/time.h>
79*38e8c45fSAndroid Build Coastguard Worker #include <sys/wait.h>
80*38e8c45fSAndroid Build Coastguard Worker #include <time.h>
81*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
82*38e8c45fSAndroid Build Coastguard Worker #include <utils/StrongPointer.h>
83*38e8c45fSAndroid Build Coastguard Worker #include <vintf/VintfObject.h>
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
86*38e8c45fSAndroid Build Coastguard Worker #include <cmath>
87*38e8c45fSAndroid Build Coastguard Worker #include <fstream>
88*38e8c45fSAndroid Build Coastguard Worker #include <functional>
89*38e8c45fSAndroid Build Coastguard Worker #include <future>
90*38e8c45fSAndroid Build Coastguard Worker #include <memory>
91*38e8c45fSAndroid Build Coastguard Worker #include <numeric>
92*38e8c45fSAndroid Build Coastguard Worker #include <regex>
93*38e8c45fSAndroid Build Coastguard Worker #include <set>
94*38e8c45fSAndroid Build Coastguard Worker #include <string>
95*38e8c45fSAndroid Build Coastguard Worker #include <utility>
96*38e8c45fSAndroid Build Coastguard Worker #include <vector>
97*38e8c45fSAndroid Build Coastguard Worker 
98*38e8c45fSAndroid Build Coastguard Worker #include "DumpstateInternal.h"
99*38e8c45fSAndroid Build Coastguard Worker #include "DumpstateService.h"
100*38e8c45fSAndroid Build Coastguard Worker 
101*38e8c45fSAndroid Build Coastguard Worker namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
102*38e8c45fSAndroid Build Coastguard Worker namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
103*38e8c45fSAndroid Build Coastguard Worker namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
104*38e8c45fSAndroid Build Coastguard Worker 
105*38e8c45fSAndroid Build Coastguard Worker using ::std::literals::chrono_literals::operator""ms;
106*38e8c45fSAndroid Build Coastguard Worker using ::std::literals::chrono_literals::operator""s;
107*38e8c45fSAndroid Build Coastguard Worker using ::std::placeholders::_1;
108*38e8c45fSAndroid Build Coastguard Worker 
109*38e8c45fSAndroid Build Coastguard Worker // TODO: remove once moved to namespace
110*38e8c45fSAndroid Build Coastguard Worker using android::defaultServiceManager;
111*38e8c45fSAndroid Build Coastguard Worker using android::Dumpsys;
112*38e8c45fSAndroid Build Coastguard Worker using android::INVALID_OPERATION;
113*38e8c45fSAndroid Build Coastguard Worker using android::IServiceManager;
114*38e8c45fSAndroid Build Coastguard Worker using android::OK;
115*38e8c45fSAndroid Build Coastguard Worker using android::sp;
116*38e8c45fSAndroid Build Coastguard Worker using android::status_t;
117*38e8c45fSAndroid Build Coastguard Worker using android::String16;
118*38e8c45fSAndroid Build Coastguard Worker using android::String8;
119*38e8c45fSAndroid Build Coastguard Worker using android::TIMED_OUT;
120*38e8c45fSAndroid Build Coastguard Worker using android::UNKNOWN_ERROR;
121*38e8c45fSAndroid Build Coastguard Worker using android::Vector;
122*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
123*38e8c45fSAndroid Build Coastguard Worker using android::os::IDumpstateListener;
124*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::CommandOptions;
125*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::DumpFileToFd;
126*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::DumpPool;
127*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::PropertiesHelper;
128*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::TaskQueue;
129*38e8c45fSAndroid Build Coastguard Worker using android::os::dumpstate::WaitForTask;
130*38e8c45fSAndroid Build Coastguard Worker 
131*38e8c45fSAndroid Build Coastguard Worker // Keep in sync with
132*38e8c45fSAndroid Build Coastguard Worker // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
133*38e8c45fSAndroid Build Coastguard Worker static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
134*38e8c45fSAndroid Build Coastguard Worker 
135*38e8c45fSAndroid Build Coastguard Worker /* Most simple commands have 10 as timeout, so 5 is a good estimate */
136*38e8c45fSAndroid Build Coastguard Worker static const int32_t WEIGHT_FILE = 5;
137*38e8c45fSAndroid Build Coastguard Worker 
138*38e8c45fSAndroid Build Coastguard Worker // TODO: temporary variables and functions used during C++ refactoring
139*38e8c45fSAndroid Build Coastguard Worker static Dumpstate& ds = Dumpstate::GetInstance();
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options=CommandOptions::DEFAULT,bool verbose_duration=false,int out_fd=STDOUT_FILENO)140*38e8c45fSAndroid Build Coastguard Worker static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
141*38e8c45fSAndroid Build Coastguard Worker                       const CommandOptions& options = CommandOptions::DEFAULT,
142*38e8c45fSAndroid Build Coastguard Worker                       bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
143*38e8c45fSAndroid Build Coastguard Worker     return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker 
146*38e8c45fSAndroid Build Coastguard Worker // Reasonable value for max stats.
147*38e8c45fSAndroid Build Coastguard Worker static const int STATS_MAX_N_RUNS = 1000;
148*38e8c45fSAndroid Build Coastguard Worker static const long STATS_MAX_AVERAGE = 100000;
149*38e8c45fSAndroid Build Coastguard Worker 
150*38e8c45fSAndroid Build Coastguard Worker CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
151*38e8c45fSAndroid Build Coastguard Worker 
152*38e8c45fSAndroid Build Coastguard Worker typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker /* read before root is shed */
155*38e8c45fSAndroid Build Coastguard Worker static char cmdline_buf[16384] = "(unknown)";
156*38e8c45fSAndroid Build Coastguard Worker static const char *dump_traces_path = nullptr;
157*38e8c45fSAndroid Build Coastguard Worker static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
158*38e8c45fSAndroid Build Coastguard Worker // Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
159*38e8c45fSAndroid Build Coastguard Worker // it's often the case that they time out far too quickly for consent with such a hefty dialog for
160*38e8c45fSAndroid Build Coastguard Worker // the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
161*38e8c45fSAndroid Build Coastguard Worker // roughly match full reports' durations.
162*38e8c45fSAndroid Build Coastguard Worker static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
163*38e8c45fSAndroid Build Coastguard Worker 
164*38e8c45fSAndroid Build Coastguard Worker // TODO: variables and functions below should be part of dumpstate object
165*38e8c45fSAndroid Build Coastguard Worker 
166*38e8c45fSAndroid Build Coastguard Worker static std::set<std::string> mount_points;
167*38e8c45fSAndroid Build Coastguard Worker void add_mountinfo();
168*38e8c45fSAndroid Build Coastguard Worker 
169*38e8c45fSAndroid Build Coastguard Worker #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
170*38e8c45fSAndroid Build Coastguard Worker #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
171*38e8c45fSAndroid Build Coastguard Worker #define BLK_DEV_SYS_DIR "/sys/block"
172*38e8c45fSAndroid Build Coastguard Worker 
173*38e8c45fSAndroid Build Coastguard Worker #define AFLAGS "/system/bin/aflags"
174*38e8c45fSAndroid Build Coastguard Worker #define RECOVERY_DIR "/cache/recovery"
175*38e8c45fSAndroid Build Coastguard Worker #define RECOVERY_DATA_DIR "/data/misc/recovery"
176*38e8c45fSAndroid Build Coastguard Worker #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
177*38e8c45fSAndroid Build Coastguard Worker #define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
178*38e8c45fSAndroid Build Coastguard Worker #define LOGPERSIST_DATA_DIR "/data/misc/logd"
179*38e8c45fSAndroid Build Coastguard Worker #define PREREBOOT_DATA_DIR "/data/misc/prereboot"
180*38e8c45fSAndroid Build Coastguard Worker #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
181*38e8c45fSAndroid Build Coastguard Worker #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
182*38e8c45fSAndroid Build Coastguard Worker #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
183*38e8c45fSAndroid Build Coastguard Worker #define KERNEL_CONFIG "/proc/config.gz"
184*38e8c45fSAndroid Build Coastguard Worker #define WLUTIL "/vendor/xbin/wlutil"
185*38e8c45fSAndroid Build Coastguard Worker #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
186*38e8c45fSAndroid Build Coastguard Worker #define OTA_METADATA_DIR "/metadata/ota"
187*38e8c45fSAndroid Build Coastguard Worker #define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
188*38e8c45fSAndroid Build Coastguard Worker #define LINKERCONFIG_DIR "/linkerconfig"
189*38e8c45fSAndroid Build Coastguard Worker #define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
190*38e8c45fSAndroid Build Coastguard Worker #define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
191*38e8c45fSAndroid Build Coastguard Worker #define CGROUPFS_DIR "/sys/fs/cgroup"
192*38e8c45fSAndroid Build Coastguard Worker #define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
193*38e8c45fSAndroid Build Coastguard Worker #define DROPBOX_DIR "/data/system/dropbox"
194*38e8c45fSAndroid Build Coastguard Worker #define PRINT_FLAGS "/system/bin/printflags"
195*38e8c45fSAndroid Build Coastguard Worker #define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
196*38e8c45fSAndroid Build Coastguard Worker 
197*38e8c45fSAndroid Build Coastguard Worker // TODO(narayan): Since this information has to be kept in sync
198*38e8c45fSAndroid Build Coastguard Worker // with tombstoned, we should just put it in a common header.
199*38e8c45fSAndroid Build Coastguard Worker //
200*38e8c45fSAndroid Build Coastguard Worker // File: system/core/debuggerd/tombstoned/tombstoned.cpp
201*38e8c45fSAndroid Build Coastguard Worker static const std::string TOMBSTONE_DIR = "/data/tombstones/";
202*38e8c45fSAndroid Build Coastguard Worker static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
203*38e8c45fSAndroid Build Coastguard Worker static const std::string ANR_DIR = "/data/anr/";
204*38e8c45fSAndroid Build Coastguard Worker static const std::string ANR_FILE_PREFIX = "anr_";
205*38e8c45fSAndroid Build Coastguard Worker static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
206*38e8c45fSAndroid Build Coastguard Worker static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
207*38e8c45fSAndroid Build Coastguard Worker static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
208*38e8c45fSAndroid Build Coastguard Worker 
209*38e8c45fSAndroid Build Coastguard Worker // File path to default screenshot image, that used when failed to capture the real screenshot.
210*38e8c45fSAndroid Build Coastguard Worker static const std::string DEFAULT_SCREENSHOT_PATH = "/system/etc/default_screenshot.png";
211*38e8c45fSAndroid Build Coastguard Worker 
212*38e8c45fSAndroid Build Coastguard Worker // TODO: temporary variables and functions used during C++ refactoring
213*38e8c45fSAndroid Build Coastguard Worker 
214*38e8c45fSAndroid Build Coastguard Worker #define RETURN_IF_USER_DENIED_CONSENT()                                                        \
215*38e8c45fSAndroid Build Coastguard Worker     if (ds.IsUserConsentDenied()) {                                                            \
216*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
217*38e8c45fSAndroid Build Coastguard Worker         return Dumpstate::RunStatus::USER_CONSENT_DENIED;                                      \
218*38e8c45fSAndroid Build Coastguard Worker     }
219*38e8c45fSAndroid Build Coastguard Worker 
220*38e8c45fSAndroid Build Coastguard Worker // Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
221*38e8c45fSAndroid Build Coastguard Worker // if consent is found to be denied.
222*38e8c45fSAndroid Build Coastguard Worker #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
223*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();                        \
224*38e8c45fSAndroid Build Coastguard Worker     func_ptr(__VA_ARGS__);                                  \
225*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
226*38e8c45fSAndroid Build Coastguard Worker 
227*38e8c45fSAndroid Build Coastguard Worker // Runs func_ptr, and logs a duration report after it's finished.
228*38e8c45fSAndroid Build Coastguard Worker #define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...)      \
229*38e8c45fSAndroid Build Coastguard Worker     {                                                            \
230*38e8c45fSAndroid Build Coastguard Worker         DurationReporter duration_reporter_in_macro(log_title);  \
231*38e8c45fSAndroid Build Coastguard Worker         func_ptr(__VA_ARGS__);                                   \
232*38e8c45fSAndroid Build Coastguard Worker     }
233*38e8c45fSAndroid Build Coastguard Worker 
234*38e8c45fSAndroid Build Coastguard Worker // Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
235*38e8c45fSAndroid Build Coastguard Worker // is output after a slow function is finished.
236*38e8c45fSAndroid Build Coastguard Worker #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
237*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();                                           \
238*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__);               \
239*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
240*38e8c45fSAndroid Build Coastguard Worker 
241*38e8c45fSAndroid Build Coastguard Worker #define WAIT_TASK_WITH_CONSENT_CHECK(future) \
242*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();                      \
243*38e8c45fSAndroid Build Coastguard Worker     WaitForTask(future);                     \
244*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
245*38e8c45fSAndroid Build Coastguard Worker 
246*38e8c45fSAndroid Build Coastguard Worker static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
247*38e8c45fSAndroid Build Coastguard Worker 
248*38e8c45fSAndroid Build Coastguard Worker // Names of parallel tasks, they are used for the DumpPool to identify the dump
249*38e8c45fSAndroid Build Coastguard Worker // task and the log title of the duration report.
250*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
251*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
252*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
253*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_HALS_TASK = "DUMP HALS";
254*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
255*38e8c45fSAndroid Build Coastguard Worker static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
256*38e8c45fSAndroid Build Coastguard Worker static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
257*38e8c45fSAndroid Build Coastguard Worker 
258*38e8c45fSAndroid Build Coastguard Worker namespace android {
259*38e8c45fSAndroid Build Coastguard Worker namespace os {
260*38e8c45fSAndroid Build Coastguard Worker namespace {
261*38e8c45fSAndroid Build Coastguard Worker 
Open(std::string path,int flags,mode_t mode=0)262*38e8c45fSAndroid Build Coastguard Worker static int Open(std::string path, int flags, mode_t mode = 0) {
263*38e8c45fSAndroid Build Coastguard Worker     int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
264*38e8c45fSAndroid Build Coastguard Worker     if (fd == -1) {
265*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
266*38e8c45fSAndroid Build Coastguard Worker     }
267*38e8c45fSAndroid Build Coastguard Worker     return fd;
268*38e8c45fSAndroid Build Coastguard Worker }
269*38e8c45fSAndroid Build Coastguard Worker 
OpenForWrite(std::string path)270*38e8c45fSAndroid Build Coastguard Worker static int OpenForWrite(std::string path) {
271*38e8c45fSAndroid Build Coastguard Worker     return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
272*38e8c45fSAndroid Build Coastguard Worker                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
273*38e8c45fSAndroid Build Coastguard Worker }
274*38e8c45fSAndroid Build Coastguard Worker 
OpenForRead(std::string path)275*38e8c45fSAndroid Build Coastguard Worker static int OpenForRead(std::string path) {
276*38e8c45fSAndroid Build Coastguard Worker     return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
277*38e8c45fSAndroid Build Coastguard Worker }
278*38e8c45fSAndroid Build Coastguard Worker 
CopyFile(int in_fd,int out_fd)279*38e8c45fSAndroid Build Coastguard Worker bool CopyFile(int in_fd, int out_fd) {
280*38e8c45fSAndroid Build Coastguard Worker     char buf[4096];
281*38e8c45fSAndroid Build Coastguard Worker     ssize_t byte_count;
282*38e8c45fSAndroid Build Coastguard Worker     while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
283*38e8c45fSAndroid Build Coastguard Worker         if (!android::base::WriteFully(out_fd, buf, byte_count)) {
284*38e8c45fSAndroid Build Coastguard Worker             return false;
285*38e8c45fSAndroid Build Coastguard Worker         }
286*38e8c45fSAndroid Build Coastguard Worker     }
287*38e8c45fSAndroid Build Coastguard Worker     return (byte_count != -1);
288*38e8c45fSAndroid Build Coastguard Worker }
289*38e8c45fSAndroid Build Coastguard Worker 
CopyFileToFd(const std::string & input_file,int out_fd)290*38e8c45fSAndroid Build Coastguard Worker static bool CopyFileToFd(const std::string& input_file, int out_fd) {
291*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
292*38e8c45fSAndroid Build Coastguard Worker 
293*38e8c45fSAndroid Build Coastguard Worker     // Obtain a handle to the source file.
294*38e8c45fSAndroid Build Coastguard Worker     android::base::unique_fd in_fd(OpenForRead(input_file));
295*38e8c45fSAndroid Build Coastguard Worker     if (out_fd != -1 && in_fd.get() != -1) {
296*38e8c45fSAndroid Build Coastguard Worker         if (CopyFile(in_fd.get(), out_fd)) {
297*38e8c45fSAndroid Build Coastguard Worker             return true;
298*38e8c45fSAndroid Build Coastguard Worker         }
299*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to copy file: %s\n", strerror(errno));
300*38e8c45fSAndroid Build Coastguard Worker     }
301*38e8c45fSAndroid Build Coastguard Worker     return false;
302*38e8c45fSAndroid Build Coastguard Worker }
303*38e8c45fSAndroid Build Coastguard Worker 
UnlinkAndLogOnError(const std::string & file)304*38e8c45fSAndroid Build Coastguard Worker static bool UnlinkAndLogOnError(const std::string& file) {
305*38e8c45fSAndroid Build Coastguard Worker     if (file.empty()) {
306*38e8c45fSAndroid Build Coastguard Worker         return false;
307*38e8c45fSAndroid Build Coastguard Worker     }
308*38e8c45fSAndroid Build Coastguard Worker     if (unlink(file.c_str())) {
309*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
310*38e8c45fSAndroid Build Coastguard Worker         return false;
311*38e8c45fSAndroid Build Coastguard Worker     }
312*38e8c45fSAndroid Build Coastguard Worker     return true;
313*38e8c45fSAndroid Build Coastguard Worker }
314*38e8c45fSAndroid Build Coastguard Worker 
GetModuleMetadataVersion()315*38e8c45fSAndroid Build Coastguard Worker int64_t GetModuleMetadataVersion() {
316*38e8c45fSAndroid Build Coastguard Worker     auto binder = defaultServiceManager()->getService(android::String16("package_native"));
317*38e8c45fSAndroid Build Coastguard Worker     if (binder == nullptr) {
318*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to retrieve package_native service");
319*38e8c45fSAndroid Build Coastguard Worker         return 0L;
320*38e8c45fSAndroid Build Coastguard Worker     }
321*38e8c45fSAndroid Build Coastguard Worker     auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
322*38e8c45fSAndroid Build Coastguard Worker     std::string package_name;
323*38e8c45fSAndroid Build Coastguard Worker     auto status = package_service->getModuleMetadataPackageName(&package_name);
324*38e8c45fSAndroid Build Coastguard Worker     if (!status.isOk()) {
325*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
326*38e8c45fSAndroid Build Coastguard Worker         return 0L;
327*38e8c45fSAndroid Build Coastguard Worker     }
328*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Module metadata package name: %s\n", package_name.c_str());
329*38e8c45fSAndroid Build Coastguard Worker     int64_t version_code;
330*38e8c45fSAndroid Build Coastguard Worker     status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
331*38e8c45fSAndroid Build Coastguard Worker                                                        &version_code);
332*38e8c45fSAndroid Build Coastguard Worker     if (!status.isOk()) {
333*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
334*38e8c45fSAndroid Build Coastguard Worker         return 0L;
335*38e8c45fSAndroid Build Coastguard Worker     }
336*38e8c45fSAndroid Build Coastguard Worker     return version_code;
337*38e8c45fSAndroid Build Coastguard Worker }
338*38e8c45fSAndroid Build Coastguard Worker 
PathExists(const std::string & path)339*38e8c45fSAndroid Build Coastguard Worker static bool PathExists(const std::string& path) {
340*38e8c45fSAndroid Build Coastguard Worker   struct stat sb;
341*38e8c45fSAndroid Build Coastguard Worker   return stat(path.c_str(), &sb) == 0;
342*38e8c45fSAndroid Build Coastguard Worker }
343*38e8c45fSAndroid Build Coastguard Worker 
CopyFileToFile(const std::string & input_file,const std::string & output_file)344*38e8c45fSAndroid Build Coastguard Worker static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
345*38e8c45fSAndroid Build Coastguard Worker     if (input_file == output_file) {
346*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
347*38e8c45fSAndroid Build Coastguard Worker                output_file.c_str());
348*38e8c45fSAndroid Build Coastguard Worker         return false;
349*38e8c45fSAndroid Build Coastguard Worker     }
350*38e8c45fSAndroid Build Coastguard Worker     else if (PathExists(output_file)) {
351*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
352*38e8c45fSAndroid Build Coastguard Worker         return false;
353*38e8c45fSAndroid Build Coastguard Worker     }
354*38e8c45fSAndroid Build Coastguard Worker 
355*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
356*38e8c45fSAndroid Build Coastguard Worker     android::base::unique_fd out_fd(OpenForWrite(output_file));
357*38e8c45fSAndroid Build Coastguard Worker     return CopyFileToFd(input_file, out_fd.get());
358*38e8c45fSAndroid Build Coastguard Worker }
359*38e8c45fSAndroid Build Coastguard Worker 
360*38e8c45fSAndroid Build Coastguard Worker }  // namespace
361*38e8c45fSAndroid Build Coastguard Worker }  // namespace os
362*38e8c45fSAndroid Build Coastguard Worker }  // namespace android
363*38e8c45fSAndroid Build Coastguard Worker 
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,const CommandOptions & options=Dumpstate::DEFAULT_DUMPSYS,long dumpsysTimeoutMs=0,int out_fd=STDOUT_FILENO)364*38e8c45fSAndroid Build Coastguard Worker static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
365*38e8c45fSAndroid Build Coastguard Worker                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
366*38e8c45fSAndroid Build Coastguard Worker                        long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
367*38e8c45fSAndroid Build Coastguard Worker     return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
368*38e8c45fSAndroid Build Coastguard Worker }
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,int out_fd)369*38e8c45fSAndroid Build Coastguard Worker static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
370*38e8c45fSAndroid Build Coastguard Worker                        int out_fd) {
371*38e8c45fSAndroid Build Coastguard Worker     return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
372*38e8c45fSAndroid Build Coastguard Worker }
DumpFile(const std::string & title,const std::string & path)373*38e8c45fSAndroid Build Coastguard Worker static int DumpFile(const std::string& title, const std::string& path) {
374*38e8c45fSAndroid Build Coastguard Worker     return ds.DumpFile(title, path);
375*38e8c45fSAndroid Build Coastguard Worker }
376*38e8c45fSAndroid Build Coastguard Worker 
377*38e8c45fSAndroid Build Coastguard Worker // Relative directory (inside the zip) for all files copied as-is into the bugreport.
378*38e8c45fSAndroid Build Coastguard Worker static const std::string ZIP_ROOT_DIR = "FS";
379*38e8c45fSAndroid Build Coastguard Worker 
380*38e8c45fSAndroid Build Coastguard Worker static const std::string kProtoPath = "proto/";
381*38e8c45fSAndroid Build Coastguard Worker static const std::string kProtoExt = ".proto";
382*38e8c45fSAndroid Build Coastguard Worker static const std::string kDumpstateBoardFiles[] = {
383*38e8c45fSAndroid Build Coastguard Worker     "dumpstate_board.txt",
384*38e8c45fSAndroid Build Coastguard Worker     "dumpstate_board.bin"
385*38e8c45fSAndroid Build Coastguard Worker };
386*38e8c45fSAndroid Build Coastguard Worker static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
387*38e8c45fSAndroid Build Coastguard Worker 
388*38e8c45fSAndroid Build Coastguard Worker static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
389*38e8c45fSAndroid Build Coastguard Worker static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
390*38e8c45fSAndroid Build Coastguard Worker 
391*38e8c45fSAndroid Build Coastguard Worker static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
392*38e8c45fSAndroid Build Coastguard Worker 
393*38e8c45fSAndroid Build Coastguard Worker /*
394*38e8c45fSAndroid Build Coastguard Worker  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
395*38e8c45fSAndroid Build Coastguard Worker  * The returned vector is sorted by the mtimes of the dumps with descending
396*38e8c45fSAndroid Build Coastguard Worker  * order.
397*38e8c45fSAndroid Build Coastguard Worker  */
GetDumpFds(const std::string & dir_path,const std::string & file_prefix)398*38e8c45fSAndroid Build Coastguard Worker static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
399*38e8c45fSAndroid Build Coastguard Worker                                         const std::string& file_prefix) {
400*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
401*38e8c45fSAndroid Build Coastguard Worker 
402*38e8c45fSAndroid Build Coastguard Worker     if (dump_dir == nullptr) {
403*38e8c45fSAndroid Build Coastguard Worker         MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
404*38e8c45fSAndroid Build Coastguard Worker         return std::vector<DumpData>();
405*38e8c45fSAndroid Build Coastguard Worker     }
406*38e8c45fSAndroid Build Coastguard Worker 
407*38e8c45fSAndroid Build Coastguard Worker     std::vector<DumpData> dump_data;
408*38e8c45fSAndroid Build Coastguard Worker     struct dirent* entry = nullptr;
409*38e8c45fSAndroid Build Coastguard Worker     while ((entry = readdir(dump_dir.get()))) {
410*38e8c45fSAndroid Build Coastguard Worker         if (entry->d_type != DT_REG) {
411*38e8c45fSAndroid Build Coastguard Worker             continue;
412*38e8c45fSAndroid Build Coastguard Worker         }
413*38e8c45fSAndroid Build Coastguard Worker 
414*38e8c45fSAndroid Build Coastguard Worker         const std::string base_name(entry->d_name);
415*38e8c45fSAndroid Build Coastguard Worker         if (base_name.find(file_prefix) != 0) {
416*38e8c45fSAndroid Build Coastguard Worker             continue;
417*38e8c45fSAndroid Build Coastguard Worker         }
418*38e8c45fSAndroid Build Coastguard Worker 
419*38e8c45fSAndroid Build Coastguard Worker         const std::string abs_path = dir_path + base_name;
420*38e8c45fSAndroid Build Coastguard Worker         android::base::unique_fd fd(
421*38e8c45fSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
422*38e8c45fSAndroid Build Coastguard Worker         if (fd == -1) {
423*38e8c45fSAndroid Build Coastguard Worker             MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
424*38e8c45fSAndroid Build Coastguard Worker             break;
425*38e8c45fSAndroid Build Coastguard Worker         }
426*38e8c45fSAndroid Build Coastguard Worker 
427*38e8c45fSAndroid Build Coastguard Worker         struct stat st = {};
428*38e8c45fSAndroid Build Coastguard Worker         if (fstat(fd, &st) == -1) {
429*38e8c45fSAndroid Build Coastguard Worker             MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
430*38e8c45fSAndroid Build Coastguard Worker             continue;
431*38e8c45fSAndroid Build Coastguard Worker         }
432*38e8c45fSAndroid Build Coastguard Worker 
433*38e8c45fSAndroid Build Coastguard Worker         dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
434*38e8c45fSAndroid Build Coastguard Worker     }
435*38e8c45fSAndroid Build Coastguard Worker     if (!dump_data.empty()) {
436*38e8c45fSAndroid Build Coastguard Worker         std::sort(dump_data.begin(), dump_data.end(),
437*38e8c45fSAndroid Build Coastguard Worker             [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
438*38e8c45fSAndroid Build Coastguard Worker     }
439*38e8c45fSAndroid Build Coastguard Worker 
440*38e8c45fSAndroid Build Coastguard Worker     return dump_data;
441*38e8c45fSAndroid Build Coastguard Worker }
442*38e8c45fSAndroid Build Coastguard Worker 
AddDumps(const std::vector<DumpData>::const_iterator start,const std::vector<DumpData>::const_iterator end,const char * type_name,const bool add_to_zip)443*38e8c45fSAndroid Build Coastguard Worker static bool AddDumps(const std::vector<DumpData>::const_iterator start,
444*38e8c45fSAndroid Build Coastguard Worker                      const std::vector<DumpData>::const_iterator end,
445*38e8c45fSAndroid Build Coastguard Worker                      const char* type_name, const bool add_to_zip) {
446*38e8c45fSAndroid Build Coastguard Worker     bool dumped = false;
447*38e8c45fSAndroid Build Coastguard Worker     for (auto it = start; it != end; ++it) {
448*38e8c45fSAndroid Build Coastguard Worker         const std::string& name = it->name;
449*38e8c45fSAndroid Build Coastguard Worker         const int fd = it->fd;
450*38e8c45fSAndroid Build Coastguard Worker         dumped = true;
451*38e8c45fSAndroid Build Coastguard Worker 
452*38e8c45fSAndroid Build Coastguard Worker         // Seek to the beginning of the file before dumping any data. A given
453*38e8c45fSAndroid Build Coastguard Worker         // DumpData entry might be dumped multiple times in the report.
454*38e8c45fSAndroid Build Coastguard Worker         //
455*38e8c45fSAndroid Build Coastguard Worker         // For example, the most recent ANR entry is dumped to the body of the
456*38e8c45fSAndroid Build Coastguard Worker         // main entry and it also shows up as a separate entry in the bugreport
457*38e8c45fSAndroid Build Coastguard Worker         // ZIP file.
458*38e8c45fSAndroid Build Coastguard Worker         if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
459*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
460*38e8c45fSAndroid Build Coastguard Worker                    strerror(errno));
461*38e8c45fSAndroid Build Coastguard Worker         }
462*38e8c45fSAndroid Build Coastguard Worker 
463*38e8c45fSAndroid Build Coastguard Worker         if (add_to_zip) {
464*38e8c45fSAndroid Build Coastguard Worker             if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
465*38e8c45fSAndroid Build Coastguard Worker                 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
466*38e8c45fSAndroid Build Coastguard Worker             }
467*38e8c45fSAndroid Build Coastguard Worker         } else {
468*38e8c45fSAndroid Build Coastguard Worker             dump_file_from_fd(type_name, name.c_str(), fd);
469*38e8c45fSAndroid Build Coastguard Worker         }
470*38e8c45fSAndroid Build Coastguard Worker     }
471*38e8c45fSAndroid Build Coastguard Worker 
472*38e8c45fSAndroid Build Coastguard Worker     return dumped;
473*38e8c45fSAndroid Build Coastguard Worker }
474*38e8c45fSAndroid Build Coastguard Worker 
475*38e8c45fSAndroid Build Coastguard Worker // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)476*38e8c45fSAndroid Build Coastguard Worker void do_mountinfo(int pid, const char* name __attribute__((unused))) {
477*38e8c45fSAndroid Build Coastguard Worker     char path[PATH_MAX];
478*38e8c45fSAndroid Build Coastguard Worker 
479*38e8c45fSAndroid Build Coastguard Worker     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
480*38e8c45fSAndroid Build Coastguard Worker     // are added.
481*38e8c45fSAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
482*38e8c45fSAndroid Build Coastguard Worker     char linkname[PATH_MAX];
483*38e8c45fSAndroid Build Coastguard Worker     ssize_t r = readlink(path, linkname, PATH_MAX);
484*38e8c45fSAndroid Build Coastguard Worker     if (r == -1) {
485*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
486*38e8c45fSAndroid Build Coastguard Worker         return;
487*38e8c45fSAndroid Build Coastguard Worker     }
488*38e8c45fSAndroid Build Coastguard Worker     linkname[r] = '\0';
489*38e8c45fSAndroid Build Coastguard Worker 
490*38e8c45fSAndroid Build Coastguard Worker     if (mount_points.find(linkname) == mount_points.end()) {
491*38e8c45fSAndroid Build Coastguard Worker         // First time this mount point was found: add it
492*38e8c45fSAndroid Build Coastguard Worker         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
493*38e8c45fSAndroid Build Coastguard Worker         if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
494*38e8c45fSAndroid Build Coastguard Worker             mount_points.insert(linkname);
495*38e8c45fSAndroid Build Coastguard Worker         } else {
496*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
497*38e8c45fSAndroid Build Coastguard Worker         }
498*38e8c45fSAndroid Build Coastguard Worker     }
499*38e8c45fSAndroid Build Coastguard Worker }
500*38e8c45fSAndroid Build Coastguard Worker 
add_mountinfo()501*38e8c45fSAndroid Build Coastguard Worker void add_mountinfo() {
502*38e8c45fSAndroid Build Coastguard Worker     std::string title = "MOUNT INFO";
503*38e8c45fSAndroid Build Coastguard Worker     mount_points.clear();
504*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title, true);
505*38e8c45fSAndroid Build Coastguard Worker     for_each_pid(do_mountinfo, nullptr);
506*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
507*38e8c45fSAndroid Build Coastguard Worker }
508*38e8c45fSAndroid Build Coastguard Worker 
dump_dev_files(const char * title,const char * driverpath,const char * filename)509*38e8c45fSAndroid Build Coastguard Worker static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
510*38e8c45fSAndroid Build Coastguard Worker {
511*38e8c45fSAndroid Build Coastguard Worker     DIR *d;
512*38e8c45fSAndroid Build Coastguard Worker     struct dirent *de;
513*38e8c45fSAndroid Build Coastguard Worker     char path[PATH_MAX];
514*38e8c45fSAndroid Build Coastguard Worker 
515*38e8c45fSAndroid Build Coastguard Worker     d = opendir(driverpath);
516*38e8c45fSAndroid Build Coastguard Worker     if (d == nullptr) {
517*38e8c45fSAndroid Build Coastguard Worker         return;
518*38e8c45fSAndroid Build Coastguard Worker     }
519*38e8c45fSAndroid Build Coastguard Worker 
520*38e8c45fSAndroid Build Coastguard Worker     while ((de = readdir(d))) {
521*38e8c45fSAndroid Build Coastguard Worker         if (de->d_type != DT_LNK) {
522*38e8c45fSAndroid Build Coastguard Worker             continue;
523*38e8c45fSAndroid Build Coastguard Worker         }
524*38e8c45fSAndroid Build Coastguard Worker         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
525*38e8c45fSAndroid Build Coastguard Worker         DumpFile(title, path);
526*38e8c45fSAndroid Build Coastguard Worker     }
527*38e8c45fSAndroid Build Coastguard Worker 
528*38e8c45fSAndroid Build Coastguard Worker     closedir(d);
529*38e8c45fSAndroid Build Coastguard Worker }
530*38e8c45fSAndroid Build Coastguard Worker 
skip_not_stat(const char * path)531*38e8c45fSAndroid Build Coastguard Worker static bool skip_not_stat(const char *path) {
532*38e8c45fSAndroid Build Coastguard Worker     static const char stat[] = "/stat";
533*38e8c45fSAndroid Build Coastguard Worker     size_t len = strlen(path);
534*38e8c45fSAndroid Build Coastguard Worker     if (path[len - 1] == '/') { /* Directory? */
535*38e8c45fSAndroid Build Coastguard Worker         return false;
536*38e8c45fSAndroid Build Coastguard Worker     }
537*38e8c45fSAndroid Build Coastguard Worker     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
538*38e8c45fSAndroid Build Coastguard Worker }
539*38e8c45fSAndroid Build Coastguard Worker 
skip_wtf_strictmode(const char * path)540*38e8c45fSAndroid Build Coastguard Worker static bool skip_wtf_strictmode(const char *path) {
541*38e8c45fSAndroid Build Coastguard Worker     if (strstr(path, "_wtf")) {
542*38e8c45fSAndroid Build Coastguard Worker         return true;
543*38e8c45fSAndroid Build Coastguard Worker     } else if (strstr(path, "_strictmode")) {
544*38e8c45fSAndroid Build Coastguard Worker         return true;
545*38e8c45fSAndroid Build Coastguard Worker     }
546*38e8c45fSAndroid Build Coastguard Worker     return false;
547*38e8c45fSAndroid Build Coastguard Worker }
548*38e8c45fSAndroid Build Coastguard Worker 
skip_none(const char * path)549*38e8c45fSAndroid Build Coastguard Worker static bool skip_none(const char* path __attribute__((unused))) {
550*38e8c45fSAndroid Build Coastguard Worker     return false;
551*38e8c45fSAndroid Build Coastguard Worker }
552*38e8c45fSAndroid Build Coastguard Worker 
553*38e8c45fSAndroid Build Coastguard Worker unsigned long worst_write_perf = 20000; /* in KB/s */
554*38e8c45fSAndroid Build Coastguard Worker 
555*38e8c45fSAndroid Build Coastguard Worker //
556*38e8c45fSAndroid Build Coastguard Worker //  stat offsets
557*38e8c45fSAndroid Build Coastguard Worker // Name            units         description
558*38e8c45fSAndroid Build Coastguard Worker // ----            -----         -----------
559*38e8c45fSAndroid Build Coastguard Worker // read I/Os       requests      number of read I/Os processed
560*38e8c45fSAndroid Build Coastguard Worker #define __STAT_READ_IOS      0
561*38e8c45fSAndroid Build Coastguard Worker // read merges     requests      number of read I/Os merged with in-queue I/O
562*38e8c45fSAndroid Build Coastguard Worker #define __STAT_READ_MERGES   1
563*38e8c45fSAndroid Build Coastguard Worker // read sectors    sectors       number of sectors read
564*38e8c45fSAndroid Build Coastguard Worker #define __STAT_READ_SECTORS  2
565*38e8c45fSAndroid Build Coastguard Worker // read ticks      milliseconds  total wait time for read requests
566*38e8c45fSAndroid Build Coastguard Worker #define __STAT_READ_TICKS    3
567*38e8c45fSAndroid Build Coastguard Worker // write I/Os      requests      number of write I/Os processed
568*38e8c45fSAndroid Build Coastguard Worker #define __STAT_WRITE_IOS     4
569*38e8c45fSAndroid Build Coastguard Worker // write merges    requests      number of write I/Os merged with in-queue I/O
570*38e8c45fSAndroid Build Coastguard Worker #define __STAT_WRITE_MERGES  5
571*38e8c45fSAndroid Build Coastguard Worker // write sectors   sectors       number of sectors written
572*38e8c45fSAndroid Build Coastguard Worker #define __STAT_WRITE_SECTORS 6
573*38e8c45fSAndroid Build Coastguard Worker // write ticks     milliseconds  total wait time for write requests
574*38e8c45fSAndroid Build Coastguard Worker #define __STAT_WRITE_TICKS   7
575*38e8c45fSAndroid Build Coastguard Worker // in_flight       requests      number of I/Os currently in flight
576*38e8c45fSAndroid Build Coastguard Worker #define __STAT_IN_FLIGHT     8
577*38e8c45fSAndroid Build Coastguard Worker // io_ticks        milliseconds  total time this block device has been active
578*38e8c45fSAndroid Build Coastguard Worker #define __STAT_IO_TICKS      9
579*38e8c45fSAndroid Build Coastguard Worker // time_in_queue   milliseconds  total wait time for all requests
580*38e8c45fSAndroid Build Coastguard Worker #define __STAT_IN_QUEUE     10
581*38e8c45fSAndroid Build Coastguard Worker #define __STAT_NUMBER_FIELD 11
582*38e8c45fSAndroid Build Coastguard Worker //
583*38e8c45fSAndroid Build Coastguard Worker // read I/Os, write I/Os
584*38e8c45fSAndroid Build Coastguard Worker // =====================
585*38e8c45fSAndroid Build Coastguard Worker //
586*38e8c45fSAndroid Build Coastguard Worker // These values increment when an I/O request completes.
587*38e8c45fSAndroid Build Coastguard Worker //
588*38e8c45fSAndroid Build Coastguard Worker // read merges, write merges
589*38e8c45fSAndroid Build Coastguard Worker // =========================
590*38e8c45fSAndroid Build Coastguard Worker //
591*38e8c45fSAndroid Build Coastguard Worker // These values increment when an I/O request is merged with an
592*38e8c45fSAndroid Build Coastguard Worker // already-queued I/O request.
593*38e8c45fSAndroid Build Coastguard Worker //
594*38e8c45fSAndroid Build Coastguard Worker // read sectors, write sectors
595*38e8c45fSAndroid Build Coastguard Worker // ===========================
596*38e8c45fSAndroid Build Coastguard Worker //
597*38e8c45fSAndroid Build Coastguard Worker // These values count the number of sectors read from or written to this
598*38e8c45fSAndroid Build Coastguard Worker // block device.  The "sectors" in question are the standard UNIX 512-byte
599*38e8c45fSAndroid Build Coastguard Worker // sectors, not any device- or filesystem-specific block size.  The
600*38e8c45fSAndroid Build Coastguard Worker // counters are incremented when the I/O completes.
601*38e8c45fSAndroid Build Coastguard Worker #define SECTOR_SIZE 512
602*38e8c45fSAndroid Build Coastguard Worker //
603*38e8c45fSAndroid Build Coastguard Worker // read ticks, write ticks
604*38e8c45fSAndroid Build Coastguard Worker // =======================
605*38e8c45fSAndroid Build Coastguard Worker //
606*38e8c45fSAndroid Build Coastguard Worker // These values count the number of milliseconds that I/O requests have
607*38e8c45fSAndroid Build Coastguard Worker // waited on this block device.  If there are multiple I/O requests waiting,
608*38e8c45fSAndroid Build Coastguard Worker // these values will increase at a rate greater than 1000/second; for
609*38e8c45fSAndroid Build Coastguard Worker // example, if 60 read requests wait for an average of 30 ms, the read_ticks
610*38e8c45fSAndroid Build Coastguard Worker // field will increase by 60*30 = 1800.
611*38e8c45fSAndroid Build Coastguard Worker //
612*38e8c45fSAndroid Build Coastguard Worker // in_flight
613*38e8c45fSAndroid Build Coastguard Worker // =========
614*38e8c45fSAndroid Build Coastguard Worker //
615*38e8c45fSAndroid Build Coastguard Worker // This value counts the number of I/O requests that have been issued to
616*38e8c45fSAndroid Build Coastguard Worker // the device driver but have not yet completed.  It does not include I/O
617*38e8c45fSAndroid Build Coastguard Worker // requests that are in the queue but not yet issued to the device driver.
618*38e8c45fSAndroid Build Coastguard Worker //
619*38e8c45fSAndroid Build Coastguard Worker // io_ticks
620*38e8c45fSAndroid Build Coastguard Worker // ========
621*38e8c45fSAndroid Build Coastguard Worker //
622*38e8c45fSAndroid Build Coastguard Worker // This value counts the number of milliseconds during which the device has
623*38e8c45fSAndroid Build Coastguard Worker // had I/O requests queued.
624*38e8c45fSAndroid Build Coastguard Worker //
625*38e8c45fSAndroid Build Coastguard Worker // time_in_queue
626*38e8c45fSAndroid Build Coastguard Worker // =============
627*38e8c45fSAndroid Build Coastguard Worker //
628*38e8c45fSAndroid Build Coastguard Worker // This value counts the number of milliseconds that I/O requests have waited
629*38e8c45fSAndroid Build Coastguard Worker // on this block device.  If there are multiple I/O requests waiting, this
630*38e8c45fSAndroid Build Coastguard Worker // value will increase as the product of the number of milliseconds times the
631*38e8c45fSAndroid Build Coastguard Worker // number of requests waiting (see "read ticks" above for an example).
632*38e8c45fSAndroid Build Coastguard Worker #define S_TO_MS 1000
633*38e8c45fSAndroid Build Coastguard Worker //
634*38e8c45fSAndroid Build Coastguard Worker 
dump_stat_from_fd(const char * title __unused,const char * path,int fd)635*38e8c45fSAndroid Build Coastguard Worker static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
636*38e8c45fSAndroid Build Coastguard Worker     unsigned long long fields[__STAT_NUMBER_FIELD];
637*38e8c45fSAndroid Build Coastguard Worker     bool z;
638*38e8c45fSAndroid Build Coastguard Worker     char *cp, *buffer = nullptr;
639*38e8c45fSAndroid Build Coastguard Worker     size_t i = 0;
640*38e8c45fSAndroid Build Coastguard Worker     FILE *fp = fdopen(dup(fd), "rb");
641*38e8c45fSAndroid Build Coastguard Worker     getline(&buffer, &i, fp);
642*38e8c45fSAndroid Build Coastguard Worker     fclose(fp);
643*38e8c45fSAndroid Build Coastguard Worker     if (!buffer) {
644*38e8c45fSAndroid Build Coastguard Worker         return -errno;
645*38e8c45fSAndroid Build Coastguard Worker     }
646*38e8c45fSAndroid Build Coastguard Worker     i = strlen(buffer);
647*38e8c45fSAndroid Build Coastguard Worker     while ((i > 0) && (buffer[i - 1] == '\n')) {
648*38e8c45fSAndroid Build Coastguard Worker         buffer[--i] = '\0';
649*38e8c45fSAndroid Build Coastguard Worker     }
650*38e8c45fSAndroid Build Coastguard Worker     if (!*buffer) {
651*38e8c45fSAndroid Build Coastguard Worker         free(buffer);
652*38e8c45fSAndroid Build Coastguard Worker         return 0;
653*38e8c45fSAndroid Build Coastguard Worker     }
654*38e8c45fSAndroid Build Coastguard Worker     z = true;
655*38e8c45fSAndroid Build Coastguard Worker     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
656*38e8c45fSAndroid Build Coastguard Worker         fields[i] = strtoull(cp, &cp, 10);
657*38e8c45fSAndroid Build Coastguard Worker         if (fields[i] != 0) {
658*38e8c45fSAndroid Build Coastguard Worker             z = false;
659*38e8c45fSAndroid Build Coastguard Worker         }
660*38e8c45fSAndroid Build Coastguard Worker     }
661*38e8c45fSAndroid Build Coastguard Worker     if (z) { /* never accessed */
662*38e8c45fSAndroid Build Coastguard Worker         free(buffer);
663*38e8c45fSAndroid Build Coastguard Worker         return 0;
664*38e8c45fSAndroid Build Coastguard Worker     }
665*38e8c45fSAndroid Build Coastguard Worker 
666*38e8c45fSAndroid Build Coastguard Worker     if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
667*38e8c45fSAndroid Build Coastguard Worker         path += sizeof(BLK_DEV_SYS_DIR) - 1;
668*38e8c45fSAndroid Build Coastguard Worker     }
669*38e8c45fSAndroid Build Coastguard Worker 
670*38e8c45fSAndroid Build Coastguard Worker     printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
671*38e8c45fSAndroid Build Coastguard Worker            "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
672*38e8c45fSAndroid Build Coastguard Worker            "W-wait", "in-fli", "activ", "T-wait", path, buffer);
673*38e8c45fSAndroid Build Coastguard Worker     free(buffer);
674*38e8c45fSAndroid Build Coastguard Worker 
675*38e8c45fSAndroid Build Coastguard Worker     if (fields[__STAT_IO_TICKS]) {
676*38e8c45fSAndroid Build Coastguard Worker         unsigned long read_perf = 0;
677*38e8c45fSAndroid Build Coastguard Worker         unsigned long read_ios = 0;
678*38e8c45fSAndroid Build Coastguard Worker         if (fields[__STAT_READ_TICKS]) {
679*38e8c45fSAndroid Build Coastguard Worker             unsigned long long divisor = fields[__STAT_READ_TICKS]
680*38e8c45fSAndroid Build Coastguard Worker                                        * fields[__STAT_IO_TICKS];
681*38e8c45fSAndroid Build Coastguard Worker             read_perf = ((unsigned long long)SECTOR_SIZE
682*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_READ_SECTORS]
683*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684*38e8c45fSAndroid Build Coastguard Worker                                         / divisor;
685*38e8c45fSAndroid Build Coastguard Worker             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
686*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
687*38e8c45fSAndroid Build Coastguard Worker                                         / divisor;
688*38e8c45fSAndroid Build Coastguard Worker         }
689*38e8c45fSAndroid Build Coastguard Worker 
690*38e8c45fSAndroid Build Coastguard Worker         unsigned long write_perf = 0;
691*38e8c45fSAndroid Build Coastguard Worker         unsigned long write_ios = 0;
692*38e8c45fSAndroid Build Coastguard Worker         if (fields[__STAT_WRITE_TICKS]) {
693*38e8c45fSAndroid Build Coastguard Worker             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
694*38e8c45fSAndroid Build Coastguard Worker                                        * fields[__STAT_IO_TICKS];
695*38e8c45fSAndroid Build Coastguard Worker             write_perf = ((unsigned long long)SECTOR_SIZE
696*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_WRITE_SECTORS]
697*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
698*38e8c45fSAndroid Build Coastguard Worker                                         / divisor;
699*38e8c45fSAndroid Build Coastguard Worker             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
700*38e8c45fSAndroid Build Coastguard Worker                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
701*38e8c45fSAndroid Build Coastguard Worker                                         / divisor;
702*38e8c45fSAndroid Build Coastguard Worker         }
703*38e8c45fSAndroid Build Coastguard Worker 
704*38e8c45fSAndroid Build Coastguard Worker         unsigned queue = (fields[__STAT_IN_QUEUE]
705*38e8c45fSAndroid Build Coastguard Worker                              + (fields[__STAT_IO_TICKS] >> 1))
706*38e8c45fSAndroid Build Coastguard Worker                                  / fields[__STAT_IO_TICKS];
707*38e8c45fSAndroid Build Coastguard Worker 
708*38e8c45fSAndroid Build Coastguard Worker         if (!write_perf && !write_ios) {
709*38e8c45fSAndroid Build Coastguard Worker             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
710*38e8c45fSAndroid Build Coastguard Worker         } else {
711*38e8c45fSAndroid Build Coastguard Worker             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
712*38e8c45fSAndroid Build Coastguard Worker                    read_ios, write_perf, write_ios, queue);
713*38e8c45fSAndroid Build Coastguard Worker         }
714*38e8c45fSAndroid Build Coastguard Worker 
715*38e8c45fSAndroid Build Coastguard Worker         /* bugreport timeout factor adjustment */
716*38e8c45fSAndroid Build Coastguard Worker         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
717*38e8c45fSAndroid Build Coastguard Worker             worst_write_perf = write_perf;
718*38e8c45fSAndroid Build Coastguard Worker         }
719*38e8c45fSAndroid Build Coastguard Worker     }
720*38e8c45fSAndroid Build Coastguard Worker     return 0;
721*38e8c45fSAndroid Build Coastguard Worker }
722*38e8c45fSAndroid Build Coastguard Worker 
723*38e8c45fSAndroid Build Coastguard Worker static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
724*38e8c45fSAndroid Build Coastguard Worker 
725*38e8c45fSAndroid Build Coastguard Worker // Returns the actual readable size of the given buffer or -1 on error.
logcat_buffer_readable_size(const std::string & buffer)726*38e8c45fSAndroid Build Coastguard Worker static long logcat_buffer_readable_size(const std::string& buffer) {
727*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
728*38e8c45fSAndroid Build Coastguard Worker         android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
729*38e8c45fSAndroid Build Coastguard Worker     auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
730*38e8c45fSAndroid Build Coastguard Worker 
731*38e8c45fSAndroid Build Coastguard Worker     return android_logger_get_log_readable_size(logger);
732*38e8c45fSAndroid Build Coastguard Worker }
733*38e8c45fSAndroid Build Coastguard Worker 
734*38e8c45fSAndroid Build Coastguard Worker // Returns timeout in ms to read a list of buffers.
logcat_timeout(const std::vector<std::string> & buffers)735*38e8c45fSAndroid Build Coastguard Worker static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
736*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms = 0;
737*38e8c45fSAndroid Build Coastguard Worker     for (const auto& buffer : buffers) {
738*38e8c45fSAndroid Build Coastguard Worker         long readable_size = logcat_buffer_readable_size(buffer);
739*38e8c45fSAndroid Build Coastguard Worker         if (readable_size > 0) {
740*38e8c45fSAndroid Build Coastguard Worker             // Engineering margin is ten-fold our guess.
741*38e8c45fSAndroid Build Coastguard Worker             timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
742*38e8c45fSAndroid Build Coastguard Worker         }
743*38e8c45fSAndroid Build Coastguard Worker     }
744*38e8c45fSAndroid Build Coastguard Worker     return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
745*38e8c45fSAndroid Build Coastguard Worker }
746*38e8c45fSAndroid Build Coastguard Worker 
747*38e8c45fSAndroid Build Coastguard Worker // Opens a socket and returns its file descriptor.
748*38e8c45fSAndroid Build Coastguard Worker static int open_socket(const char* service);
749*38e8c45fSAndroid Build Coastguard Worker 
ConsentCallback()750*38e8c45fSAndroid Build Coastguard Worker Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
751*38e8c45fSAndroid Build Coastguard Worker }
752*38e8c45fSAndroid Build Coastguard Worker 
onReportApproved()753*38e8c45fSAndroid Build Coastguard Worker android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
754*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
755*38e8c45fSAndroid Build Coastguard Worker     result_ = APPROVED;
756*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("User approved consent to share bugreport\n");
757*38e8c45fSAndroid Build Coastguard Worker 
758*38e8c45fSAndroid Build Coastguard Worker     // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
759*38e8c45fSAndroid Build Coastguard Worker     // consent is granted.
760*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->is_screenshot_copied) {
761*38e8c45fSAndroid Build Coastguard Worker         return android::binder::Status::ok();
762*38e8c45fSAndroid Build Coastguard Worker     }
763*38e8c45fSAndroid Build Coastguard Worker 
764*38e8c45fSAndroid Build Coastguard Worker     if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
765*38e8c45fSAndroid Build Coastguard Worker         !ds.do_early_screenshot_) {
766*38e8c45fSAndroid Build Coastguard Worker         return android::binder::Status::ok();
767*38e8c45fSAndroid Build Coastguard Worker     }
768*38e8c45fSAndroid Build Coastguard Worker 
769*38e8c45fSAndroid Build Coastguard Worker     bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
770*38e8c45fSAndroid Build Coastguard Worker                                                     ds.options_->screenshot_fd.get());
771*38e8c45fSAndroid Build Coastguard Worker     if (copy_succeeded) {
772*38e8c45fSAndroid Build Coastguard Worker         android::os::UnlinkAndLogOnError(ds.screenshot_path_);
773*38e8c45fSAndroid Build Coastguard Worker     } else {
774*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to copy screenshot to a permanent file.\n");
775*38e8c45fSAndroid Build Coastguard Worker         copy_succeeded = android::os::CopyFileToFd(DEFAULT_SCREENSHOT_PATH,
776*38e8c45fSAndroid Build Coastguard Worker                                                            ds.options_->screenshot_fd.get());
777*38e8c45fSAndroid Build Coastguard Worker     }
778*38e8c45fSAndroid Build Coastguard Worker     ds.options_->is_screenshot_copied = copy_succeeded;
779*38e8c45fSAndroid Build Coastguard Worker     return android::binder::Status::ok();
780*38e8c45fSAndroid Build Coastguard Worker }
781*38e8c45fSAndroid Build Coastguard Worker 
onReportDenied()782*38e8c45fSAndroid Build Coastguard Worker android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
783*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
784*38e8c45fSAndroid Build Coastguard Worker     result_ = DENIED;
785*38e8c45fSAndroid Build Coastguard Worker     MYLOGW("User denied consent to share bugreport\n");
786*38e8c45fSAndroid Build Coastguard Worker     return android::binder::Status::ok();
787*38e8c45fSAndroid Build Coastguard Worker }
788*38e8c45fSAndroid Build Coastguard Worker 
getResult()789*38e8c45fSAndroid Build Coastguard Worker UserConsentResult Dumpstate::ConsentCallback::getResult() {
790*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
791*38e8c45fSAndroid Build Coastguard Worker     return result_;
792*38e8c45fSAndroid Build Coastguard Worker }
793*38e8c45fSAndroid Build Coastguard Worker 
getElapsedTimeMs() const794*38e8c45fSAndroid Build Coastguard Worker uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
795*38e8c45fSAndroid Build Coastguard Worker     return (Nanotime() - start_time_) / NANOS_PER_MILLI;
796*38e8c45fSAndroid Build Coastguard Worker }
797*38e8c45fSAndroid Build Coastguard Worker 
PrintHeader() const798*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::PrintHeader() const {
799*38e8c45fSAndroid Build Coastguard Worker     std::string build, fingerprint, radio, bootloader, network, sdkversion;
800*38e8c45fSAndroid Build Coastguard Worker     char date[80];
801*38e8c45fSAndroid Build Coastguard Worker 
802*38e8c45fSAndroid Build Coastguard Worker     build = android::base::GetProperty("ro.build.display.id", "(unknown)");
803*38e8c45fSAndroid Build Coastguard Worker     fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
804*38e8c45fSAndroid Build Coastguard Worker     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
805*38e8c45fSAndroid Build Coastguard Worker     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
806*38e8c45fSAndroid Build Coastguard Worker     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
807*38e8c45fSAndroid Build Coastguard Worker     sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
808*38e8c45fSAndroid Build Coastguard Worker     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
809*38e8c45fSAndroid Build Coastguard Worker 
810*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
811*38e8c45fSAndroid Build Coastguard Worker     printf("== dumpstate: %s\n", date);
812*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
813*38e8c45fSAndroid Build Coastguard Worker 
814*38e8c45fSAndroid Build Coastguard Worker     printf("\n");
815*38e8c45fSAndroid Build Coastguard Worker     printf("Build: %s\n", build.c_str());
816*38e8c45fSAndroid Build Coastguard Worker     // NOTE: fingerprint entry format is important for other tools.
817*38e8c45fSAndroid Build Coastguard Worker     printf("Build fingerprint: '%s'\n", fingerprint.c_str());
818*38e8c45fSAndroid Build Coastguard Worker     printf("Bootloader: %s\n", bootloader.c_str());
819*38e8c45fSAndroid Build Coastguard Worker     printf("Radio: %s\n", radio.c_str());
820*38e8c45fSAndroid Build Coastguard Worker     printf("Network: %s\n", network.c_str());
821*38e8c45fSAndroid Build Coastguard Worker     int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
822*38e8c45fSAndroid Build Coastguard Worker     if (module_metadata_version != 0) {
823*38e8c45fSAndroid Build Coastguard Worker         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
824*38e8c45fSAndroid Build Coastguard Worker     }
825*38e8c45fSAndroid Build Coastguard Worker     printf("Android SDK version: %s\n", sdkversion.c_str());
826*38e8c45fSAndroid Build Coastguard Worker     printf("SDK extensions: ");
827*38e8c45fSAndroid Build Coastguard Worker     RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
828*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(1).Always().DropRoot().Build());
829*38e8c45fSAndroid Build Coastguard Worker 
830*38e8c45fSAndroid Build Coastguard Worker     printf("Kernel: ");
831*38e8c45fSAndroid Build Coastguard Worker     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
832*38e8c45fSAndroid Build Coastguard Worker     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
833*38e8c45fSAndroid Build Coastguard Worker     printf("Bootconfig: ");
834*38e8c45fSAndroid Build Coastguard Worker     DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
835*38e8c45fSAndroid Build Coastguard Worker     printf("Uptime: ");
836*38e8c45fSAndroid Build Coastguard Worker     RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
837*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(1).Always().Build());
838*38e8c45fSAndroid Build Coastguard Worker     printf("Bugreport format version: %s\n", version_.c_str());
839*38e8c45fSAndroid Build Coastguard Worker     printf(
840*38e8c45fSAndroid Build Coastguard Worker         "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
841*38e8c45fSAndroid Build Coastguard Worker         "bugreport_mode=%s\n",
842*38e8c45fSAndroid Build Coastguard Worker         id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
843*38e8c45fSAndroid Build Coastguard Worker         PropertiesHelper::IsStrictRun(), options_->args.c_str(),
844*38e8c45fSAndroid Build Coastguard Worker         options_->bugreport_mode_string.c_str());
845*38e8c45fSAndroid Build Coastguard Worker     printf("\n");
846*38e8c45fSAndroid Build Coastguard Worker }
847*38e8c45fSAndroid Build Coastguard Worker 
848*38e8c45fSAndroid Build Coastguard Worker // List of file extensions that can cause a zip file attachment to be rejected by some email
849*38e8c45fSAndroid Build Coastguard Worker // service providers.
850*38e8c45fSAndroid Build Coastguard Worker static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
851*38e8c45fSAndroid Build Coastguard Worker       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
852*38e8c45fSAndroid Build Coastguard Worker       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
853*38e8c45fSAndroid Build Coastguard Worker       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
854*38e8c45fSAndroid Build Coastguard Worker };
855*38e8c45fSAndroid Build Coastguard Worker 
AddZipEntryFromFd(const std::string & entry_name,int fd,std::chrono::milliseconds timeout=0ms)856*38e8c45fSAndroid Build Coastguard Worker status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
857*38e8c45fSAndroid Build Coastguard Worker                                       std::chrono::milliseconds timeout = 0ms) {
858*38e8c45fSAndroid Build Coastguard Worker     std::string valid_name = entry_name;
859*38e8c45fSAndroid Build Coastguard Worker 
860*38e8c45fSAndroid Build Coastguard Worker     // Rename extension if necessary.
861*38e8c45fSAndroid Build Coastguard Worker     size_t idx = entry_name.rfind('.');
862*38e8c45fSAndroid Build Coastguard Worker     if (idx != std::string::npos) {
863*38e8c45fSAndroid Build Coastguard Worker         std::string extension = entry_name.substr(idx);
864*38e8c45fSAndroid Build Coastguard Worker         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
865*38e8c45fSAndroid Build Coastguard Worker         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
866*38e8c45fSAndroid Build Coastguard Worker             valid_name = entry_name + ".renamed";
867*38e8c45fSAndroid Build Coastguard Worker             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
868*38e8c45fSAndroid Build Coastguard Worker         }
869*38e8c45fSAndroid Build Coastguard Worker     }
870*38e8c45fSAndroid Build Coastguard Worker 
871*38e8c45fSAndroid Build Coastguard Worker     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
872*38e8c45fSAndroid Build Coastguard Worker     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
873*38e8c45fSAndroid Build Coastguard Worker     size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
874*38e8c45fSAndroid Build Coastguard Worker     int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
875*38e8c45fSAndroid Build Coastguard Worker                                                   get_mtime(fd, ds.now_));
876*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
877*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
878*38e8c45fSAndroid Build Coastguard Worker                ZipWriter::ErrorCodeString(err));
879*38e8c45fSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
880*38e8c45fSAndroid Build Coastguard Worker     }
881*38e8c45fSAndroid Build Coastguard Worker     bool finished_entry = false;
882*38e8c45fSAndroid Build Coastguard Worker     auto finish_entry = [this, &finished_entry] {
883*38e8c45fSAndroid Build Coastguard Worker         if (!finished_entry) {
884*38e8c45fSAndroid Build Coastguard Worker             // This should only be called when we're going to return an earlier error,
885*38e8c45fSAndroid Build Coastguard Worker             // which would've been logged. This may imply the file is already corrupt
886*38e8c45fSAndroid Build Coastguard Worker             // and any further logging from FinishEntry is more likely to mislead than
887*38e8c45fSAndroid Build Coastguard Worker             // not.
888*38e8c45fSAndroid Build Coastguard Worker             this->zip_writer_->FinishEntry();
889*38e8c45fSAndroid Build Coastguard Worker         }
890*38e8c45fSAndroid Build Coastguard Worker     };
891*38e8c45fSAndroid Build Coastguard Worker     auto scope_guard = android::base::make_scope_guard(finish_entry);
892*38e8c45fSAndroid Build Coastguard Worker     auto start = std::chrono::steady_clock::now();
893*38e8c45fSAndroid Build Coastguard Worker     auto end = start + timeout;
894*38e8c45fSAndroid Build Coastguard Worker     struct pollfd pfd = {fd, POLLIN};
895*38e8c45fSAndroid Build Coastguard Worker 
896*38e8c45fSAndroid Build Coastguard Worker     std::vector<uint8_t> buffer(65536);
897*38e8c45fSAndroid Build Coastguard Worker     while (1) {
898*38e8c45fSAndroid Build Coastguard Worker         if (timeout.count() > 0) {
899*38e8c45fSAndroid Build Coastguard Worker             // lambda to recalculate the timeout.
900*38e8c45fSAndroid Build Coastguard Worker             auto time_left_ms = [end]() {
901*38e8c45fSAndroid Build Coastguard Worker                 auto now = std::chrono::steady_clock::now();
902*38e8c45fSAndroid Build Coastguard Worker                 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
903*38e8c45fSAndroid Build Coastguard Worker                 return std::max(diff.count(), 0LL);
904*38e8c45fSAndroid Build Coastguard Worker             };
905*38e8c45fSAndroid Build Coastguard Worker 
906*38e8c45fSAndroid Build Coastguard Worker             int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
907*38e8c45fSAndroid Build Coastguard Worker             if (rc < 0) {
908*38e8c45fSAndroid Build Coastguard Worker                 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
909*38e8c45fSAndroid Build Coastguard Worker                        entry_name.c_str(), strerror(errno));
910*38e8c45fSAndroid Build Coastguard Worker                 return -errno;
911*38e8c45fSAndroid Build Coastguard Worker             } else if (rc == 0) {
912*38e8c45fSAndroid Build Coastguard Worker                 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
913*38e8c45fSAndroid Build Coastguard Worker                        entry_name.c_str(), strerror(errno), timeout.count());
914*38e8c45fSAndroid Build Coastguard Worker                 return TIMED_OUT;
915*38e8c45fSAndroid Build Coastguard Worker             }
916*38e8c45fSAndroid Build Coastguard Worker         }
917*38e8c45fSAndroid Build Coastguard Worker 
918*38e8c45fSAndroid Build Coastguard Worker         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
919*38e8c45fSAndroid Build Coastguard Worker         if (bytes_read == 0) {
920*38e8c45fSAndroid Build Coastguard Worker             break;
921*38e8c45fSAndroid Build Coastguard Worker         } else if (bytes_read == -1) {
922*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
923*38e8c45fSAndroid Build Coastguard Worker             return -errno;
924*38e8c45fSAndroid Build Coastguard Worker         }
925*38e8c45fSAndroid Build Coastguard Worker         err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
926*38e8c45fSAndroid Build Coastguard Worker         if (err) {
927*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
928*38e8c45fSAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
929*38e8c45fSAndroid Build Coastguard Worker         }
930*38e8c45fSAndroid Build Coastguard Worker     }
931*38e8c45fSAndroid Build Coastguard Worker 
932*38e8c45fSAndroid Build Coastguard Worker     err = zip_writer_->FinishEntry();
933*38e8c45fSAndroid Build Coastguard Worker     finished_entry = true;
934*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
935*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
936*38e8c45fSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
937*38e8c45fSAndroid Build Coastguard Worker     }
938*38e8c45fSAndroid Build Coastguard Worker 
939*38e8c45fSAndroid Build Coastguard Worker     return OK;
940*38e8c45fSAndroid Build Coastguard Worker }
941*38e8c45fSAndroid Build Coastguard Worker 
AddZipEntry(const std::string & entry_name,const std::string & entry_path)942*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
943*38e8c45fSAndroid Build Coastguard Worker     android::base::unique_fd fd(
944*38e8c45fSAndroid Build Coastguard Worker         TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
945*38e8c45fSAndroid Build Coastguard Worker     if (fd == -1) {
946*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
947*38e8c45fSAndroid Build Coastguard Worker         return false;
948*38e8c45fSAndroid Build Coastguard Worker     }
949*38e8c45fSAndroid Build Coastguard Worker 
950*38e8c45fSAndroid Build Coastguard Worker     return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
951*38e8c45fSAndroid Build Coastguard Worker }
952*38e8c45fSAndroid Build Coastguard Worker 
953*38e8c45fSAndroid Build Coastguard Worker /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)954*38e8c45fSAndroid Build Coastguard Worker static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
955*38e8c45fSAndroid Build Coastguard Worker     return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
956*38e8c45fSAndroid Build Coastguard Worker }
957*38e8c45fSAndroid Build Coastguard Worker 
AddDir(const std::string & dir,bool recursive)958*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::AddDir(const std::string& dir, bool recursive) {
959*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
960*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(dir, true);
961*38e8c45fSAndroid Build Coastguard Worker     dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
962*38e8c45fSAndroid Build Coastguard Worker }
963*38e8c45fSAndroid Build Coastguard Worker 
AddTextZipEntry(const std::string & entry_name,const std::string & content)964*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
965*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
966*38e8c45fSAndroid Build Coastguard Worker     size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
967*38e8c45fSAndroid Build Coastguard Worker     int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
968*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
969*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
970*38e8c45fSAndroid Build Coastguard Worker                ZipWriter::ErrorCodeString(err));
971*38e8c45fSAndroid Build Coastguard Worker         return false;
972*38e8c45fSAndroid Build Coastguard Worker     }
973*38e8c45fSAndroid Build Coastguard Worker 
974*38e8c45fSAndroid Build Coastguard Worker     err = zip_writer_->WriteBytes(content.c_str(), content.length());
975*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
976*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
977*38e8c45fSAndroid Build Coastguard Worker                ZipWriter::ErrorCodeString(err));
978*38e8c45fSAndroid Build Coastguard Worker         return false;
979*38e8c45fSAndroid Build Coastguard Worker     }
980*38e8c45fSAndroid Build Coastguard Worker 
981*38e8c45fSAndroid Build Coastguard Worker     err = zip_writer_->FinishEntry();
982*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
983*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
984*38e8c45fSAndroid Build Coastguard Worker         return false;
985*38e8c45fSAndroid Build Coastguard Worker     }
986*38e8c45fSAndroid Build Coastguard Worker 
987*38e8c45fSAndroid Build Coastguard Worker     return true;
988*38e8c45fSAndroid Build Coastguard Worker }
989*38e8c45fSAndroid Build Coastguard Worker 
DoKmsg()990*38e8c45fSAndroid Build Coastguard Worker static void DoKmsg() {
991*38e8c45fSAndroid Build Coastguard Worker     struct stat st;
992*38e8c45fSAndroid Build Coastguard Worker     if (!stat(PSTORE_LAST_KMSG, &st)) {
993*38e8c45fSAndroid Build Coastguard Worker         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
994*38e8c45fSAndroid Build Coastguard Worker         DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
995*38e8c45fSAndroid Build Coastguard Worker     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
996*38e8c45fSAndroid Build Coastguard Worker         DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
997*38e8c45fSAndroid Build Coastguard Worker     } else {
998*38e8c45fSAndroid Build Coastguard Worker         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
999*38e8c45fSAndroid Build Coastguard Worker         DumpFile("LAST KMSG", "/proc/last_kmsg");
1000*38e8c45fSAndroid Build Coastguard Worker     }
1001*38e8c45fSAndroid Build Coastguard Worker }
1002*38e8c45fSAndroid Build Coastguard Worker 
DoKernelLogcat()1003*38e8c45fSAndroid Build Coastguard Worker static void DoKernelLogcat() {
1004*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms = logcat_timeout({"kernel"});
1005*38e8c45fSAndroid Build Coastguard Worker     RunCommand(
1006*38e8c45fSAndroid Build Coastguard Worker         "KERNEL LOG",
1007*38e8c45fSAndroid Build Coastguard Worker         {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1008*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1009*38e8c45fSAndroid Build Coastguard Worker }
1010*38e8c45fSAndroid Build Coastguard Worker 
DoSystemLogcat(time_t since)1011*38e8c45fSAndroid Build Coastguard Worker static void DoSystemLogcat(time_t since) {
1012*38e8c45fSAndroid Build Coastguard Worker     char since_str[80];
1013*38e8c45fSAndroid Build Coastguard Worker     strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1014*38e8c45fSAndroid Build Coastguard Worker 
1015*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1016*38e8c45fSAndroid Build Coastguard Worker     RunCommand("SYSTEM LOG",
1017*38e8c45fSAndroid Build Coastguard Worker                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1018*38e8c45fSAndroid Build Coastguard Worker                 since_str},
1019*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1020*38e8c45fSAndroid Build Coastguard Worker }
1021*38e8c45fSAndroid Build Coastguard Worker 
DoRadioLogcat()1022*38e8c45fSAndroid Build Coastguard Worker static void DoRadioLogcat() {
1023*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms = logcat_timeout({"radio"});
1024*38e8c45fSAndroid Build Coastguard Worker     RunCommand(
1025*38e8c45fSAndroid Build Coastguard Worker         "RADIO LOG",
1026*38e8c45fSAndroid Build Coastguard Worker         {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1027*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1028*38e8c45fSAndroid Build Coastguard Worker }
1029*38e8c45fSAndroid Build Coastguard Worker 
DoLogcat()1030*38e8c45fSAndroid Build Coastguard Worker static void DoLogcat() {
1031*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms;
1032*38e8c45fSAndroid Build Coastguard Worker     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1033*38e8c45fSAndroid Build Coastguard Worker     // calculate timeout
1034*38e8c45fSAndroid Build Coastguard Worker     timeout_ms = logcat_timeout({"main", "system", "crash"});
1035*38e8c45fSAndroid Build Coastguard Worker     RunCommand("SYSTEM LOG",
1036*38e8c45fSAndroid Build Coastguard Worker                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1037*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1038*38e8c45fSAndroid Build Coastguard Worker     timeout_ms = logcat_timeout({"events"});
1039*38e8c45fSAndroid Build Coastguard Worker     RunCommand(
1040*38e8c45fSAndroid Build Coastguard Worker         "EVENT LOG",
1041*38e8c45fSAndroid Build Coastguard Worker         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1042*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1043*38e8c45fSAndroid Build Coastguard Worker     timeout_ms = logcat_timeout({"stats"});
1044*38e8c45fSAndroid Build Coastguard Worker     RunCommand(
1045*38e8c45fSAndroid Build Coastguard Worker         "STATS LOG",
1046*38e8c45fSAndroid Build Coastguard Worker         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1047*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1048*38e8c45fSAndroid Build Coastguard Worker     DoRadioLogcat();
1049*38e8c45fSAndroid Build Coastguard Worker 
1050*38e8c45fSAndroid Build Coastguard Worker     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
1051*38e8c45fSAndroid Build Coastguard Worker     RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1052*38e8c45fSAndroid Build Coastguard Worker                                "-v", "uid", "-d", "*:v"});
1053*38e8c45fSAndroid Build Coastguard Worker }
1054*38e8c45fSAndroid Build Coastguard Worker 
DumpIncidentReport()1055*38e8c45fSAndroid Build Coastguard Worker static void DumpIncidentReport() {
1056*38e8c45fSAndroid Build Coastguard Worker     const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1057*38e8c45fSAndroid Build Coastguard Worker     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1058*38e8c45fSAndroid Build Coastguard Worker                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1059*38e8c45fSAndroid Build Coastguard Worker                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1060*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
1061*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1062*38e8c45fSAndroid Build Coastguard Worker         return;
1063*38e8c45fSAndroid Build Coastguard Worker     }
1064*38e8c45fSAndroid Build Coastguard Worker     RunCommandToFd(fd, "", {"incident", "-u"},
1065*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
1066*38e8c45fSAndroid Build Coastguard Worker     bool empty = 0 == lseek(fd, 0, SEEK_END);
1067*38e8c45fSAndroid Build Coastguard Worker     if (!empty) {
1068*38e8c45fSAndroid Build Coastguard Worker         // Use a different name from "incident.proto"
1069*38e8c45fSAndroid Build Coastguard Worker         // /proto/incident.proto is reserved for incident service dump
1070*38e8c45fSAndroid Build Coastguard Worker         // i.e. metadata for debugging.
1071*38e8c45fSAndroid Build Coastguard Worker         ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1072*38e8c45fSAndroid Build Coastguard Worker                 path);
1073*38e8c45fSAndroid Build Coastguard Worker     } else {
1074*38e8c45fSAndroid Build Coastguard Worker         unlink(path.c_str());
1075*38e8c45fSAndroid Build Coastguard Worker     }
1076*38e8c45fSAndroid Build Coastguard Worker }
1077*38e8c45fSAndroid Build Coastguard Worker 
DumpNetstatsProto()1078*38e8c45fSAndroid Build Coastguard Worker static void DumpNetstatsProto() {
1079*38e8c45fSAndroid Build Coastguard Worker     const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1080*38e8c45fSAndroid Build Coastguard Worker     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1081*38e8c45fSAndroid Build Coastguard Worker                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1082*38e8c45fSAndroid Build Coastguard Worker                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1083*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
1084*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1085*38e8c45fSAndroid Build Coastguard Worker         return;
1086*38e8c45fSAndroid Build Coastguard Worker     }
1087*38e8c45fSAndroid Build Coastguard Worker     RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
1088*38e8c45fSAndroid Build Coastguard Worker             CommandOptions::WithTimeout(5).Build());
1089*38e8c45fSAndroid Build Coastguard Worker     bool empty = 0 == lseek(fd, 0, SEEK_END);
1090*38e8c45fSAndroid Build Coastguard Worker     if (!empty) {
1091*38e8c45fSAndroid Build Coastguard Worker         ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1092*38e8c45fSAndroid Build Coastguard Worker                 path);
1093*38e8c45fSAndroid Build Coastguard Worker     } else {
1094*38e8c45fSAndroid Build Coastguard Worker         unlink(path.c_str());
1095*38e8c45fSAndroid Build Coastguard Worker     }
1096*38e8c45fSAndroid Build Coastguard Worker }
1097*38e8c45fSAndroid Build Coastguard Worker 
MaybeAddSystemTraceToZip()1098*38e8c45fSAndroid Build Coastguard Worker static void MaybeAddSystemTraceToZip() {
1099*38e8c45fSAndroid Build Coastguard Worker     // This function copies into the .zip the system trace that was snapshotted
1100*38e8c45fSAndroid Build Coastguard Worker     // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
1101*38e8c45fSAndroid Build Coastguard Worker     // tracing was happening.
1102*38e8c45fSAndroid Build Coastguard Worker     bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1103*38e8c45fSAndroid Build Coastguard Worker     if (!system_trace_exists) {
1104*38e8c45fSAndroid Build Coastguard Worker         // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
1105*38e8c45fSAndroid Build Coastguard Worker         if (!PropertiesHelper::IsUserBuild()) {
1106*38e8c45fSAndroid Build Coastguard Worker             MYLOGI(
1107*38e8c45fSAndroid Build Coastguard Worker                 "No system traces found. Check for previously uploaded traces by looking for "
1108*38e8c45fSAndroid Build Coastguard Worker                 "go/trace-uuid in logcat")
1109*38e8c45fSAndroid Build Coastguard Worker         }
1110*38e8c45fSAndroid Build Coastguard Worker         return;
1111*38e8c45fSAndroid Build Coastguard Worker     }
1112*38e8c45fSAndroid Build Coastguard Worker     ds.AddZipEntry(
1113*38e8c45fSAndroid Build Coastguard Worker             ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1114*38e8c45fSAndroid Build Coastguard Worker             SYSTEM_TRACE_SNAPSHOT);
1115*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1116*38e8c45fSAndroid Build Coastguard Worker }
1117*38e8c45fSAndroid Build Coastguard Worker 
DumpVisibleWindowViews()1118*38e8c45fSAndroid Build Coastguard Worker static void DumpVisibleWindowViews() {
1119*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1120*38e8c45fSAndroid Build Coastguard Worker     const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1121*38e8c45fSAndroid Build Coastguard Worker     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1122*38e8c45fSAndroid Build Coastguard Worker                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1123*38e8c45fSAndroid Build Coastguard Worker                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1124*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
1125*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1126*38e8c45fSAndroid Build Coastguard Worker         return;
1127*38e8c45fSAndroid Build Coastguard Worker     }
1128*38e8c45fSAndroid Build Coastguard Worker     RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1129*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(10).Build());
1130*38e8c45fSAndroid Build Coastguard Worker     bool empty = 0 == lseek(fd, 0, SEEK_END);
1131*38e8c45fSAndroid Build Coastguard Worker     if (!empty) {
1132*38e8c45fSAndroid Build Coastguard Worker         ds.AddZipEntry("visible_windows.zip", path);
1133*38e8c45fSAndroid Build Coastguard Worker     } else {
1134*38e8c45fSAndroid Build Coastguard Worker         MYLOGW("Failed to dump visible windows\n");
1135*38e8c45fSAndroid Build Coastguard Worker     }
1136*38e8c45fSAndroid Build Coastguard Worker     unlink(path.c_str());
1137*38e8c45fSAndroid Build Coastguard Worker }
1138*38e8c45fSAndroid Build Coastguard Worker 
DumpIpTablesAsRoot()1139*38e8c45fSAndroid Build Coastguard Worker static void DumpIpTablesAsRoot() {
1140*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1141*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
1142*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
1143*38e8c45fSAndroid Build Coastguard Worker     /* no ip6 nat */
1144*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1145*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1146*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1147*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
1148*38e8c45fSAndroid Build Coastguard Worker }
1149*38e8c45fSAndroid Build Coastguard Worker 
DumpShutdownCheckpoints()1150*38e8c45fSAndroid Build Coastguard Worker static void DumpShutdownCheckpoints() {
1151*38e8c45fSAndroid Build Coastguard Worker     const bool shutdown_checkpoints_dumped = AddDumps(
1152*38e8c45fSAndroid Build Coastguard Worker         ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1153*38e8c45fSAndroid Build Coastguard Worker         "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1154*38e8c45fSAndroid Build Coastguard Worker     if (!shutdown_checkpoints_dumped) {
1155*38e8c45fSAndroid Build Coastguard Worker         printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1156*38e8c45fSAndroid Build Coastguard Worker             SHUTDOWN_CHECKPOINTS_DIR.c_str());
1157*38e8c45fSAndroid Build Coastguard Worker     }
1158*38e8c45fSAndroid Build Coastguard Worker }
1159*38e8c45fSAndroid Build Coastguard Worker 
DumpDynamicPartitionInfo()1160*38e8c45fSAndroid Build Coastguard Worker static void DumpDynamicPartitionInfo() {
1161*38e8c45fSAndroid Build Coastguard Worker     if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1162*38e8c45fSAndroid Build Coastguard Worker         return;
1163*38e8c45fSAndroid Build Coastguard Worker     }
1164*38e8c45fSAndroid Build Coastguard Worker 
1165*38e8c45fSAndroid Build Coastguard Worker     RunCommand("LPDUMP", {"lpdump", "--all"});
1166*38e8c45fSAndroid Build Coastguard Worker     RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
1167*38e8c45fSAndroid Build Coastguard Worker }
1168*38e8c45fSAndroid Build Coastguard Worker 
AddAnrTraceDir(const std::string & anr_traces_dir)1169*38e8c45fSAndroid Build Coastguard Worker static void AddAnrTraceDir(const std::string& anr_traces_dir) {
1170*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1171*38e8c45fSAndroid Build Coastguard Worker            anr_traces_dir.c_str());
1172*38e8c45fSAndroid Build Coastguard Worker 
1173*38e8c45fSAndroid Build Coastguard Worker     // If we're here, dump_traces_path will always be a temporary file
1174*38e8c45fSAndroid Build Coastguard Worker     // (created with mkostemp or similar) that contains dumps taken earlier
1175*38e8c45fSAndroid Build Coastguard Worker     // on in the process.
1176*38e8c45fSAndroid Build Coastguard Worker     if (dump_traces_path != nullptr) {
1177*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1178*38e8c45fSAndroid Build Coastguard Worker                 dump_traces_path);
1179*38e8c45fSAndroid Build Coastguard Worker         ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1180*38e8c45fSAndroid Build Coastguard Worker 
1181*38e8c45fSAndroid Build Coastguard Worker         const int ret = unlink(dump_traces_path);
1182*38e8c45fSAndroid Build Coastguard Worker         if (ret == -1) {
1183*38e8c45fSAndroid Build Coastguard Worker             MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1184*38e8c45fSAndroid Build Coastguard Worker                    strerror(errno));
1185*38e8c45fSAndroid Build Coastguard Worker         }
1186*38e8c45fSAndroid Build Coastguard Worker     }
1187*38e8c45fSAndroid Build Coastguard Worker 
1188*38e8c45fSAndroid Build Coastguard Worker     // Add a specific message for the first ANR Dump.
1189*38e8c45fSAndroid Build Coastguard Worker     if (ds.anr_data_.size() > 0) {
1190*38e8c45fSAndroid Build Coastguard Worker         // The "last" ANR will always be present in the body of the main entry.
1191*38e8c45fSAndroid Build Coastguard Worker         AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
1192*38e8c45fSAndroid Build Coastguard Worker                  "VM TRACES AT LAST ANR", false /* add_to_zip */);
1193*38e8c45fSAndroid Build Coastguard Worker 
1194*38e8c45fSAndroid Build Coastguard Worker         // Historical ANRs are always included as separate entries in the bugreport zip file.
1195*38e8c45fSAndroid Build Coastguard Worker         AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
1196*38e8c45fSAndroid Build Coastguard Worker                  "HISTORICAL ANR", true /* add_to_zip */);
1197*38e8c45fSAndroid Build Coastguard Worker     } else {
1198*38e8c45fSAndroid Build Coastguard Worker         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1199*38e8c45fSAndroid Build Coastguard Worker     }
1200*38e8c45fSAndroid Build Coastguard Worker 
1201*38e8c45fSAndroid Build Coastguard Worker     // Add Java anr traces (such as generated by the Finalizer Watchdog).
1202*38e8c45fSAndroid Build Coastguard Worker     AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1203*38e8c45fSAndroid Build Coastguard Worker              true /* add_to_zip */);
1204*38e8c45fSAndroid Build Coastguard Worker }
1205*38e8c45fSAndroid Build Coastguard Worker 
AddAnrTraceFiles()1206*38e8c45fSAndroid Build Coastguard Worker static void AddAnrTraceFiles() {
1207*38e8c45fSAndroid Build Coastguard Worker     std::string anr_traces_dir = "/data/anr";
1208*38e8c45fSAndroid Build Coastguard Worker 
1209*38e8c45fSAndroid Build Coastguard Worker     AddAnrTraceDir(anr_traces_dir);
1210*38e8c45fSAndroid Build Coastguard Worker 
1211*38e8c45fSAndroid Build Coastguard Worker     RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1212*38e8c45fSAndroid Build Coastguard Worker 
1213*38e8c45fSAndroid Build Coastguard Worker     // Slow traces for slow operations.
1214*38e8c45fSAndroid Build Coastguard Worker     struct stat st;
1215*38e8c45fSAndroid Build Coastguard Worker     int i = 0;
1216*38e8c45fSAndroid Build Coastguard Worker     while (true) {
1217*38e8c45fSAndroid Build Coastguard Worker         const std::string slow_trace_path =
1218*38e8c45fSAndroid Build Coastguard Worker             anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1219*38e8c45fSAndroid Build Coastguard Worker         if (stat(slow_trace_path.c_str(), &st)) {
1220*38e8c45fSAndroid Build Coastguard Worker             // No traces file at this index, done with the files.
1221*38e8c45fSAndroid Build Coastguard Worker             break;
1222*38e8c45fSAndroid Build Coastguard Worker         }
1223*38e8c45fSAndroid Build Coastguard Worker         ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1224*38e8c45fSAndroid Build Coastguard Worker         i++;
1225*38e8c45fSAndroid Build Coastguard Worker     }
1226*38e8c45fSAndroid Build Coastguard Worker }
1227*38e8c45fSAndroid Build Coastguard Worker 
DumpBlockStatFiles()1228*38e8c45fSAndroid Build Coastguard Worker static void DumpBlockStatFiles() {
1229*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMP BLOCK STAT");
1230*38e8c45fSAndroid Build Coastguard Worker 
1231*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1232*38e8c45fSAndroid Build Coastguard Worker 
1233*38e8c45fSAndroid Build Coastguard Worker     if (dirptr == nullptr) {
1234*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1235*38e8c45fSAndroid Build Coastguard Worker         return;
1236*38e8c45fSAndroid Build Coastguard Worker     }
1237*38e8c45fSAndroid Build Coastguard Worker 
1238*38e8c45fSAndroid Build Coastguard Worker     printf("------ DUMP BLOCK STAT ------\n\n");
1239*38e8c45fSAndroid Build Coastguard Worker     while (struct dirent *d = readdir(dirptr.get())) {
1240*38e8c45fSAndroid Build Coastguard Worker         if ((d->d_name[0] == '.')
1241*38e8c45fSAndroid Build Coastguard Worker          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1242*38e8c45fSAndroid Build Coastguard Worker           || (d->d_name[1] == '\0'))) {
1243*38e8c45fSAndroid Build Coastguard Worker             continue;
1244*38e8c45fSAndroid Build Coastguard Worker         }
1245*38e8c45fSAndroid Build Coastguard Worker         const std::string new_path =
1246*38e8c45fSAndroid Build Coastguard Worker             android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1247*38e8c45fSAndroid Build Coastguard Worker         printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1248*38e8c45fSAndroid Build Coastguard Worker         dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1249*38e8c45fSAndroid Build Coastguard Worker         printf("\n");
1250*38e8c45fSAndroid Build Coastguard Worker     }
1251*38e8c45fSAndroid Build Coastguard Worker      return;
1252*38e8c45fSAndroid Build Coastguard Worker }
1253*38e8c45fSAndroid Build Coastguard Worker 
DumpPacketStats()1254*38e8c45fSAndroid Build Coastguard Worker static void DumpPacketStats() {
1255*38e8c45fSAndroid Build Coastguard Worker     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1256*38e8c45fSAndroid Build Coastguard Worker }
1257*38e8c45fSAndroid Build Coastguard Worker 
DumpIpAddrAndRules()1258*38e8c45fSAndroid Build Coastguard Worker static void DumpIpAddrAndRules() {
1259*38e8c45fSAndroid Build Coastguard Worker     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1260*38e8c45fSAndroid Build Coastguard Worker     RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
1261*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1262*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1263*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP RULES", {"ip", "rule", "show"});
1264*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1265*38e8c45fSAndroid Build Coastguard Worker }
1266*38e8c45fSAndroid Build Coastguard Worker 
RunDumpsysTextByPriority(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1267*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1268*38e8c45fSAndroid Build Coastguard Worker                                                      std::chrono::milliseconds timeout,
1269*38e8c45fSAndroid Build Coastguard Worker                                                      std::chrono::milliseconds service_timeout) {
1270*38e8c45fSAndroid Build Coastguard Worker     auto start = std::chrono::steady_clock::now();
1271*38e8c45fSAndroid Build Coastguard Worker     sp<android::IServiceManager> sm = defaultServiceManager();
1272*38e8c45fSAndroid Build Coastguard Worker     Dumpsys dumpsys(sm.get());
1273*38e8c45fSAndroid Build Coastguard Worker     Vector<String16> args;
1274*38e8c45fSAndroid Build Coastguard Worker     Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
1275*38e8c45fSAndroid Build Coastguard Worker     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1276*38e8c45fSAndroid Build Coastguard Worker     for (const String16& service : services) {
1277*38e8c45fSAndroid Build Coastguard Worker         RETURN_IF_USER_DENIED_CONSENT();
1278*38e8c45fSAndroid Build Coastguard Worker         std::string path(title);
1279*38e8c45fSAndroid Build Coastguard Worker         path.append(" - ").append(String8(service).c_str());
1280*38e8c45fSAndroid Build Coastguard Worker         size_t bytes_written = 0;
1281*38e8c45fSAndroid Build Coastguard Worker         if (PropertiesHelper::IsDryRun()) {
1282*38e8c45fSAndroid Build Coastguard Worker              dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1283*38e8c45fSAndroid Build Coastguard Worker              dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1284*38e8c45fSAndroid Build Coastguard Worker         } else {
1285*38e8c45fSAndroid Build Coastguard Worker              status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1286*38e8c45fSAndroid Build Coastguard Worker                                                        Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
1287*38e8c45fSAndroid Build Coastguard Worker                                                        service, args);
1288*38e8c45fSAndroid Build Coastguard Worker              if (status == OK) {
1289*38e8c45fSAndroid Build Coastguard Worker                 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1290*38e8c45fSAndroid Build Coastguard Worker                 std::chrono::duration<double> elapsed_seconds;
1291*38e8c45fSAndroid Build Coastguard Worker                 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1292*38e8c45fSAndroid Build Coastguard Worker                     service == String16("meminfo")) {
1293*38e8c45fSAndroid Build Coastguard Worker                     // Use a longer timeout for meminfo, since 30s is not always enough.
1294*38e8c45fSAndroid Build Coastguard Worker                     status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1295*38e8c45fSAndroid Build Coastguard Worker                                                /* as_proto = */ false, elapsed_seconds,
1296*38e8c45fSAndroid Build Coastguard Worker                                                 bytes_written);
1297*38e8c45fSAndroid Build Coastguard Worker                 } else {
1298*38e8c45fSAndroid Build Coastguard Worker                     status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1299*38e8c45fSAndroid Build Coastguard Worker                                                /* as_proto = */ false, elapsed_seconds,
1300*38e8c45fSAndroid Build Coastguard Worker                                                 bytes_written);
1301*38e8c45fSAndroid Build Coastguard Worker                 }
1302*38e8c45fSAndroid Build Coastguard Worker                 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1303*38e8c45fSAndroid Build Coastguard Worker                 bool dump_complete = (status == OK);
1304*38e8c45fSAndroid Build Coastguard Worker                 dumpsys.stopDumpThread(dump_complete);
1305*38e8c45fSAndroid Build Coastguard Worker             } else {
1306*38e8c45fSAndroid Build Coastguard Worker                 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1307*38e8c45fSAndroid Build Coastguard Worker                        String8(service).c_str(), status);
1308*38e8c45fSAndroid Build Coastguard Worker             }
1309*38e8c45fSAndroid Build Coastguard Worker         }
1310*38e8c45fSAndroid Build Coastguard Worker 
1311*38e8c45fSAndroid Build Coastguard Worker         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1312*38e8c45fSAndroid Build Coastguard Worker             std::chrono::steady_clock::now() - start);
1313*38e8c45fSAndroid Build Coastguard Worker         if (elapsed_duration > timeout) {
1314*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1315*38e8c45fSAndroid Build Coastguard Worker                    elapsed_duration.count());
1316*38e8c45fSAndroid Build Coastguard Worker             break;
1317*38e8c45fSAndroid Build Coastguard Worker         }
1318*38e8c45fSAndroid Build Coastguard Worker     }
1319*38e8c45fSAndroid Build Coastguard Worker     return Dumpstate::RunStatus::OK;
1320*38e8c45fSAndroid Build Coastguard Worker }
1321*38e8c45fSAndroid Build Coastguard Worker 
RunDumpsysText(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1322*38e8c45fSAndroid Build Coastguard Worker static void RunDumpsysText(const std::string& title, int priority,
1323*38e8c45fSAndroid Build Coastguard Worker                            std::chrono::milliseconds timeout,
1324*38e8c45fSAndroid Build Coastguard Worker                            std::chrono::milliseconds service_timeout) {
1325*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
1326*38e8c45fSAndroid Build Coastguard Worker     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1327*38e8c45fSAndroid Build Coastguard Worker     fsync(STDOUT_FILENO);
1328*38e8c45fSAndroid Build Coastguard Worker     RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1329*38e8c45fSAndroid Build Coastguard Worker }
1330*38e8c45fSAndroid Build Coastguard Worker 
1331*38e8c45fSAndroid Build Coastguard Worker /* Dump all services registered with Normal or Default priority. */
RunDumpsysTextNormalPriority(const std::string & title,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1332*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1333*38e8c45fSAndroid Build Coastguard Worker                                                          std::chrono::milliseconds timeout,
1334*38e8c45fSAndroid Build Coastguard Worker                                                          std::chrono::milliseconds service_timeout) {
1335*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
1336*38e8c45fSAndroid Build Coastguard Worker     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1337*38e8c45fSAndroid Build Coastguard Worker     fsync(STDOUT_FILENO);
1338*38e8c45fSAndroid Build Coastguard Worker     RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1339*38e8c45fSAndroid Build Coastguard Worker                              service_timeout);
1340*38e8c45fSAndroid Build Coastguard Worker 
1341*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
1342*38e8c45fSAndroid Build Coastguard Worker 
1343*38e8c45fSAndroid Build Coastguard Worker     return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1344*38e8c45fSAndroid Build Coastguard Worker                                     service_timeout);
1345*38e8c45fSAndroid Build Coastguard Worker }
1346*38e8c45fSAndroid Build Coastguard Worker 
RunDumpsysProto(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1347*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1348*38e8c45fSAndroid Build Coastguard Worker                                             std::chrono::milliseconds timeout,
1349*38e8c45fSAndroid Build Coastguard Worker                                             std::chrono::milliseconds service_timeout) {
1350*38e8c45fSAndroid Build Coastguard Worker     sp<android::IServiceManager> sm = defaultServiceManager();
1351*38e8c45fSAndroid Build Coastguard Worker     Dumpsys dumpsys(sm.get());
1352*38e8c45fSAndroid Build Coastguard Worker     Vector<String16> args;
1353*38e8c45fSAndroid Build Coastguard Worker     Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1354*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
1355*38e8c45fSAndroid Build Coastguard Worker 
1356*38e8c45fSAndroid Build Coastguard Worker     auto start = std::chrono::steady_clock::now();
1357*38e8c45fSAndroid Build Coastguard Worker     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1358*38e8c45fSAndroid Build Coastguard Worker     for (const String16& service : services) {
1359*38e8c45fSAndroid Build Coastguard Worker         RETURN_IF_USER_DENIED_CONSENT();
1360*38e8c45fSAndroid Build Coastguard Worker         std::string path(kProtoPath);
1361*38e8c45fSAndroid Build Coastguard Worker         path.append(String8(service).c_str());
1362*38e8c45fSAndroid Build Coastguard Worker         if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1363*38e8c45fSAndroid Build Coastguard Worker             path.append("_CRITICAL");
1364*38e8c45fSAndroid Build Coastguard Worker         } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1365*38e8c45fSAndroid Build Coastguard Worker             path.append("_HIGH");
1366*38e8c45fSAndroid Build Coastguard Worker         }
1367*38e8c45fSAndroid Build Coastguard Worker         path.append(kProtoExt);
1368*38e8c45fSAndroid Build Coastguard Worker         status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1369*38e8c45fSAndroid Build Coastguard Worker         if (status == OK) {
1370*38e8c45fSAndroid Build Coastguard Worker             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1371*38e8c45fSAndroid Build Coastguard Worker             bool dumpTerminated = (status == OK);
1372*38e8c45fSAndroid Build Coastguard Worker             dumpsys.stopDumpThread(dumpTerminated);
1373*38e8c45fSAndroid Build Coastguard Worker         }
1374*38e8c45fSAndroid Build Coastguard Worker         ZipWriter::FileEntry file_entry;
1375*38e8c45fSAndroid Build Coastguard Worker         ds.zip_writer_->GetLastEntry(&file_entry);
1376*38e8c45fSAndroid Build Coastguard Worker 
1377*38e8c45fSAndroid Build Coastguard Worker         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1378*38e8c45fSAndroid Build Coastguard Worker             std::chrono::steady_clock::now() - start);
1379*38e8c45fSAndroid Build Coastguard Worker         if (elapsed_duration > timeout) {
1380*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1381*38e8c45fSAndroid Build Coastguard Worker                    elapsed_duration.count());
1382*38e8c45fSAndroid Build Coastguard Worker             break;
1383*38e8c45fSAndroid Build Coastguard Worker         }
1384*38e8c45fSAndroid Build Coastguard Worker     }
1385*38e8c45fSAndroid Build Coastguard Worker     return Dumpstate::RunStatus::OK;
1386*38e8c45fSAndroid Build Coastguard Worker }
1387*38e8c45fSAndroid Build Coastguard Worker 
1388*38e8c45fSAndroid Build Coastguard Worker // Runs dumpsys on services that must dump first and will take less than 100ms to dump.
RunDumpsysCritical()1389*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysCritical() {
1390*38e8c45fSAndroid Build Coastguard Worker     RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1391*38e8c45fSAndroid Build Coastguard Worker                    /* timeout= */ 5s, /* service_timeout= */ 500ms);
1392*38e8c45fSAndroid Build Coastguard Worker 
1393*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
1394*38e8c45fSAndroid Build Coastguard Worker 
1395*38e8c45fSAndroid Build Coastguard Worker     return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1396*38e8c45fSAndroid Build Coastguard Worker                            /* timeout= */ 5s, /* service_timeout= */ 500ms);
1397*38e8c45fSAndroid Build Coastguard Worker }
1398*38e8c45fSAndroid Build Coastguard Worker 
1399*38e8c45fSAndroid Build Coastguard Worker // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
RunDumpsysHigh()1400*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysHigh() {
1401*38e8c45fSAndroid Build Coastguard Worker     // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1402*38e8c45fSAndroid Build Coastguard Worker     // high priority. Reduce timeout once they are able to dump in a shorter time or
1403*38e8c45fSAndroid Build Coastguard Worker     // moved to a parallel task.
1404*38e8c45fSAndroid Build Coastguard Worker     RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1405*38e8c45fSAndroid Build Coastguard Worker                    /* timeout= */ 90s, /* service_timeout= */ 30s);
1406*38e8c45fSAndroid Build Coastguard Worker 
1407*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
1408*38e8c45fSAndroid Build Coastguard Worker 
1409*38e8c45fSAndroid Build Coastguard Worker     return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1410*38e8c45fSAndroid Build Coastguard Worker                            /* timeout= */ 5s, /* service_timeout= */ 1s);
1411*38e8c45fSAndroid Build Coastguard Worker }
1412*38e8c45fSAndroid Build Coastguard Worker 
1413*38e8c45fSAndroid Build Coastguard Worker // Runs dumpsys on services that must dump but can take up to 10s to dump.
RunDumpsysNormal()1414*38e8c45fSAndroid Build Coastguard Worker static Dumpstate::RunStatus RunDumpsysNormal() {
1415*38e8c45fSAndroid Build Coastguard Worker     RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1416*38e8c45fSAndroid Build Coastguard Worker 
1417*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
1418*38e8c45fSAndroid Build Coastguard Worker 
1419*38e8c45fSAndroid Build Coastguard Worker     return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1420*38e8c45fSAndroid Build Coastguard Worker                            /* timeout= */ 90s, /* service_timeout= */ 10s);
1421*38e8c45fSAndroid Build Coastguard Worker }
1422*38e8c45fSAndroid Build Coastguard Worker 
1423*38e8c45fSAndroid Build Coastguard Worker /*
1424*38e8c45fSAndroid Build Coastguard Worker  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1425*38e8c45fSAndroid Build Coastguard Worker  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1426*38e8c45fSAndroid Build Coastguard Worker  * if it's not running in the parallel task.
1427*38e8c45fSAndroid Build Coastguard Worker  */
DumpHals(int out_fd=STDOUT_FILENO)1428*38e8c45fSAndroid Build Coastguard Worker static void DumpHals(int out_fd = STDOUT_FILENO) {
1429*38e8c45fSAndroid Build Coastguard Worker     RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
1430*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1431*38e8c45fSAndroid Build Coastguard Worker                false, out_fd);
1432*38e8c45fSAndroid Build Coastguard Worker 
1433*38e8c45fSAndroid Build Coastguard Worker     using android::hidl::manager::V1_0::IServiceManager;
1434*38e8c45fSAndroid Build Coastguard Worker     using android::hardware::defaultServiceManager;
1435*38e8c45fSAndroid Build Coastguard Worker 
1436*38e8c45fSAndroid Build Coastguard Worker     sp<IServiceManager> sm = defaultServiceManager();
1437*38e8c45fSAndroid Build Coastguard Worker     if (sm == nullptr) {
1438*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1439*38e8c45fSAndroid Build Coastguard Worker         return;
1440*38e8c45fSAndroid Build Coastguard Worker     }
1441*38e8c45fSAndroid Build Coastguard Worker 
1442*38e8c45fSAndroid Build Coastguard Worker     auto ret = sm->list([&](const auto& interfaces) {
1443*38e8c45fSAndroid Build Coastguard Worker         for (const std::string& interface : interfaces) {
1444*38e8c45fSAndroid Build Coastguard Worker             std::string cleanName = interface;
1445*38e8c45fSAndroid Build Coastguard Worker             std::replace_if(
1446*38e8c45fSAndroid Build Coastguard Worker                 cleanName.begin(), cleanName.end(),
1447*38e8c45fSAndroid Build Coastguard Worker                 [](char c) {
1448*38e8c45fSAndroid Build Coastguard Worker                     return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1449*38e8c45fSAndroid Build Coastguard Worker                 },
1450*38e8c45fSAndroid Build Coastguard Worker                 '_');
1451*38e8c45fSAndroid Build Coastguard Worker             const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
1452*38e8c45fSAndroid Build Coastguard Worker 
1453*38e8c45fSAndroid Build Coastguard Worker             bool empty = false;
1454*38e8c45fSAndroid Build Coastguard Worker             {
1455*38e8c45fSAndroid Build Coastguard Worker                 auto fd = android::base::unique_fd(
1456*38e8c45fSAndroid Build Coastguard Worker                     TEMP_FAILURE_RETRY(open(path.c_str(),
1457*38e8c45fSAndroid Build Coastguard Worker                     O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1458*38e8c45fSAndroid Build Coastguard Worker                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1459*38e8c45fSAndroid Build Coastguard Worker                 if (fd < 0) {
1460*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1461*38e8c45fSAndroid Build Coastguard Worker                     continue;
1462*38e8c45fSAndroid Build Coastguard Worker                 }
1463*38e8c45fSAndroid Build Coastguard Worker                 RunCommandToFd(fd,
1464*38e8c45fSAndroid Build Coastguard Worker                         "",
1465*38e8c45fSAndroid Build Coastguard Worker                         {"lshal", "debug", "-E", interface},
1466*38e8c45fSAndroid Build Coastguard Worker                         CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1467*38e8c45fSAndroid Build Coastguard Worker 
1468*38e8c45fSAndroid Build Coastguard Worker                 empty = 0 == lseek(fd, 0, SEEK_END);
1469*38e8c45fSAndroid Build Coastguard Worker             }
1470*38e8c45fSAndroid Build Coastguard Worker             if (!empty) {
1471*38e8c45fSAndroid Build Coastguard Worker                 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1472*38e8c45fSAndroid Build Coastguard Worker                         path);
1473*38e8c45fSAndroid Build Coastguard Worker             } else {
1474*38e8c45fSAndroid Build Coastguard Worker                 unlink(path.c_str());
1475*38e8c45fSAndroid Build Coastguard Worker             }
1476*38e8c45fSAndroid Build Coastguard Worker         }
1477*38e8c45fSAndroid Build Coastguard Worker     });
1478*38e8c45fSAndroid Build Coastguard Worker 
1479*38e8c45fSAndroid Build Coastguard Worker     if (!ret.isOk()) {
1480*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not list hals from hwservicemanager.\n");
1481*38e8c45fSAndroid Build Coastguard Worker     }
1482*38e8c45fSAndroid Build Coastguard Worker }
1483*38e8c45fSAndroid Build Coastguard Worker 
1484*38e8c45fSAndroid Build Coastguard Worker // Dump all of the files that make up the vendor interface.
1485*38e8c45fSAndroid Build Coastguard Worker // See the files listed in dumpFileList() for the latest list of files.
DumpVintf()1486*38e8c45fSAndroid Build Coastguard Worker static void DumpVintf() {
1487*38e8c45fSAndroid Build Coastguard Worker 
1488*38e8c45fSAndroid Build Coastguard Worker     const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1489*38e8c45fSAndroid Build Coastguard Worker     const auto vintfFiles = android::vintf::details::dumpFileList(sku);
1490*38e8c45fSAndroid Build Coastguard Worker     for (const auto vintfFile : vintfFiles) {
1491*38e8c45fSAndroid Build Coastguard Worker         struct stat st;
1492*38e8c45fSAndroid Build Coastguard Worker         if (stat(vintfFile.c_str(), &st) == 0) {
1493*38e8c45fSAndroid Build Coastguard Worker             if (S_ISDIR(st.st_mode)) {
1494*38e8c45fSAndroid Build Coastguard Worker                 ds.AddDir(vintfFile, true /* recursive */);
1495*38e8c45fSAndroid Build Coastguard Worker             } else {
1496*38e8c45fSAndroid Build Coastguard Worker                 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1497*38e8c45fSAndroid Build Coastguard Worker                         vintfFile);
1498*38e8c45fSAndroid Build Coastguard Worker             }
1499*38e8c45fSAndroid Build Coastguard Worker         }
1500*38e8c45fSAndroid Build Coastguard Worker     }
1501*38e8c45fSAndroid Build Coastguard Worker }
1502*38e8c45fSAndroid Build Coastguard Worker 
DumpExternalFragmentationInfo()1503*38e8c45fSAndroid Build Coastguard Worker static void DumpExternalFragmentationInfo() {
1504*38e8c45fSAndroid Build Coastguard Worker     struct stat st;
1505*38e8c45fSAndroid Build Coastguard Worker     if (stat("/proc/buddyinfo", &st) != 0) {
1506*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Unable to dump external fragmentation info\n");
1507*38e8c45fSAndroid Build Coastguard Worker         return;
1508*38e8c45fSAndroid Build Coastguard Worker     }
1509*38e8c45fSAndroid Build Coastguard Worker 
1510*38e8c45fSAndroid Build Coastguard Worker     printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1511*38e8c45fSAndroid Build Coastguard Worker     std::ifstream ifs("/proc/buddyinfo");
1512*38e8c45fSAndroid Build Coastguard Worker     auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1513*38e8c45fSAndroid Build Coastguard Worker     for (std::string line; std::getline(ifs, line);) {
1514*38e8c45fSAndroid Build Coastguard Worker         std::smatch match_results;
1515*38e8c45fSAndroid Build Coastguard Worker         if (std::regex_match(line, match_results, unusable_index_regex)) {
1516*38e8c45fSAndroid Build Coastguard Worker             std::stringstream free_pages(std::string{match_results[3]});
1517*38e8c45fSAndroid Build Coastguard Worker             std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1518*38e8c45fSAndroid Build Coastguard Worker                                                   std::istream_iterator<int>());
1519*38e8c45fSAndroid Build Coastguard Worker 
1520*38e8c45fSAndroid Build Coastguard Worker             int total_free_pages = 0;
1521*38e8c45fSAndroid Build Coastguard Worker             for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1522*38e8c45fSAndroid Build Coastguard Worker                 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1523*38e8c45fSAndroid Build Coastguard Worker             }
1524*38e8c45fSAndroid Build Coastguard Worker 
1525*38e8c45fSAndroid Build Coastguard Worker             printf("Node %s, zone %8s", match_results[1].str().c_str(),
1526*38e8c45fSAndroid Build Coastguard Worker                    match_results[2].str().c_str());
1527*38e8c45fSAndroid Build Coastguard Worker 
1528*38e8c45fSAndroid Build Coastguard Worker             int usable_free_pages = total_free_pages;
1529*38e8c45fSAndroid Build Coastguard Worker             for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1530*38e8c45fSAndroid Build Coastguard Worker                 auto unusable_index = (total_free_pages - usable_free_pages) /
1531*38e8c45fSAndroid Build Coastguard Worker                         static_cast<double>(total_free_pages);
1532*38e8c45fSAndroid Build Coastguard Worker                 printf(" %5.3f", unusable_index);
1533*38e8c45fSAndroid Build Coastguard Worker                 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1534*38e8c45fSAndroid Build Coastguard Worker             }
1535*38e8c45fSAndroid Build Coastguard Worker 
1536*38e8c45fSAndroid Build Coastguard Worker             printf("\n");
1537*38e8c45fSAndroid Build Coastguard Worker         }
1538*38e8c45fSAndroid Build Coastguard Worker     }
1539*38e8c45fSAndroid Build Coastguard Worker     printf("\n");
1540*38e8c45fSAndroid Build Coastguard Worker }
1541*38e8c45fSAndroid Build Coastguard Worker 
DumpstateLimitedOnly()1542*38e8c45fSAndroid Build Coastguard Worker static void DumpstateLimitedOnly() {
1543*38e8c45fSAndroid Build Coastguard Worker     // Trimmed-down version of dumpstate to only include a allowlisted
1544*38e8c45fSAndroid Build Coastguard Worker     // set of logs (system log, event log, and system server / system app
1545*38e8c45fSAndroid Build Coastguard Worker     // crashes, and networking logs). See b/136273873 and b/138459828
1546*38e8c45fSAndroid Build Coastguard Worker     // for context.
1547*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMPSTATE");
1548*38e8c45fSAndroid Build Coastguard Worker     unsigned long timeout_ms;
1549*38e8c45fSAndroid Build Coastguard Worker     // calculate timeout
1550*38e8c45fSAndroid Build Coastguard Worker     timeout_ms = logcat_timeout({"main", "system", "crash"});
1551*38e8c45fSAndroid Build Coastguard Worker     RunCommand("SYSTEM LOG",
1552*38e8c45fSAndroid Build Coastguard Worker                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1553*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1554*38e8c45fSAndroid Build Coastguard Worker     timeout_ms = logcat_timeout({"events"});
1555*38e8c45fSAndroid Build Coastguard Worker     RunCommand(
1556*38e8c45fSAndroid Build Coastguard Worker         "EVENT LOG",
1557*38e8c45fSAndroid Build Coastguard Worker         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1558*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1559*38e8c45fSAndroid Build Coastguard Worker 
1560*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1561*38e8c45fSAndroid Build Coastguard Worker     printf("== Networking Service\n");
1562*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1563*38e8c45fSAndroid Build Coastguard Worker 
1564*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1565*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1566*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1567*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1568*38e8c45fSAndroid Build Coastguard Worker 
1569*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1570*38e8c45fSAndroid Build Coastguard Worker     printf("== Networking Policy\n");
1571*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1572*38e8c45fSAndroid Build Coastguard Worker 
1573*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS NETWORK POLICY", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(),
1574*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
1575*38e8c45fSAndroid Build Coastguard Worker 
1576*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1577*38e8c45fSAndroid Build Coastguard Worker     printf("== Dropbox crashes\n");
1578*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1579*38e8c45fSAndroid Build Coastguard Worker 
1580*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1581*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1582*38e8c45fSAndroid Build Coastguard Worker 
1583*38e8c45fSAndroid Build Coastguard Worker 
1584*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1585*38e8c45fSAndroid Build Coastguard Worker     printf("== ANR Traces\n");
1586*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1587*38e8c45fSAndroid Build Coastguard Worker 
1588*38e8c45fSAndroid Build Coastguard Worker     ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
1589*38e8c45fSAndroid Build Coastguard Worker     AddAnrTraceFiles();
1590*38e8c45fSAndroid Build Coastguard Worker 
1591*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1592*38e8c45fSAndroid Build Coastguard Worker     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1593*38e8c45fSAndroid Build Coastguard Worker            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1594*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1595*38e8c45fSAndroid Build Coastguard Worker     printf("== dumpstate: done (id %d)\n", ds.id_);
1596*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1597*38e8c45fSAndroid Build Coastguard Worker }
1598*38e8c45fSAndroid Build Coastguard Worker 
1599*38e8c45fSAndroid Build Coastguard Worker /*
1600*38e8c45fSAndroid Build Coastguard Worker  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1601*38e8c45fSAndroid Build Coastguard Worker  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1602*38e8c45fSAndroid Build Coastguard Worker  * if it's not running in the parallel task.
1603*38e8c45fSAndroid Build Coastguard Worker  */
DumpCheckins(int out_fd=STDOUT_FILENO)1604*38e8c45fSAndroid Build Coastguard Worker static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1605*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1606*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Checkins\n");
1607*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1608*38e8c45fSAndroid Build Coastguard Worker 
1609*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1610*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1611*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1612*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1613*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1614*38e8c45fSAndroid Build Coastguard Worker }
1615*38e8c45fSAndroid Build Coastguard Worker 
1616*38e8c45fSAndroid Build Coastguard Worker /*
1617*38e8c45fSAndroid Build Coastguard Worker  * Runs dumpsys on activity service to dump all application activities, services
1618*38e8c45fSAndroid Build Coastguard Worker  * and providers in the device.
1619*38e8c45fSAndroid Build Coastguard Worker  *
1620*38e8c45fSAndroid Build Coastguard Worker  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1621*38e8c45fSAndroid Build Coastguard Worker  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1622*38e8c45fSAndroid Build Coastguard Worker  * if it's not running in the parallel task.
1623*38e8c45fSAndroid Build Coastguard Worker  */
DumpAppInfos(int out_fd=STDOUT_FILENO)1624*38e8c45fSAndroid Build Coastguard Worker static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1625*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1626*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Running Application Activities\n");
1627*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1628*38e8c45fSAndroid Build Coastguard Worker 
1629*38e8c45fSAndroid Build Coastguard Worker     // The following dumpsys internally collects output from running apps, so it can take a long
1630*38e8c45fSAndroid Build Coastguard Worker     // time. So let's extend the timeout.
1631*38e8c45fSAndroid Build Coastguard Worker 
1632*38e8c45fSAndroid Build Coastguard Worker     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1633*38e8c45fSAndroid Build Coastguard Worker 
1634*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1635*38e8c45fSAndroid Build Coastguard Worker 
1636*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1637*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Running Application Services (platform)\n");
1638*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1639*38e8c45fSAndroid Build Coastguard Worker 
1640*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1641*38e8c45fSAndroid Build Coastguard Worker             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1642*38e8c45fSAndroid Build Coastguard Worker 
1643*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1644*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Running Application Services (non-platform)\n");
1645*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1646*38e8c45fSAndroid Build Coastguard Worker 
1647*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1648*38e8c45fSAndroid Build Coastguard Worker             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1649*38e8c45fSAndroid Build Coastguard Worker 
1650*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1651*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Running Application Providers (platform)\n");
1652*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1653*38e8c45fSAndroid Build Coastguard Worker 
1654*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1655*38e8c45fSAndroid Build Coastguard Worker             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1656*38e8c45fSAndroid Build Coastguard Worker 
1657*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1658*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1659*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
1660*38e8c45fSAndroid Build Coastguard Worker 
1661*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1662*38e8c45fSAndroid Build Coastguard Worker             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1663*38e8c45fSAndroid Build Coastguard Worker }
1664*38e8c45fSAndroid Build Coastguard Worker 
1665*38e8c45fSAndroid Build Coastguard Worker // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1666*38e8c45fSAndroid Build Coastguard Worker // via the consent they are shown. Ignores other errors that occur while running various
1667*38e8c45fSAndroid Build Coastguard Worker // commands. The consent checking is currently done around long running tasks, which happen to
1668*38e8c45fSAndroid Build Coastguard Worker // be distributed fairly evenly throughout the function.
dumpstate()1669*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::dumpstate() {
1670*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMPSTATE");
1671*38e8c45fSAndroid Build Coastguard Worker 
1672*38e8c45fSAndroid Build Coastguard Worker     // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1673*38e8c45fSAndroid Build Coastguard Worker     std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
1674*38e8c45fSAndroid Build Coastguard Worker         dump_netstats_report;
1675*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1676*38e8c45fSAndroid Build Coastguard Worker         // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1677*38e8c45fSAndroid Build Coastguard Worker         // drop root user. Restarts it.
1678*38e8c45fSAndroid Build Coastguard Worker         ds.dump_pool_->start(/* thread_counts = */3);
1679*38e8c45fSAndroid Build Coastguard Worker 
1680*38e8c45fSAndroid Build Coastguard Worker         dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1681*38e8c45fSAndroid Build Coastguard Worker         dump_incident_report = ds.dump_pool_->enqueueTask(
1682*38e8c45fSAndroid Build Coastguard Worker             DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1683*38e8c45fSAndroid Build Coastguard Worker         dump_netstats_report = ds.dump_pool_->enqueueTask(
1684*38e8c45fSAndroid Build Coastguard Worker             DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
1685*38e8c45fSAndroid Build Coastguard Worker         dump_board = ds.dump_pool_->enqueueTaskWithFd(
1686*38e8c45fSAndroid Build Coastguard Worker             DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1687*38e8c45fSAndroid Build Coastguard Worker         dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
1688*38e8c45fSAndroid Build Coastguard Worker     }
1689*38e8c45fSAndroid Build Coastguard Worker 
1690*38e8c45fSAndroid Build Coastguard Worker     // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1691*38e8c45fSAndroid Build Coastguard Worker     // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1692*38e8c45fSAndroid Build Coastguard Worker     // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
1693*38e8c45fSAndroid Build Coastguard Worker     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
1694*38e8c45fSAndroid Build Coastguard Worker     RunCommand("UPTIME", {"uptime"});
1695*38e8c45fSAndroid Build Coastguard Worker     DumpBlockStatFiles();
1696*38e8c45fSAndroid Build Coastguard Worker     DumpFile("MEMORY INFO", "/proc/meminfo");
1697*38e8c45fSAndroid Build Coastguard Worker     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
1698*38e8c45fSAndroid Build Coastguard Worker                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
1699*38e8c45fSAndroid Build Coastguard Worker 
1700*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1701*38e8c45fSAndroid Build Coastguard Worker                                          CommandOptions::AS_ROOT);
1702*38e8c45fSAndroid Build Coastguard Worker 
1703*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1704*38e8c45fSAndroid Build Coastguard Worker 
1705*38e8c45fSAndroid Build Coastguard Worker     DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1706*38e8c45fSAndroid Build Coastguard Worker     DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1707*38e8c45fSAndroid Build Coastguard Worker     DumpFile("SLAB INFO", "/proc/slabinfo");
1708*38e8c45fSAndroid Build Coastguard Worker     DumpFile("ZONEINFO", "/proc/zoneinfo");
1709*38e8c45fSAndroid Build Coastguard Worker     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1710*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BUDDYINFO", "/proc/buddyinfo");
1711*38e8c45fSAndroid Build Coastguard Worker     DumpExternalFragmentationInfo();
1712*38e8c45fSAndroid Build Coastguard Worker 
1713*38e8c45fSAndroid Build Coastguard Worker     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1714*38e8c45fSAndroid Build Coastguard Worker 
1715*38e8c45fSAndroid Build Coastguard Worker     RunCommand("PROCESSES AND THREADS",
1716*38e8c45fSAndroid Build Coastguard Worker                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
1717*38e8c45fSAndroid Build Coastguard Worker 
1718*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1719*38e8c45fSAndroid Build Coastguard Worker         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
1720*38e8c45fSAndroid Build Coastguard Worker     } else {
1721*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1722*38e8c45fSAndroid Build Coastguard Worker     }
1723*38e8c45fSAndroid Build Coastguard Worker 
1724*38e8c45fSAndroid Build Coastguard Worker     RunCommand("PRINTENV", {"printenv"});
1725*38e8c45fSAndroid Build Coastguard Worker     RunCommand("NETSTAT", {"netstat", "-nW"});
1726*38e8c45fSAndroid Build Coastguard Worker     struct stat s;
1727*38e8c45fSAndroid Build Coastguard Worker     if (stat("/proc/modules", &s) != 0) {
1728*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1729*38e8c45fSAndroid Build Coastguard Worker     } else {
1730*38e8c45fSAndroid Build Coastguard Worker         RunCommand("LSMOD", {"lsmod"});
1731*38e8c45fSAndroid Build Coastguard Worker         RunCommand("MODULES INFO",
1732*38e8c45fSAndroid Build Coastguard Worker                    {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1733*38e8c45fSAndroid Build Coastguard Worker                     "    while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1734*38e8c45fSAndroid Build Coastguard Worker                     "done"}, CommandOptions::AS_ROOT);
1735*38e8c45fSAndroid Build Coastguard Worker     }
1736*38e8c45fSAndroid Build Coastguard Worker 
1737*38e8c45fSAndroid Build Coastguard Worker     if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
1738*38e8c45fSAndroid Build Coastguard Worker         DoKernelLogcat();
1739*38e8c45fSAndroid Build Coastguard Worker     } else {
1740*38e8c45fSAndroid Build Coastguard Worker         do_dmesg();
1741*38e8c45fSAndroid Build Coastguard Worker     }
1742*38e8c45fSAndroid Build Coastguard Worker 
1743*38e8c45fSAndroid Build Coastguard Worker     DumpVintf();
1744*38e8c45fSAndroid Build Coastguard Worker 
1745*38e8c45fSAndroid Build Coastguard Worker     RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
1746*38e8c45fSAndroid Build Coastguard Worker 
1747*38e8c45fSAndroid Build Coastguard Worker     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
1748*38e8c45fSAndroid Build Coastguard Worker     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
1749*38e8c45fSAndroid Build Coastguard Worker 
1750*38e8c45fSAndroid Build Coastguard Worker     /* Dump Nfc NCI logs */
1751*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir("/data/misc/nfc/logs", true);
1752*38e8c45fSAndroid Build Coastguard Worker 
1753*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
1754*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("taking late screenshot\n");
1755*38e8c45fSAndroid Build Coastguard Worker         ds.TakeScreenshot();
1756*38e8c45fSAndroid Build Coastguard Worker     }
1757*38e8c45fSAndroid Build Coastguard Worker 
1758*38e8c45fSAndroid Build Coastguard Worker     AddAnrTraceFiles();
1759*38e8c45fSAndroid Build Coastguard Worker 
1760*38e8c45fSAndroid Build Coastguard Worker     MaybeAddSystemTraceToZip();
1761*38e8c45fSAndroid Build Coastguard Worker 
1762*38e8c45fSAndroid Build Coastguard Worker     // NOTE: tombstones are always added as separate entries in the zip archive
1763*38e8c45fSAndroid Build Coastguard Worker     // and are not interspersed with the main report.
1764*38e8c45fSAndroid Build Coastguard Worker     const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
1765*38e8c45fSAndroid Build Coastguard Worker                                             "TOMBSTONE", true /* add_to_zip */);
1766*38e8c45fSAndroid Build Coastguard Worker     if (!tombstones_dumped) {
1767*38e8c45fSAndroid Build Coastguard Worker         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
1768*38e8c45fSAndroid Build Coastguard Worker     }
1769*38e8c45fSAndroid Build Coastguard Worker 
1770*38e8c45fSAndroid Build Coastguard Worker     DumpPacketStats();
1771*38e8c45fSAndroid Build Coastguard Worker 
1772*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
1773*38e8c45fSAndroid Build Coastguard Worker 
1774*38e8c45fSAndroid Build Coastguard Worker     DoKmsg();
1775*38e8c45fSAndroid Build Coastguard Worker 
1776*38e8c45fSAndroid Build Coastguard Worker     DumpShutdownCheckpoints();
1777*38e8c45fSAndroid Build Coastguard Worker 
1778*38e8c45fSAndroid Build Coastguard Worker     DumpIpAddrAndRules();
1779*38e8c45fSAndroid Build Coastguard Worker 
1780*38e8c45fSAndroid Build Coastguard Worker     dump_route_tables();
1781*38e8c45fSAndroid Build Coastguard Worker 
1782*38e8c45fSAndroid Build Coastguard Worker     RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1783*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1784*38e8c45fSAndroid Build Coastguard Worker     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1785*38e8c45fSAndroid Build Coastguard Worker 
1786*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
1787*38e8c45fSAndroid Build Coastguard Worker 
1788*38e8c45fSAndroid Build Coastguard Worker     // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1789*38e8c45fSAndroid Build Coastguard Worker     // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1790*38e8c45fSAndroid Build Coastguard Worker     // dump with priority parameters to dump high priority information.
1791*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1792*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(10).Build());
1793*38e8c45fSAndroid Build Coastguard Worker 
1794*38e8c45fSAndroid Build Coastguard Worker     RunCommand("SYSTEM PROPERTIES", {"getprop"});
1795*38e8c45fSAndroid Build Coastguard Worker 
1796*38e8c45fSAndroid Build Coastguard Worker     DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1797*38e8c45fSAndroid Build Coastguard Worker     DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1798*38e8c45fSAndroid Build Coastguard Worker     DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1799*38e8c45fSAndroid Build Coastguard Worker     DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1800*38e8c45fSAndroid Build Coastguard Worker 
1801*38e8c45fSAndroid Build Coastguard Worker     RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1802*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1803*38e8c45fSAndroid Build Coastguard Worker     RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1804*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1805*38e8c45fSAndroid Build Coastguard Worker     RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
1806*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1807*38e8c45fSAndroid Build Coastguard Worker 
1808*38e8c45fSAndroid Build Coastguard Worker     RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
1809*38e8c45fSAndroid Build Coastguard Worker 
1810*38e8c45fSAndroid Build Coastguard Worker     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
1811*38e8c45fSAndroid Build Coastguard Worker 
1812*38e8c45fSAndroid Build Coastguard Worker     /* Binder state is expensive to look at as it uses a lot of memory. */
1813*38e8c45fSAndroid Build Coastguard Worker     std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1814*38e8c45fSAndroid Build Coastguard Worker             "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1815*38e8c45fSAndroid Build Coastguard Worker 
1816*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1817*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1818*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1819*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1820*38e8c45fSAndroid Build Coastguard Worker     DumpFile("BINDER STATE", binder_logs_dir + "/state");
1821*38e8c45fSAndroid Build Coastguard Worker 
1822*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1823*38e8c45fSAndroid Build Coastguard Worker 
1824*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1825*38e8c45fSAndroid Build Coastguard Worker         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
1826*38e8c45fSAndroid Build Coastguard Worker     } else {
1827*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1828*38e8c45fSAndroid Build Coastguard Worker     }
1829*38e8c45fSAndroid Build Coastguard Worker 
1830*38e8c45fSAndroid Build Coastguard Worker     /* Migrate the ril_dumpstate to a device specific dumpstate? */
1831*38e8c45fSAndroid Build Coastguard Worker     int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1832*38e8c45fSAndroid Build Coastguard Worker     if (rilDumpstateTimeout > 0) {
1833*38e8c45fSAndroid Build Coastguard Worker         // su does not exist on user builds, so try running without it.
1834*38e8c45fSAndroid Build Coastguard Worker         // This way any implementations of vril-dump that do not require
1835*38e8c45fSAndroid Build Coastguard Worker         // root can run on user builds.
1836*38e8c45fSAndroid Build Coastguard Worker         CommandOptions::CommandOptionsBuilder options =
1837*38e8c45fSAndroid Build Coastguard Worker             CommandOptions::WithTimeout(rilDumpstateTimeout);
1838*38e8c45fSAndroid Build Coastguard Worker         if (!PropertiesHelper::IsUserBuild()) {
1839*38e8c45fSAndroid Build Coastguard Worker             options.AsRoot();
1840*38e8c45fSAndroid Build Coastguard Worker         }
1841*38e8c45fSAndroid Build Coastguard Worker         RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
1842*38e8c45fSAndroid Build Coastguard Worker     }
1843*38e8c45fSAndroid Build Coastguard Worker 
1844*38e8c45fSAndroid Build Coastguard Worker     /* Dump USB information */
1845*38e8c45fSAndroid Build Coastguard Worker     RunCommand("typec_connector_class", {"typec_connector_class"},
1846*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1847*38e8c45fSAndroid Build Coastguard Worker     RunCommand("lsusb", {"lsusb"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1848*38e8c45fSAndroid Build Coastguard Worker 
1849*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1850*38e8c45fSAndroid Build Coastguard Worker     printf("== Android Framework Services\n");
1851*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1852*38e8c45fSAndroid Build Coastguard Worker 
1853*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
1854*38e8c45fSAndroid Build Coastguard Worker 
1855*38e8c45fSAndroid Build Coastguard Worker     /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1856*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir("/data/misc/bluetooth/logs", true);
1857*38e8c45fSAndroid Build Coastguard Worker 
1858*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1859*38e8c45fSAndroid Build Coastguard Worker         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
1860*38e8c45fSAndroid Build Coastguard Worker     } else {
1861*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1862*38e8c45fSAndroid Build Coastguard Worker     }
1863*38e8c45fSAndroid Build Coastguard Worker 
1864*38e8c45fSAndroid Build Coastguard Worker     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
1865*38e8c45fSAndroid Build Coastguard Worker 
1866*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1867*38e8c45fSAndroid Build Coastguard Worker     printf("== Dropbox crashes\n");
1868*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1869*38e8c45fSAndroid Build Coastguard Worker 
1870*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1871*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1872*38e8c45fSAndroid Build Coastguard Worker 
1873*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1874*38e8c45fSAndroid Build Coastguard Worker     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1875*38e8c45fSAndroid Build Coastguard Worker            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1876*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1877*38e8c45fSAndroid Build Coastguard Worker     printf("== dumpstate: done (id %d)\n", ds.id_);
1878*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1879*38e8c45fSAndroid Build Coastguard Worker 
1880*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1881*38e8c45fSAndroid Build Coastguard Worker     printf("== Obtaining statsd metadata\n");
1882*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
1883*38e8c45fSAndroid Build Coastguard Worker     // This differs from the usual dumpsys stats, which is the stats report data.
1884*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
1885*38e8c45fSAndroid Build Coastguard Worker 
1886*38e8c45fSAndroid Build Coastguard Worker     // Add linker configuration directory
1887*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(LINKERCONFIG_DIR, true);
1888*38e8c45fSAndroid Build Coastguard Worker 
1889*38e8c45fSAndroid Build Coastguard Worker     /* Dump frozen cgroupfs */
1890*38e8c45fSAndroid Build Coastguard Worker     dump_frozen_cgroupfs();
1891*38e8c45fSAndroid Build Coastguard Worker 
1892*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1893*38e8c45fSAndroid Build Coastguard Worker         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1894*38e8c45fSAndroid Build Coastguard Worker     } else {
1895*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1896*38e8c45fSAndroid Build Coastguard Worker                 DumpNetstatsProto);
1897*38e8c45fSAndroid Build Coastguard Worker     }
1898*38e8c45fSAndroid Build Coastguard Worker 
1899*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
1900*38e8c45fSAndroid Build Coastguard Worker         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
1901*38e8c45fSAndroid Build Coastguard Worker     } else {
1902*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1903*38e8c45fSAndroid Build Coastguard Worker                 DumpIncidentReport);
1904*38e8c45fSAndroid Build Coastguard Worker     }
1905*38e8c45fSAndroid Build Coastguard Worker 
1906*38e8c45fSAndroid Build Coastguard Worker     MaybeAddUiTracesToZip();
1907*38e8c45fSAndroid Build Coastguard Worker 
1908*38e8c45fSAndroid Build Coastguard Worker     return Dumpstate::RunStatus::OK;
1909*38e8c45fSAndroid Build Coastguard Worker }
1910*38e8c45fSAndroid Build Coastguard Worker 
1911*38e8c45fSAndroid Build Coastguard Worker /*
1912*38e8c45fSAndroid Build Coastguard Worker  * Dumps state for the default case; drops root after it's no longer necessary.
1913*38e8c45fSAndroid Build Coastguard Worker  *
1914*38e8c45fSAndroid Build Coastguard Worker  * Returns RunStatus::OK if everything went fine.
1915*38e8c45fSAndroid Build Coastguard Worker  * Returns RunStatus::ERROR if there was an error.
1916*38e8c45fSAndroid Build Coastguard Worker  * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1917*38e8c45fSAndroid Build Coastguard Worker  * with the caller.
1918*38e8c45fSAndroid Build Coastguard Worker  */
DumpstateDefaultAfterCritical()1919*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
1920*38e8c45fSAndroid Build Coastguard Worker     // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1921*38e8c45fSAndroid Build Coastguard Worker     // buffer.
1922*38e8c45fSAndroid Build Coastguard Worker     DoLogcat();
1923*38e8c45fSAndroid Build Coastguard Worker     // Capture timestamp after first logcat to use in next logcat
1924*38e8c45fSAndroid Build Coastguard Worker     time_t logcat_ts = time(nullptr);
1925*38e8c45fSAndroid Build Coastguard Worker 
1926*38e8c45fSAndroid Build Coastguard Worker     /* collect stack traces from Dalvik and native processes (needs root) */
1927*38e8c45fSAndroid Build Coastguard Worker     std::future<std::string> dump_traces;
1928*38e8c45fSAndroid Build Coastguard Worker     if (dump_pool_) {
1929*38e8c45fSAndroid Build Coastguard Worker         RETURN_IF_USER_DENIED_CONSENT();
1930*38e8c45fSAndroid Build Coastguard Worker         // One thread is enough since we only need to enqueue DumpTraces here.
1931*38e8c45fSAndroid Build Coastguard Worker         dump_pool_->start(/* thread_counts = */1);
1932*38e8c45fSAndroid Build Coastguard Worker 
1933*38e8c45fSAndroid Build Coastguard Worker         // DumpTraces takes long time, post it to the another thread in the
1934*38e8c45fSAndroid Build Coastguard Worker         // pool, if pool is available
1935*38e8c45fSAndroid Build Coastguard Worker         dump_traces = dump_pool_->enqueueTask(
1936*38e8c45fSAndroid Build Coastguard Worker             DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1937*38e8c45fSAndroid Build Coastguard Worker     } else {
1938*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1939*38e8c45fSAndroid Build Coastguard Worker                 &dump_traces_path);
1940*38e8c45fSAndroid Build Coastguard Worker     }
1941*38e8c45fSAndroid Build Coastguard Worker 
1942*38e8c45fSAndroid Build Coastguard Worker     /* Run some operations that require root. */
1943*38e8c45fSAndroid Build Coastguard Worker     if (!PropertiesHelper::IsDryRun()) {
1944*38e8c45fSAndroid Build Coastguard Worker         ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1945*38e8c45fSAndroid Build Coastguard Worker         ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
1946*38e8c45fSAndroid Build Coastguard Worker         ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
1947*38e8c45fSAndroid Build Coastguard Worker         ds.shutdown_checkpoints_ = GetDumpFds(
1948*38e8c45fSAndroid Build Coastguard Worker             SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
1949*38e8c45fSAndroid Build Coastguard Worker     }
1950*38e8c45fSAndroid Build Coastguard Worker 
1951*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(RECOVERY_DIR, true);
1952*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(RECOVERY_DATA_DIR, true);
1953*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1954*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
1955*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(LOGPERSIST_DATA_DIR, false);
1956*38e8c45fSAndroid Build Coastguard Worker     if (!PropertiesHelper::IsUserBuild()) {
1957*38e8c45fSAndroid Build Coastguard Worker         ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1958*38e8c45fSAndroid Build Coastguard Worker         ds.AddDir(PROFILE_DATA_DIR_REF, true);
1959*38e8c45fSAndroid Build Coastguard Worker         ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
1960*38e8c45fSAndroid Build Coastguard Worker     }
1961*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(PREREBOOT_DATA_DIR, false);
1962*38e8c45fSAndroid Build Coastguard Worker     add_mountinfo();
1963*38e8c45fSAndroid Build Coastguard Worker     for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1964*38e8c45fSAndroid Build Coastguard Worker         ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1965*38e8c45fSAndroid Build Coastguard Worker     }
1966*38e8c45fSAndroid Build Coastguard Worker     DumpIpTablesAsRoot();
1967*38e8c45fSAndroid Build Coastguard Worker     DumpDynamicPartitionInfo();
1968*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(OTA_METADATA_DIR, true);
1969*38e8c45fSAndroid Build Coastguard Worker     if (!PropertiesHelper::IsUserBuild()) {
1970*38e8c45fSAndroid Build Coastguard Worker         // Include dropbox entry files inside ZIP, but exclude
1971*38e8c45fSAndroid Build Coastguard Worker         // noisy WTF and StrictMode entries
1972*38e8c45fSAndroid Build Coastguard Worker         dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1973*38e8c45fSAndroid Build Coastguard Worker     }
1974*38e8c45fSAndroid Build Coastguard Worker 
1975*38e8c45fSAndroid Build Coastguard Worker     // Capture any IPSec policies in play. No keys are exposed here.
1976*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1977*38e8c45fSAndroid Build Coastguard Worker 
1978*38e8c45fSAndroid Build Coastguard Worker     // Dump IPsec stats. No keys are exposed here.
1979*38e8c45fSAndroid Build Coastguard Worker     DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1980*38e8c45fSAndroid Build Coastguard Worker 
1981*38e8c45fSAndroid Build Coastguard Worker     // Run ss as root so we can see socket marks.
1982*38e8c45fSAndroid Build Coastguard Worker     RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1983*38e8c45fSAndroid Build Coastguard Worker 
1984*38e8c45fSAndroid Build Coastguard Worker     // Run iotop as root to show top 100 IO threads
1985*38e8c45fSAndroid Build Coastguard Worker     RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1986*38e8c45fSAndroid Build Coastguard Worker 
1987*38e8c45fSAndroid Build Coastguard Worker     // Gather shared memory buffer info if the product implements it
1988*38e8c45fSAndroid Build Coastguard Worker     RunCommand("Dmabuf dump", {"dmabuf_dump"});
1989*38e8c45fSAndroid Build Coastguard Worker     RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
1990*38e8c45fSAndroid Build Coastguard Worker 
1991*38e8c45fSAndroid Build Coastguard Worker     DumpFile("PSI cpu", "/proc/pressure/cpu");
1992*38e8c45fSAndroid Build Coastguard Worker     DumpFile("PSI memory", "/proc/pressure/memory");
1993*38e8c45fSAndroid Build Coastguard Worker     DumpFile("PSI io", "/proc/pressure/io");
1994*38e8c45fSAndroid Build Coastguard Worker 
1995*38e8c45fSAndroid Build Coastguard Worker     ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1996*38e8c45fSAndroid Build Coastguard Worker 
1997*38e8c45fSAndroid Build Coastguard Worker     RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1998*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1999*38e8c45fSAndroid Build Coastguard Worker 
2000*38e8c45fSAndroid Build Coastguard Worker     // Dump UWB UCI logs here because apexdata requires root access
2001*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(UWB_LOG_DIR, true);
2002*38e8c45fSAndroid Build Coastguard Worker 
2003*38e8c45fSAndroid Build Coastguard Worker     if (dump_pool_) {
2004*38e8c45fSAndroid Build Coastguard Worker         RETURN_IF_USER_DENIED_CONSENT();
2005*38e8c45fSAndroid Build Coastguard Worker         WaitForTask(std::move(dump_traces));
2006*38e8c45fSAndroid Build Coastguard Worker 
2007*38e8c45fSAndroid Build Coastguard Worker         // Current running thread in the pool is the root user also. Delete
2008*38e8c45fSAndroid Build Coastguard Worker         // the pool and make a new one later to ensure none of threads in the pool are root.
2009*38e8c45fSAndroid Build Coastguard Worker         dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
2010*38e8c45fSAndroid Build Coastguard Worker     }
2011*38e8c45fSAndroid Build Coastguard Worker     if (!DropRootUser()) {
2012*38e8c45fSAndroid Build Coastguard Worker         return Dumpstate::RunStatus::ERROR;
2013*38e8c45fSAndroid Build Coastguard Worker     }
2014*38e8c45fSAndroid Build Coastguard Worker 
2015*38e8c45fSAndroid Build Coastguard Worker     RETURN_IF_USER_DENIED_CONSENT();
2016*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = dumpstate();
2017*38e8c45fSAndroid Build Coastguard Worker     // Capture logcat since the last time we did it.
2018*38e8c45fSAndroid Build Coastguard Worker     DoSystemLogcat(logcat_ts);
2019*38e8c45fSAndroid Build Coastguard Worker     return status;
2020*38e8c45fSAndroid Build Coastguard Worker }
2021*38e8c45fSAndroid Build Coastguard Worker 
2022*38e8c45fSAndroid Build Coastguard Worker // Common states for telephony and wifi which are needed to be collected before
2023*38e8c45fSAndroid Build Coastguard Worker // dumpstate drop the root user.
DumpstateRadioAsRoot()2024*38e8c45fSAndroid Build Coastguard Worker static void DumpstateRadioAsRoot() {
2025*38e8c45fSAndroid Build Coastguard Worker     DumpIpTablesAsRoot();
2026*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(LOGPERSIST_DATA_DIR, false);
2027*38e8c45fSAndroid Build Coastguard Worker }
2028*38e8c45fSAndroid Build Coastguard Worker 
2029*38e8c45fSAndroid Build Coastguard Worker // This method collects common dumpsys for telephony and wifi. Typically, wifi
2030*38e8c45fSAndroid Build Coastguard Worker // reports are fine to include all information, but telephony reports on user
2031*38e8c45fSAndroid Build Coastguard Worker // builds need to strip some content (see DumpstateTelephonyOnly).
DumpstateRadioCommon(bool include_sensitive_info=true)2032*38e8c45fSAndroid Build Coastguard Worker static void DumpstateRadioCommon(bool include_sensitive_info = true) {
2033*38e8c45fSAndroid Build Coastguard Worker     // We need to be picky about some stuff for telephony reports on user builds.
2034*38e8c45fSAndroid Build Coastguard Worker     if (!include_sensitive_info) {
2035*38e8c45fSAndroid Build Coastguard Worker         // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2036*38e8c45fSAndroid Build Coastguard Worker         DoRadioLogcat();
2037*38e8c45fSAndroid Build Coastguard Worker     } else {
2038*38e8c45fSAndroid Build Coastguard Worker         // DumpHals takes long time, post it to the another thread in the pool,
2039*38e8c45fSAndroid Build Coastguard Worker         // if pool is available.
2040*38e8c45fSAndroid Build Coastguard Worker         std::future<std::string> dump_hals;
2041*38e8c45fSAndroid Build Coastguard Worker         if (ds.dump_pool_) {
2042*38e8c45fSAndroid Build Coastguard Worker             dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
2043*38e8c45fSAndroid Build Coastguard Worker         }
2044*38e8c45fSAndroid Build Coastguard Worker         // Contains various system properties and process startup info.
2045*38e8c45fSAndroid Build Coastguard Worker         do_dmesg();
2046*38e8c45fSAndroid Build Coastguard Worker         // Logs other than the radio buffer may contain package/component names and potential PII.
2047*38e8c45fSAndroid Build Coastguard Worker         DoLogcat();
2048*38e8c45fSAndroid Build Coastguard Worker         // Too broad for connectivity problems.
2049*38e8c45fSAndroid Build Coastguard Worker         DoKmsg();
2050*38e8c45fSAndroid Build Coastguard Worker         // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2051*38e8c45fSAndroid Build Coastguard Worker         if (ds.dump_pool_) {
2052*38e8c45fSAndroid Build Coastguard Worker             WaitForTask(std::move(dump_hals));
2053*38e8c45fSAndroid Build Coastguard Worker         } else {
2054*38e8c45fSAndroid Build Coastguard Worker             RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2055*38e8c45fSAndroid Build Coastguard Worker         }
2056*38e8c45fSAndroid Build Coastguard Worker     }
2057*38e8c45fSAndroid Build Coastguard Worker 
2058*38e8c45fSAndroid Build Coastguard Worker     DumpPacketStats();
2059*38e8c45fSAndroid Build Coastguard Worker     DumpIpAddrAndRules();
2060*38e8c45fSAndroid Build Coastguard Worker     dump_route_tables();
2061*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2062*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10).Build());
2063*38e8c45fSAndroid Build Coastguard Worker }
2064*38e8c45fSAndroid Build Coastguard Worker 
2065*38e8c45fSAndroid Build Coastguard Worker // We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2066*38e8c45fSAndroid Build Coastguard Worker // + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2067*38e8c45fSAndroid Build Coastguard Worker // for what can be included on user builds: all reported information MUST directly relate to
2068*38e8c45fSAndroid Build Coastguard Worker // connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2069*38e8c45fSAndroid Build Coastguard Worker // information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2070*38e8c45fSAndroid Build Coastguard Worker // names are not), and MUST NOT contain logs of user application traffic.
2071*38e8c45fSAndroid Build Coastguard Worker // TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
DumpstateTelephonyOnly(const std::string & calling_package)2072*38e8c45fSAndroid Build Coastguard Worker static void DumpstateTelephonyOnly(const std::string& calling_package) {
2073*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMPSTATE");
2074*38e8c45fSAndroid Build Coastguard Worker 
2075*38e8c45fSAndroid Build Coastguard Worker     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
2076*38e8c45fSAndroid Build Coastguard Worker 
2077*38e8c45fSAndroid Build Coastguard Worker     const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
2078*38e8c45fSAndroid Build Coastguard Worker 
2079*38e8c45fSAndroid Build Coastguard Worker     DumpstateRadioAsRoot();
2080*38e8c45fSAndroid Build Coastguard Worker     if (!DropRootUser()) {
2081*38e8c45fSAndroid Build Coastguard Worker         return;
2082*38e8c45fSAndroid Build Coastguard Worker     }
2083*38e8c45fSAndroid Build Coastguard Worker 
2084*38e8c45fSAndroid Build Coastguard Worker     // Starts thread pool after the root user is dropped, and two additional threads
2085*38e8c45fSAndroid Build Coastguard Worker     // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
2086*38e8c45fSAndroid Build Coastguard Worker     std::future<std::string> dump_board;
2087*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
2088*38e8c45fSAndroid Build Coastguard Worker         ds.dump_pool_->start(/*thread_counts =*/2);
2089*38e8c45fSAndroid Build Coastguard Worker 
2090*38e8c45fSAndroid Build Coastguard Worker         // DumpstateBoard takes long time, post it to the another thread in the pool,
2091*38e8c45fSAndroid Build Coastguard Worker         // if pool is available.
2092*38e8c45fSAndroid Build Coastguard Worker         dump_board = ds.dump_pool_->enqueueTaskWithFd(
2093*38e8c45fSAndroid Build Coastguard Worker             DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
2094*38e8c45fSAndroid Build Coastguard Worker     }
2095*38e8c45fSAndroid Build Coastguard Worker 
2096*38e8c45fSAndroid Build Coastguard Worker     DumpstateRadioCommon(include_sensitive_info);
2097*38e8c45fSAndroid Build Coastguard Worker 
2098*38e8c45fSAndroid Build Coastguard Worker     if (include_sensitive_info) {
2099*38e8c45fSAndroid Build Coastguard Worker         // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2100*38e8c45fSAndroid Build Coastguard Worker         // really cherrypick all of the connectivity-related ones. Apps generally have no business
2101*38e8c45fSAndroid Build Coastguard Worker         // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2102*38e8c45fSAndroid Build Coastguard Worker         // way.
2103*38e8c45fSAndroid Build Coastguard Worker         RunCommand("SYSTEM PROPERTIES", {"getprop"});
2104*38e8c45fSAndroid Build Coastguard Worker     }
2105*38e8c45fSAndroid Build Coastguard Worker 
2106*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2107*38e8c45fSAndroid Build Coastguard Worker     printf("== Android Framework Services\n");
2108*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2109*38e8c45fSAndroid Build Coastguard Worker 
2110*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2111*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2112*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2113*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2114*38e8c45fSAndroid Build Coastguard Worker     if (include_sensitive_info) {
2115*38e8c45fSAndroid Build Coastguard Worker         // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2116*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2117*38e8c45fSAndroid Build Coastguard Worker                    SEC_TO_MSEC(10));
2118*38e8c45fSAndroid Build Coastguard Worker     } else {
2119*38e8c45fSAndroid Build Coastguard Worker         // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2120*38e8c45fSAndroid Build Coastguard Worker         // running dumpsys activity service all-non-platform below. Due to the increased output, we
2121*38e8c45fSAndroid Build Coastguard Worker         // give a higher timeout as well.
2122*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2123*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2124*38e8c45fSAndroid Build Coastguard Worker     }
2125*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2126*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2127*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
2128*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2129*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2130*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2131*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2132*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2133*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2134*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2135*38e8c45fSAndroid Build Coastguard Worker     if (include_sensitive_info) {
2136*38e8c45fSAndroid Build Coastguard Worker         // Contains raw IP addresses, omit from reports on user builds.
2137*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2138*38e8c45fSAndroid Build Coastguard Worker         // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2139*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2140*38e8c45fSAndroid Build Coastguard Worker                    SEC_TO_MSEC(10));
2141*38e8c45fSAndroid Build Coastguard Worker         // Contains package/component names, omit from reports on user builds.
2142*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2143*38e8c45fSAndroid Build Coastguard Worker                    SEC_TO_MSEC(10));
2144*38e8c45fSAndroid Build Coastguard Worker         // Contains package names, but should be relatively simple to remove them (also contains
2145*38e8c45fSAndroid Build Coastguard Worker         // UIDs already), omit from reports on user builds.
2146*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2147*38e8c45fSAndroid Build Coastguard Worker                    SEC_TO_MSEC(10));
2148*38e8c45fSAndroid Build Coastguard Worker     }
2149*38e8c45fSAndroid Build Coastguard Worker 
2150*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2151*38e8c45fSAndroid Build Coastguard Worker     printf("== Running Application Services\n");
2152*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2153*38e8c45fSAndroid Build Coastguard Worker 
2154*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2155*38e8c45fSAndroid Build Coastguard Worker 
2156*38e8c45fSAndroid Build Coastguard Worker     if (include_sensitive_info) {
2157*38e8c45fSAndroid Build Coastguard Worker         printf("========================================================\n");
2158*38e8c45fSAndroid Build Coastguard Worker         printf("== Running Application Services (non-platform)\n");
2159*38e8c45fSAndroid Build Coastguard Worker         printf("========================================================\n");
2160*38e8c45fSAndroid Build Coastguard Worker 
2161*38e8c45fSAndroid Build Coastguard Worker         // Contains package/component names and potential PII, omit from reports on user builds.
2162*38e8c45fSAndroid Build Coastguard Worker         // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2163*38e8c45fSAndroid Build Coastguard Worker         // carrier_config dumpsys instead.
2164*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2165*38e8c45fSAndroid Build Coastguard Worker                    DUMPSYS_COMPONENTS_OPTIONS);
2166*38e8c45fSAndroid Build Coastguard Worker 
2167*38e8c45fSAndroid Build Coastguard Worker         printf("========================================================\n");
2168*38e8c45fSAndroid Build Coastguard Worker         printf("== Checkins\n");
2169*38e8c45fSAndroid Build Coastguard Worker         printf("========================================================\n");
2170*38e8c45fSAndroid Build Coastguard Worker 
2171*38e8c45fSAndroid Build Coastguard Worker         // Contains package/component names, omit from reports on user builds.
2172*38e8c45fSAndroid Build Coastguard Worker         RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2173*38e8c45fSAndroid Build Coastguard Worker     }
2174*38e8c45fSAndroid Build Coastguard Worker 
2175*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2176*38e8c45fSAndroid Build Coastguard Worker     printf("== dumpstate: done (id %d)\n", ds.id_);
2177*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2178*38e8c45fSAndroid Build Coastguard Worker 
2179*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
2180*38e8c45fSAndroid Build Coastguard Worker         WaitForTask(std::move(dump_board));
2181*38e8c45fSAndroid Build Coastguard Worker     } else {
2182*38e8c45fSAndroid Build Coastguard Worker         RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2183*38e8c45fSAndroid Build Coastguard Worker     }
2184*38e8c45fSAndroid Build Coastguard Worker }
2185*38e8c45fSAndroid Build Coastguard Worker 
2186*38e8c45fSAndroid Build Coastguard Worker // This method collects dumpsys for wifi debugging only
DumpstateWifiOnly()2187*38e8c45fSAndroid Build Coastguard Worker static void DumpstateWifiOnly() {
2188*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMPSTATE");
2189*38e8c45fSAndroid Build Coastguard Worker 
2190*38e8c45fSAndroid Build Coastguard Worker     DumpstateRadioAsRoot();
2191*38e8c45fSAndroid Build Coastguard Worker     if (!DropRootUser()) {
2192*38e8c45fSAndroid Build Coastguard Worker         return;
2193*38e8c45fSAndroid Build Coastguard Worker     }
2194*38e8c45fSAndroid Build Coastguard Worker 
2195*38e8c45fSAndroid Build Coastguard Worker     // Starts thread pool after the root user is dropped. Only one additional
2196*38e8c45fSAndroid Build Coastguard Worker     // thread is needed for DumpHals in the DumpstateRadioCommon.
2197*38e8c45fSAndroid Build Coastguard Worker     if (ds.dump_pool_) {
2198*38e8c45fSAndroid Build Coastguard Worker         ds.dump_pool_->start(/*thread_counts =*/1);
2199*38e8c45fSAndroid Build Coastguard Worker     }
2200*38e8c45fSAndroid Build Coastguard Worker 
2201*38e8c45fSAndroid Build Coastguard Worker     DumpstateRadioCommon();
2202*38e8c45fSAndroid Build Coastguard Worker 
2203*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2204*38e8c45fSAndroid Build Coastguard Worker     printf("== Android Framework Services\n");
2205*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2206*38e8c45fSAndroid Build Coastguard Worker 
2207*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2208*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2209*38e8c45fSAndroid Build Coastguard Worker     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2210*38e8c45fSAndroid Build Coastguard Worker                SEC_TO_MSEC(10));
2211*38e8c45fSAndroid Build Coastguard Worker 
2212*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2213*38e8c45fSAndroid Build Coastguard Worker     printf("== dumpstate: done (id %d)\n", ds.id_);
2214*38e8c45fSAndroid Build Coastguard Worker     printf("========================================================\n");
2215*38e8c45fSAndroid Build Coastguard Worker }
2216*38e8c45fSAndroid Build Coastguard Worker 
2217*38e8c45fSAndroid Build Coastguard Worker // Collects a lightweight dumpstate to be used for debugging onboarding related flows.
DumpstateOnboardingOnly()2218*38e8c45fSAndroid Build Coastguard Worker static void DumpstateOnboardingOnly() {
2219*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(LOGPERSIST_DATA_DIR, false);
2220*38e8c45fSAndroid Build Coastguard Worker }
2221*38e8c45fSAndroid Build Coastguard Worker 
GetTimestamp(const timespec & ts)2222*38e8c45fSAndroid Build Coastguard Worker static std::string GetTimestamp(const timespec& ts) {
2223*38e8c45fSAndroid Build Coastguard Worker     tm tm;
2224*38e8c45fSAndroid Build Coastguard Worker     localtime_r(&ts.tv_sec, &tm);
2225*38e8c45fSAndroid Build Coastguard Worker 
2226*38e8c45fSAndroid Build Coastguard Worker     // Reserve enough space for the entire time string, includes the space
2227*38e8c45fSAndroid Build Coastguard Worker     // for the '\0' to make the calculations below easier by using size for
2228*38e8c45fSAndroid Build Coastguard Worker     // the total string size.
2229*38e8c45fSAndroid Build Coastguard Worker     std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2230*38e8c45fSAndroid Build Coastguard Worker     size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2231*38e8c45fSAndroid Build Coastguard Worker     if (n == 0) {
2232*38e8c45fSAndroid Build Coastguard Worker         return "TIMESTAMP FAILURE";
2233*38e8c45fSAndroid Build Coastguard Worker     }
2234*38e8c45fSAndroid Build Coastguard Worker     int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2235*38e8c45fSAndroid Build Coastguard Worker     if (num_chars > str.size() - n) {
2236*38e8c45fSAndroid Build Coastguard Worker         return "TIMESTAMP FAILURE";
2237*38e8c45fSAndroid Build Coastguard Worker     }
2238*38e8c45fSAndroid Build Coastguard Worker     n += static_cast<size_t>(num_chars);
2239*38e8c45fSAndroid Build Coastguard Worker     if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2240*38e8c45fSAndroid Build Coastguard Worker         return "TIMESTAMP FAILURE";
2241*38e8c45fSAndroid Build Coastguard Worker     }
2242*38e8c45fSAndroid Build Coastguard Worker     return str;
2243*38e8c45fSAndroid Build Coastguard Worker }
2244*38e8c45fSAndroid Build Coastguard Worker 
GetCmdline(pid_t pid)2245*38e8c45fSAndroid Build Coastguard Worker static std::string GetCmdline(pid_t pid) {
2246*38e8c45fSAndroid Build Coastguard Worker     std::string cmdline;
2247*38e8c45fSAndroid Build Coastguard Worker     if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2248*38e8c45fSAndroid Build Coastguard Worker                                          &cmdline)) {
2249*38e8c45fSAndroid Build Coastguard Worker         return "UNKNOWN";
2250*38e8c45fSAndroid Build Coastguard Worker     }
2251*38e8c45fSAndroid Build Coastguard Worker     // There are '\0' terminators between arguments, convert them to spaces.
2252*38e8c45fSAndroid Build Coastguard Worker     // But start by skipping all trailing '\0' values.
2253*38e8c45fSAndroid Build Coastguard Worker     size_t cur = cmdline.size() - 1;
2254*38e8c45fSAndroid Build Coastguard Worker     while (cur != 0 && cmdline[cur] == '\0') {
2255*38e8c45fSAndroid Build Coastguard Worker         cur--;
2256*38e8c45fSAndroid Build Coastguard Worker     }
2257*38e8c45fSAndroid Build Coastguard Worker     if (cur == 0) {
2258*38e8c45fSAndroid Build Coastguard Worker         return "UNKNOWN";
2259*38e8c45fSAndroid Build Coastguard Worker     }
2260*38e8c45fSAndroid Build Coastguard Worker     while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2261*38e8c45fSAndroid Build Coastguard Worker         cmdline[cur] = ' ';
2262*38e8c45fSAndroid Build Coastguard Worker     }
2263*38e8c45fSAndroid Build Coastguard Worker     return cmdline;
2264*38e8c45fSAndroid Build Coastguard Worker }
2265*38e8c45fSAndroid Build Coastguard Worker 
DumpPidHeader(int fd,pid_t pid,const timespec & ts)2266*38e8c45fSAndroid Build Coastguard Worker static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2267*38e8c45fSAndroid Build Coastguard Worker     // For consistency, the header to this message matches the one
2268*38e8c45fSAndroid Build Coastguard Worker     // dumped by debuggerd.
2269*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2270*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2271*38e8c45fSAndroid Build Coastguard Worker }
2272*38e8c45fSAndroid Build Coastguard Worker 
DumpPidFooter(int fd,pid_t pid)2273*38e8c45fSAndroid Build Coastguard Worker static void DumpPidFooter(int fd, pid_t pid) {
2274*38e8c45fSAndroid Build Coastguard Worker     // For consistency, the footer to this message matches the one
2275*38e8c45fSAndroid Build Coastguard Worker     // dumped by debuggerd.
2276*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "----- end %d -----\n", pid);
2277*38e8c45fSAndroid Build Coastguard Worker }
2278*38e8c45fSAndroid Build Coastguard Worker 
DumpBacktrace(int fd,pid_t pid,bool is_java_process)2279*38e8c45fSAndroid Build Coastguard Worker static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2280*38e8c45fSAndroid Build Coastguard Worker     int ret = dump_backtrace_to_file_timeout(
2281*38e8c45fSAndroid Build Coastguard Worker         pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2282*38e8c45fSAndroid Build Coastguard Worker     if (ret == -1 && is_java_process) {
2283*38e8c45fSAndroid Build Coastguard Worker         // Tried to unwind as a java process, try a native unwind.
2284*38e8c45fSAndroid Build Coastguard Worker         dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2285*38e8c45fSAndroid Build Coastguard Worker         ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2286*38e8c45fSAndroid Build Coastguard Worker     }
2287*38e8c45fSAndroid Build Coastguard Worker     return ret != -1;
2288*38e8c45fSAndroid Build Coastguard Worker }
2289*38e8c45fSAndroid Build Coastguard Worker 
DumpTraces(const char ** path)2290*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
2291*38e8c45fSAndroid Build Coastguard Worker     const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
2292*38e8c45fSAndroid Build Coastguard Worker     const size_t buf_size = temp_file_pattern.length() + 1;
2293*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2294*38e8c45fSAndroid Build Coastguard Worker     memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2295*38e8c45fSAndroid Build Coastguard Worker 
2296*38e8c45fSAndroid Build Coastguard Worker     // Create a new, empty file to receive all trace dumps.
2297*38e8c45fSAndroid Build Coastguard Worker     //
2298*38e8c45fSAndroid Build Coastguard Worker     // TODO: This can be simplified once we remove support for the old style
2299*38e8c45fSAndroid Build Coastguard Worker     // dumps. We can have a file descriptor passed in to dump_traces instead
2300*38e8c45fSAndroid Build Coastguard Worker     // of creating a file, closing it and then reopening it again.
2301*38e8c45fSAndroid Build Coastguard Worker     android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2302*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
2303*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
2304*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::OK;
2305*38e8c45fSAndroid Build Coastguard Worker     }
2306*38e8c45fSAndroid Build Coastguard Worker 
2307*38e8c45fSAndroid Build Coastguard Worker     // Nobody should have access to this temporary file except dumpstate, but we
2308*38e8c45fSAndroid Build Coastguard Worker     // temporarily grant 'read' to 'others' here because this file is created
2309*38e8c45fSAndroid Build Coastguard Worker     // when tombstoned is still running as root, but dumped after dropping. This
2310*38e8c45fSAndroid Build Coastguard Worker     // can go away once support for old style dumping has.
2311*38e8c45fSAndroid Build Coastguard Worker     const int chmod_ret = fchmod(fd, 0666);
2312*38e8c45fSAndroid Build Coastguard Worker     if (chmod_ret < 0) {
2313*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
2314*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::OK;
2315*38e8c45fSAndroid Build Coastguard Worker     }
2316*38e8c45fSAndroid Build Coastguard Worker 
2317*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2318*38e8c45fSAndroid Build Coastguard Worker     if (proc.get() == nullptr) {
2319*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("opendir /proc failed: %s\n", strerror(errno));
2320*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::OK;
2321*38e8c45fSAndroid Build Coastguard Worker     }
2322*38e8c45fSAndroid Build Coastguard Worker 
2323*38e8c45fSAndroid Build Coastguard Worker     // Number of times process dumping has timed out. If we encounter too many
2324*38e8c45fSAndroid Build Coastguard Worker     // failures, we'll give up.
2325*38e8c45fSAndroid Build Coastguard Worker     int timeout_failures = 0;
2326*38e8c45fSAndroid Build Coastguard Worker     bool dalvik_found = false;
2327*38e8c45fSAndroid Build Coastguard Worker 
2328*38e8c45fSAndroid Build Coastguard Worker     const std::set<int> hal_pids = get_interesting_pids();
2329*38e8c45fSAndroid Build Coastguard Worker 
2330*38e8c45fSAndroid Build Coastguard Worker     struct dirent* d;
2331*38e8c45fSAndroid Build Coastguard Worker     while ((d = readdir(proc.get()))) {
2332*38e8c45fSAndroid Build Coastguard Worker         RETURN_IF_USER_DENIED_CONSENT();
2333*38e8c45fSAndroid Build Coastguard Worker         int pid = atoi(d->d_name);
2334*38e8c45fSAndroid Build Coastguard Worker         if (pid <= 0) {
2335*38e8c45fSAndroid Build Coastguard Worker             continue;
2336*38e8c45fSAndroid Build Coastguard Worker         }
2337*38e8c45fSAndroid Build Coastguard Worker 
2338*38e8c45fSAndroid Build Coastguard Worker         const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2339*38e8c45fSAndroid Build Coastguard Worker         std::string exe;
2340*38e8c45fSAndroid Build Coastguard Worker         if (!android::base::Readlink(link_name, &exe)) {
2341*38e8c45fSAndroid Build Coastguard Worker             continue;
2342*38e8c45fSAndroid Build Coastguard Worker         }
2343*38e8c45fSAndroid Build Coastguard Worker 
2344*38e8c45fSAndroid Build Coastguard Worker         bool is_java_process;
2345*38e8c45fSAndroid Build Coastguard Worker         if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2346*38e8c45fSAndroid Build Coastguard Worker             // Don't bother dumping backtraces for the zygote.
2347*38e8c45fSAndroid Build Coastguard Worker             if (IsZygote(pid)) {
2348*38e8c45fSAndroid Build Coastguard Worker                 continue;
2349*38e8c45fSAndroid Build Coastguard Worker             }
2350*38e8c45fSAndroid Build Coastguard Worker 
2351*38e8c45fSAndroid Build Coastguard Worker             dalvik_found = true;
2352*38e8c45fSAndroid Build Coastguard Worker             is_java_process = true;
2353*38e8c45fSAndroid Build Coastguard Worker         } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2354*38e8c45fSAndroid Build Coastguard Worker             is_java_process = false;
2355*38e8c45fSAndroid Build Coastguard Worker         } else {
2356*38e8c45fSAndroid Build Coastguard Worker             // Probably a native process we don't care about, continue.
2357*38e8c45fSAndroid Build Coastguard Worker             continue;
2358*38e8c45fSAndroid Build Coastguard Worker         }
2359*38e8c45fSAndroid Build Coastguard Worker 
2360*38e8c45fSAndroid Build Coastguard Worker         // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2361*38e8c45fSAndroid Build Coastguard Worker         if (timeout_failures == 3) {
2362*38e8c45fSAndroid Build Coastguard Worker             dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2363*38e8c45fSAndroid Build Coastguard Worker             break;
2364*38e8c45fSAndroid Build Coastguard Worker         }
2365*38e8c45fSAndroid Build Coastguard Worker 
2366*38e8c45fSAndroid Build Coastguard Worker         timespec start_timespec;
2367*38e8c45fSAndroid Build Coastguard Worker         clock_gettime(CLOCK_REALTIME, &start_timespec);
2368*38e8c45fSAndroid Build Coastguard Worker         if (IsCached(pid)) {
2369*38e8c45fSAndroid Build Coastguard Worker             DumpPidHeader(fd, pid, start_timespec);
2370*38e8c45fSAndroid Build Coastguard Worker             dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2371*38e8c45fSAndroid Build Coastguard Worker             DumpPidFooter(fd, pid);
2372*38e8c45fSAndroid Build Coastguard Worker             continue;
2373*38e8c45fSAndroid Build Coastguard Worker         }
2374*38e8c45fSAndroid Build Coastguard Worker 
2375*38e8c45fSAndroid Build Coastguard Worker         const uint64_t start = Nanotime();
2376*38e8c45fSAndroid Build Coastguard Worker         if (!DumpBacktrace(fd, pid, is_java_process)) {
2377*38e8c45fSAndroid Build Coastguard Worker             if (IsCached(pid)) {
2378*38e8c45fSAndroid Build Coastguard Worker                 DumpPidHeader(fd, pid, start_timespec);
2379*38e8c45fSAndroid Build Coastguard Worker                 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2380*38e8c45fSAndroid Build Coastguard Worker                 DumpPidFooter(fd, pid);
2381*38e8c45fSAndroid Build Coastguard Worker                 continue;
2382*38e8c45fSAndroid Build Coastguard Worker             }
2383*38e8c45fSAndroid Build Coastguard Worker 
2384*38e8c45fSAndroid Build Coastguard Worker             DumpPidHeader(fd, pid, start_timespec);
2385*38e8c45fSAndroid Build Coastguard Worker             dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2386*38e8c45fSAndroid Build Coastguard Worker             DumpPidFooter(fd, pid);
2387*38e8c45fSAndroid Build Coastguard Worker 
2388*38e8c45fSAndroid Build Coastguard Worker             dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2389*38e8c45fSAndroid Build Coastguard Worker                     is_java_process ? "dalvik" : "native", pid,
2390*38e8c45fSAndroid Build Coastguard Worker                     (float)(Nanotime() - start) / NANOS_PER_SEC);
2391*38e8c45fSAndroid Build Coastguard Worker             timeout_failures++;
2392*38e8c45fSAndroid Build Coastguard Worker             continue;
2393*38e8c45fSAndroid Build Coastguard Worker         }
2394*38e8c45fSAndroid Build Coastguard Worker 
2395*38e8c45fSAndroid Build Coastguard Worker         // We've successfully dumped stack traces, reset the failure count
2396*38e8c45fSAndroid Build Coastguard Worker         // and write a summary of the elapsed time to the file and continue with the
2397*38e8c45fSAndroid Build Coastguard Worker         // next process.
2398*38e8c45fSAndroid Build Coastguard Worker         timeout_failures = 0;
2399*38e8c45fSAndroid Build Coastguard Worker 
2400*38e8c45fSAndroid Build Coastguard Worker         dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2401*38e8c45fSAndroid Build Coastguard Worker                 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2402*38e8c45fSAndroid Build Coastguard Worker     }
2403*38e8c45fSAndroid Build Coastguard Worker 
2404*38e8c45fSAndroid Build Coastguard Worker     if (!dalvik_found) {
2405*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2406*38e8c45fSAndroid Build Coastguard Worker     }
2407*38e8c45fSAndroid Build Coastguard Worker 
2408*38e8c45fSAndroid Build Coastguard Worker     *path = file_name_buf.release();
2409*38e8c45fSAndroid Build Coastguard Worker     return RunStatus::OK;
2410*38e8c45fSAndroid Build Coastguard Worker }
2411*38e8c45fSAndroid Build Coastguard Worker 
GetDumpstateHalModeHidl(const Dumpstate::BugreportMode bugreport_mode)2412*38e8c45fSAndroid Build Coastguard Worker static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2413*38e8c45fSAndroid Build Coastguard Worker     const Dumpstate::BugreportMode bugreport_mode) {
2414*38e8c45fSAndroid Build Coastguard Worker     switch (bugreport_mode) {
2415*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2416*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::FULL;
2417*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2418*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2419*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2420*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2421*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2422*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::WEAR;
2423*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2424*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2425*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2426*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::WIFI;
2427*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2428*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2429*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2430*38e8c45fSAndroid Build Coastguard Worker     }
2431*38e8c45fSAndroid Build Coastguard Worker     return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2432*38e8c45fSAndroid Build Coastguard Worker }
2433*38e8c45fSAndroid Build Coastguard Worker 
GetDumpstateHalModeAidl(const Dumpstate::BugreportMode bugreport_mode)2434*38e8c45fSAndroid Build Coastguard Worker static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2435*38e8c45fSAndroid Build Coastguard Worker     const Dumpstate::BugreportMode bugreport_mode) {
2436*38e8c45fSAndroid Build Coastguard Worker     switch (bugreport_mode) {
2437*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2438*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2439*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2440*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2441*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2442*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2443*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2444*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2445*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2446*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2447*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2448*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2449*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2450*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2451*38e8c45fSAndroid Build Coastguard Worker             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2452*38e8c45fSAndroid Build Coastguard Worker     }
2453*38e8c45fSAndroid Build Coastguard Worker     return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2454*38e8c45fSAndroid Build Coastguard Worker }
2455*38e8c45fSAndroid Build Coastguard Worker 
DoDumpstateBoardHidl(const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,const std::vector<::ndk::ScopedFileDescriptor> & dumpstate_fds,const Dumpstate::BugreportMode bugreport_mode,const size_t timeout_sec)2456*38e8c45fSAndroid Build Coastguard Worker static void DoDumpstateBoardHidl(
2457*38e8c45fSAndroid Build Coastguard Worker     const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2458*38e8c45fSAndroid Build Coastguard Worker     const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2459*38e8c45fSAndroid Build Coastguard Worker     const Dumpstate::BugreportMode bugreport_mode,
2460*38e8c45fSAndroid Build Coastguard Worker     const size_t timeout_sec) {
2461*38e8c45fSAndroid Build Coastguard Worker 
2462*38e8c45fSAndroid Build Coastguard Worker     using ScopedNativeHandle =
2463*38e8c45fSAndroid Build Coastguard Worker         std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2464*38e8c45fSAndroid Build Coastguard Worker     ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2465*38e8c45fSAndroid Build Coastguard Worker                               [](native_handle_t* handle) {
2466*38e8c45fSAndroid Build Coastguard Worker                                   // we don't close file handle's here
2467*38e8c45fSAndroid Build Coastguard Worker                                   // via native_handle_close(handle)
2468*38e8c45fSAndroid Build Coastguard Worker                                   // instead we let dumpstate_fds close the file handles when
2469*38e8c45fSAndroid Build Coastguard Worker                                   // dumpstate_fds gets destroyed
2470*38e8c45fSAndroid Build Coastguard Worker                                   native_handle_delete(handle);
2471*38e8c45fSAndroid Build Coastguard Worker                               });
2472*38e8c45fSAndroid Build Coastguard Worker     if (handle == nullptr) {
2473*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not create native_handle for dumpstate HAL\n");
2474*38e8c45fSAndroid Build Coastguard Worker         return;
2475*38e8c45fSAndroid Build Coastguard Worker     }
2476*38e8c45fSAndroid Build Coastguard Worker 
2477*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2478*38e8c45fSAndroid Build Coastguard Worker         handle.get()->data[i] = dumpstate_fds[i].get();
2479*38e8c45fSAndroid Build Coastguard Worker     }
2480*38e8c45fSAndroid Build Coastguard Worker 
2481*38e8c45fSAndroid Build Coastguard Worker     // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2482*38e8c45fSAndroid Build Coastguard Worker     // implement just 1.0.
2483*38e8c45fSAndroid Build Coastguard Worker     const char* descriptor_to_kill;
2484*38e8c45fSAndroid Build Coastguard Worker     using DumpstateBoardTask = std::packaged_task<bool()>;
2485*38e8c45fSAndroid Build Coastguard Worker     DumpstateBoardTask dumpstate_board_task;
2486*38e8c45fSAndroid Build Coastguard Worker     sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2487*38e8c45fSAndroid Build Coastguard Worker         dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2488*38e8c45fSAndroid Build Coastguard Worker     if (dumpstate_hal != nullptr) {
2489*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2490*38e8c45fSAndroid Build Coastguard Worker 
2491*38e8c45fSAndroid Build Coastguard Worker         dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2492*38e8c45fSAndroid Build Coastguard Worker             GetDumpstateHalModeHidl(bugreport_mode);
2493*38e8c45fSAndroid Build Coastguard Worker 
2494*38e8c45fSAndroid Build Coastguard Worker         descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2495*38e8c45fSAndroid Build Coastguard Worker         dumpstate_board_task =
2496*38e8c45fSAndroid Build Coastguard Worker             DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2497*38e8c45fSAndroid Build Coastguard Worker                 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2498*38e8c45fSAndroid Build Coastguard Worker                     dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2499*38e8c45fSAndroid Build Coastguard Worker                                                       SEC_TO_MSEC(timeout_sec));
2500*38e8c45fSAndroid Build Coastguard Worker                 if (!status.isOk()) {
2501*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2502*38e8c45fSAndroid Build Coastguard Worker                     return false;
2503*38e8c45fSAndroid Build Coastguard Worker                 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2504*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2505*38e8c45fSAndroid Build Coastguard Worker                            dumpstate_hal_hidl::toString(status).c_str());
2506*38e8c45fSAndroid Build Coastguard Worker                     return false;
2507*38e8c45fSAndroid Build Coastguard Worker                 }
2508*38e8c45fSAndroid Build Coastguard Worker                 return true;
2509*38e8c45fSAndroid Build Coastguard Worker             });
2510*38e8c45fSAndroid Build Coastguard Worker     } else {
2511*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2512*38e8c45fSAndroid Build Coastguard Worker 
2513*38e8c45fSAndroid Build Coastguard Worker         descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2514*38e8c45fSAndroid Build Coastguard Worker         dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2515*38e8c45fSAndroid Build Coastguard Worker             ::android::hardware::Return<void> status =
2516*38e8c45fSAndroid Build Coastguard Worker                 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2517*38e8c45fSAndroid Build Coastguard Worker             if (!status.isOk()) {
2518*38e8c45fSAndroid Build Coastguard Worker                 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2519*38e8c45fSAndroid Build Coastguard Worker                 return false;
2520*38e8c45fSAndroid Build Coastguard Worker             }
2521*38e8c45fSAndroid Build Coastguard Worker             return true;
2522*38e8c45fSAndroid Build Coastguard Worker         });
2523*38e8c45fSAndroid Build Coastguard Worker     }
2524*38e8c45fSAndroid Build Coastguard Worker     auto result = dumpstate_board_task.get_future();
2525*38e8c45fSAndroid Build Coastguard Worker     std::thread(std::move(dumpstate_board_task)).detach();
2526*38e8c45fSAndroid Build Coastguard Worker 
2527*38e8c45fSAndroid Build Coastguard Worker     if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2528*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2529*38e8c45fSAndroid Build Coastguard Worker         if (!android::base::SetProperty(
2530*38e8c45fSAndroid Build Coastguard Worker                 "ctl.interface_restart",
2531*38e8c45fSAndroid Build Coastguard Worker                 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2532*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Couldn't restart dumpstate HAL\n");
2533*38e8c45fSAndroid Build Coastguard Worker         }
2534*38e8c45fSAndroid Build Coastguard Worker     }
2535*38e8c45fSAndroid Build Coastguard Worker     // Wait some time for init to kill dumpstate vendor HAL
2536*38e8c45fSAndroid Build Coastguard Worker     constexpr size_t killing_timeout_sec = 10;
2537*38e8c45fSAndroid Build Coastguard Worker     if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2538*38e8c45fSAndroid Build Coastguard Worker         MYLOGE(
2539*38e8c45fSAndroid Build Coastguard Worker             "killing dumpstateBoard timed out after %zus, continue and "
2540*38e8c45fSAndroid Build Coastguard Worker             "there might be racing in content\n",
2541*38e8c45fSAndroid Build Coastguard Worker             killing_timeout_sec);
2542*38e8c45fSAndroid Build Coastguard Worker     }
2543*38e8c45fSAndroid Build Coastguard Worker }
2544*38e8c45fSAndroid Build Coastguard Worker 
DoDumpstateBoardAidl(const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,const std::vector<::ndk::ScopedFileDescriptor> & dumpstate_fds,const Dumpstate::BugreportMode bugreport_mode,const size_t timeout_sec)2545*38e8c45fSAndroid Build Coastguard Worker static void DoDumpstateBoardAidl(
2546*38e8c45fSAndroid Build Coastguard Worker     const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2547*38e8c45fSAndroid Build Coastguard Worker     const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2548*38e8c45fSAndroid Build Coastguard Worker     const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2549*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("Using IDumpstateDevice AIDL HAL");
2550*38e8c45fSAndroid Build Coastguard Worker 
2551*38e8c45fSAndroid Build Coastguard Worker     const char* descriptor_to_kill;
2552*38e8c45fSAndroid Build Coastguard Worker     using DumpstateBoardTask = std::packaged_task<bool()>;
2553*38e8c45fSAndroid Build Coastguard Worker     DumpstateBoardTask dumpstate_board_task;
2554*38e8c45fSAndroid Build Coastguard Worker     dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2555*38e8c45fSAndroid Build Coastguard Worker         GetDumpstateHalModeAidl(bugreport_mode);
2556*38e8c45fSAndroid Build Coastguard Worker 
2557*38e8c45fSAndroid Build Coastguard Worker     descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2558*38e8c45fSAndroid Build Coastguard Worker     dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2559*38e8c45fSAndroid Build Coastguard Worker                                                timeout_sec]() -> bool {
2560*38e8c45fSAndroid Build Coastguard Worker         auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2561*38e8c45fSAndroid Build Coastguard Worker 
2562*38e8c45fSAndroid Build Coastguard Worker         if (!status.isOk()) {
2563*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2564*38e8c45fSAndroid Build Coastguard Worker             return false;
2565*38e8c45fSAndroid Build Coastguard Worker         }
2566*38e8c45fSAndroid Build Coastguard Worker         return true;
2567*38e8c45fSAndroid Build Coastguard Worker     });
2568*38e8c45fSAndroid Build Coastguard Worker     auto result = dumpstate_board_task.get_future();
2569*38e8c45fSAndroid Build Coastguard Worker     std::thread(std::move(dumpstate_board_task)).detach();
2570*38e8c45fSAndroid Build Coastguard Worker 
2571*38e8c45fSAndroid Build Coastguard Worker     if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2572*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2573*38e8c45fSAndroid Build Coastguard Worker         if (!android::base::SetProperty(
2574*38e8c45fSAndroid Build Coastguard Worker                 "ctl.interface_restart",
2575*38e8c45fSAndroid Build Coastguard Worker                 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2576*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Couldn't restart dumpstate HAL\n");
2577*38e8c45fSAndroid Build Coastguard Worker         }
2578*38e8c45fSAndroid Build Coastguard Worker     }
2579*38e8c45fSAndroid Build Coastguard Worker     // Wait some time for init to kill dumpstate vendor HAL
2580*38e8c45fSAndroid Build Coastguard Worker     constexpr size_t killing_timeout_sec = 10;
2581*38e8c45fSAndroid Build Coastguard Worker     if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2582*38e8c45fSAndroid Build Coastguard Worker         MYLOGE(
2583*38e8c45fSAndroid Build Coastguard Worker             "killing dumpstateBoard timed out after %zus, continue and "
2584*38e8c45fSAndroid Build Coastguard Worker             "there might be racing in content\n",
2585*38e8c45fSAndroid Build Coastguard Worker             killing_timeout_sec);
2586*38e8c45fSAndroid Build Coastguard Worker     }
2587*38e8c45fSAndroid Build Coastguard Worker }
2588*38e8c45fSAndroid Build Coastguard Worker 
GetDumpstateBoardAidlService()2589*38e8c45fSAndroid Build Coastguard Worker static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2590*38e8c45fSAndroid Build Coastguard Worker     const std::string aidl_instance_name =
2591*38e8c45fSAndroid Build Coastguard Worker         std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2592*38e8c45fSAndroid Build Coastguard Worker 
2593*38e8c45fSAndroid Build Coastguard Worker     if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2594*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
2595*38e8c45fSAndroid Build Coastguard Worker     }
2596*38e8c45fSAndroid Build Coastguard Worker 
2597*38e8c45fSAndroid Build Coastguard Worker     ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2598*38e8c45fSAndroid Build Coastguard Worker 
2599*38e8c45fSAndroid Build Coastguard Worker     return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2600*38e8c45fSAndroid Build Coastguard Worker }
2601*38e8c45fSAndroid Build Coastguard Worker 
DumpstateBoard(int out_fd)2602*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::DumpstateBoard(int out_fd) {
2603*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
2604*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "== Board\n");
2605*38e8c45fSAndroid Build Coastguard Worker     dprintf(out_fd, "========================================================\n");
2606*38e8c45fSAndroid Build Coastguard Worker 
2607*38e8c45fSAndroid Build Coastguard Worker     /*
2608*38e8c45fSAndroid Build Coastguard Worker      * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
2609*38e8c45fSAndroid Build Coastguard Worker      * set to true and unmount it after invoking dumpstateBoard_* methods.
2610*38e8c45fSAndroid Build Coastguard Worker      * This is to enable debug builds to not have debugfs mounted during runtime.
2611*38e8c45fSAndroid Build Coastguard Worker      * It will also ensure that debugfs is only accessed by the dumpstate HAL.
2612*38e8c45fSAndroid Build Coastguard Worker      */
2613*38e8c45fSAndroid Build Coastguard Worker     auto mount_debugfs =
2614*38e8c45fSAndroid Build Coastguard Worker         android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
2615*38e8c45fSAndroid Build Coastguard Worker     if (mount_debugfs) {
2616*38e8c45fSAndroid Build Coastguard Worker         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2617*38e8c45fSAndroid Build Coastguard Worker                    AS_ROOT_20);
2618*38e8c45fSAndroid Build Coastguard Worker         RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
2619*38e8c45fSAndroid Build Coastguard Worker     }
2620*38e8c45fSAndroid Build Coastguard Worker 
2621*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> paths;
2622*38e8c45fSAndroid Build Coastguard Worker     std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
2623*38e8c45fSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_OF_DUMPS; i++) {
2624*38e8c45fSAndroid Build Coastguard Worker         paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2625*38e8c45fSAndroid Build Coastguard Worker                                         kDumpstateBoardFiles[i].c_str()));
2626*38e8c45fSAndroid Build Coastguard Worker         remover.emplace_back(android::base::make_scope_guard(
2627*38e8c45fSAndroid Build Coastguard Worker             std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
2628*38e8c45fSAndroid Build Coastguard Worker     }
2629*38e8c45fSAndroid Build Coastguard Worker 
2630*38e8c45fSAndroid Build Coastguard Worker     // get dumpstate HAL AIDL implementation
2631*38e8c45fSAndroid Build Coastguard Worker     std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2632*38e8c45fSAndroid Build Coastguard Worker         GetDumpstateBoardAidlService());
2633*38e8c45fSAndroid Build Coastguard Worker     if (dumpstate_hal_handle_aidl == nullptr) {
2634*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("No IDumpstateDevice AIDL implementation\n");
2635*38e8c45fSAndroid Build Coastguard Worker     }
2636*38e8c45fSAndroid Build Coastguard Worker 
2637*38e8c45fSAndroid Build Coastguard Worker     // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2638*38e8c45fSAndroid Build Coastguard Worker     sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2639*38e8c45fSAndroid Build Coastguard Worker     if (dumpstate_hal_handle_aidl == nullptr) {
2640*38e8c45fSAndroid Build Coastguard Worker         dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2641*38e8c45fSAndroid Build Coastguard Worker         if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2642*38e8c45fSAndroid Build Coastguard Worker             MYLOGI("No IDumpstateDevice HIDL implementation\n");
2643*38e8c45fSAndroid Build Coastguard Worker         }
2644*38e8c45fSAndroid Build Coastguard Worker     }
2645*38e8c45fSAndroid Build Coastguard Worker 
2646*38e8c45fSAndroid Build Coastguard Worker     // if neither HIDL nor AIDL implementation found, then return
2647*38e8c45fSAndroid Build Coastguard Worker     if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2648*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not find IDumpstateDevice implementation\n");
2649*38e8c45fSAndroid Build Coastguard Worker         return;
2650*38e8c45fSAndroid Build Coastguard Worker     }
2651*38e8c45fSAndroid Build Coastguard Worker 
2652*38e8c45fSAndroid Build Coastguard Worker     // this is used to hold the file descriptors and when this variable goes out of scope
2653*38e8c45fSAndroid Build Coastguard Worker     // the file descriptors are closed
2654*38e8c45fSAndroid Build Coastguard Worker     std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
2655*38e8c45fSAndroid Build Coastguard Worker 
2656*38e8c45fSAndroid Build Coastguard Worker     // TODO(128270426): Check for consent in between?
2657*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < paths.size(); i++) {
2658*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2659*38e8c45fSAndroid Build Coastguard Worker 
2660*38e8c45fSAndroid Build Coastguard Worker         android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2661*38e8c45fSAndroid Build Coastguard Worker             open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2662*38e8c45fSAndroid Build Coastguard Worker                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2663*38e8c45fSAndroid Build Coastguard Worker         if (fd < 0) {
2664*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2665*38e8c45fSAndroid Build Coastguard Worker             return;
2666*38e8c45fSAndroid Build Coastguard Worker         }
2667*38e8c45fSAndroid Build Coastguard Worker 
2668*38e8c45fSAndroid Build Coastguard Worker         dumpstate_fds.emplace_back(fd.release());
2669*38e8c45fSAndroid Build Coastguard Worker         // we call fd.release() here to make sure "fd" does not get closed
2670*38e8c45fSAndroid Build Coastguard Worker         // after "fd" goes out of scope after this block.
2671*38e8c45fSAndroid Build Coastguard Worker         // "fd" will be closed when "dumpstate_fds" goes out of scope
2672*38e8c45fSAndroid Build Coastguard Worker         // i.e. when we exit this function
2673*38e8c45fSAndroid Build Coastguard Worker     }
2674*38e8c45fSAndroid Build Coastguard Worker 
2675*38e8c45fSAndroid Build Coastguard Worker     // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2676*38e8c45fSAndroid Build Coastguard Worker     // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2677*38e8c45fSAndroid Build Coastguard Worker     // will kill the HAL and grab whatever it dumped in time.
2678*38e8c45fSAndroid Build Coastguard Worker     constexpr size_t timeout_sec = 45;
2679*38e8c45fSAndroid Build Coastguard Worker 
2680*38e8c45fSAndroid Build Coastguard Worker     if (dumpstate_hal_handle_aidl != nullptr) {
2681*38e8c45fSAndroid Build Coastguard Worker         DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2682*38e8c45fSAndroid Build Coastguard Worker                              timeout_sec);
2683*38e8c45fSAndroid Build Coastguard Worker     } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2684*38e8c45fSAndroid Build Coastguard Worker         // run HIDL HAL only if AIDL HAL not found
2685*38e8c45fSAndroid Build Coastguard Worker         DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2686*38e8c45fSAndroid Build Coastguard Worker                              timeout_sec);
2687*38e8c45fSAndroid Build Coastguard Worker     }
2688*38e8c45fSAndroid Build Coastguard Worker 
2689*38e8c45fSAndroid Build Coastguard Worker     if (mount_debugfs) {
2690*38e8c45fSAndroid Build Coastguard Worker         auto keep_debugfs_mounted =
2691*38e8c45fSAndroid Build Coastguard Worker             android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2692*38e8c45fSAndroid Build Coastguard Worker         if (keep_debugfs_mounted.empty())
2693*38e8c45fSAndroid Build Coastguard Worker             RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
2694*38e8c45fSAndroid Build Coastguard Worker     }
2695*38e8c45fSAndroid Build Coastguard Worker 
2696*38e8c45fSAndroid Build Coastguard Worker     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2697*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < paths.size(); i++) {
2698*38e8c45fSAndroid Build Coastguard Worker         struct stat s;
2699*38e8c45fSAndroid Build Coastguard Worker         if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2700*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
2701*38e8c45fSAndroid Build Coastguard Worker             file_sizes[i] = -1;
2702*38e8c45fSAndroid Build Coastguard Worker             continue;
2703*38e8c45fSAndroid Build Coastguard Worker         }
2704*38e8c45fSAndroid Build Coastguard Worker         file_sizes[i] = s.st_size;
2705*38e8c45fSAndroid Build Coastguard Worker     }
2706*38e8c45fSAndroid Build Coastguard Worker 
2707*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < paths.size(); i++) {
2708*38e8c45fSAndroid Build Coastguard Worker         if (file_sizes[i] == -1) {
2709*38e8c45fSAndroid Build Coastguard Worker             continue;
2710*38e8c45fSAndroid Build Coastguard Worker         }
2711*38e8c45fSAndroid Build Coastguard Worker         if (file_sizes[i] == 0) {
2712*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
2713*38e8c45fSAndroid Build Coastguard Worker             continue;
2714*38e8c45fSAndroid Build Coastguard Worker         }
2715*38e8c45fSAndroid Build Coastguard Worker         remover[i].Disable();
2716*38e8c45fSAndroid Build Coastguard Worker         EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2717*38e8c45fSAndroid Build Coastguard Worker         dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
2718*38e8c45fSAndroid Build Coastguard Worker     }
2719*38e8c45fSAndroid Build Coastguard Worker }
2720*38e8c45fSAndroid Build Coastguard Worker 
ShowUsage()2721*38e8c45fSAndroid Build Coastguard Worker static void ShowUsage() {
2722*38e8c45fSAndroid Build Coastguard Worker     fprintf(stderr,
2723*38e8c45fSAndroid Build Coastguard Worker             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2724*38e8c45fSAndroid Build Coastguard Worker             "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
2725*38e8c45fSAndroid Build Coastguard Worker             "  -h: display this help message\n"
2726*38e8c45fSAndroid Build Coastguard Worker             "  -b: play sound file instead of vibrate, at beginning of job\n"
2727*38e8c45fSAndroid Build Coastguard Worker             "  -e: play sound file instead of vibrate, at end of job\n"
2728*38e8c45fSAndroid Build Coastguard Worker             "  -o: write to custom directory (only in limited mode)\n"
2729*38e8c45fSAndroid Build Coastguard Worker             "  -p: capture screenshot to filename.png\n"
2730*38e8c45fSAndroid Build Coastguard Worker             "  -s: write zipped file to control socket (for init)\n"
2731*38e8c45fSAndroid Build Coastguard Worker             "  -S: write file location to control socket (for init)\n"
2732*38e8c45fSAndroid Build Coastguard Worker             "  -q: disable vibrate\n"
2733*38e8c45fSAndroid Build Coastguard Worker             "  -P: send broadcast when started and do progress updates\n"
2734*38e8c45fSAndroid Build Coastguard Worker             "  -R: take bugreport in remote mode (shouldn't be used with -P)\n"
2735*38e8c45fSAndroid Build Coastguard Worker             "  -w: start binder service and make it wait for a call to startBugreport\n"
2736*38e8c45fSAndroid Build Coastguard Worker             "  -L: output limited information that is safe for submission in feedback reports\n"
2737*38e8c45fSAndroid Build Coastguard Worker             "  -v: prints the dumpstate header and exit\n");
2738*38e8c45fSAndroid Build Coastguard Worker }
2739*38e8c45fSAndroid Build Coastguard Worker 
register_sig_handler()2740*38e8c45fSAndroid Build Coastguard Worker static void register_sig_handler() {
2741*38e8c45fSAndroid Build Coastguard Worker     signal(SIGPIPE, SIG_IGN);
2742*38e8c45fSAndroid Build Coastguard Worker }
2743*38e8c45fSAndroid Build Coastguard Worker 
FinishZipFile()2744*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::FinishZipFile() {
2745*38e8c45fSAndroid Build Coastguard Worker     // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2746*38e8c45fSAndroid Build Coastguard Worker     if (zip_entry_tasks_) {
2747*38e8c45fSAndroid Build Coastguard Worker         zip_entry_tasks_->run(/* do_cancel = */false);
2748*38e8c45fSAndroid Build Coastguard Worker     }
2749*38e8c45fSAndroid Build Coastguard Worker 
2750*38e8c45fSAndroid Build Coastguard Worker     std::string entry_name = base_name_ + "-" + name_ + ".txt";
2751*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
2752*38e8c45fSAndroid Build Coastguard Worker            tmp_path_.c_str());
2753*38e8c45fSAndroid Build Coastguard Worker     // Final timestamp
2754*38e8c45fSAndroid Build Coastguard Worker     char date[80];
2755*38e8c45fSAndroid Build Coastguard Worker     time_t the_real_now_please_stand_up = time(nullptr);
2756*38e8c45fSAndroid Build Coastguard Worker     strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
2757*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
2758*38e8c45fSAndroid Build Coastguard Worker            the_real_now_please_stand_up - ds.now_);
2759*38e8c45fSAndroid Build Coastguard Worker 
2760*38e8c45fSAndroid Build Coastguard Worker     if (!ds.AddZipEntry(entry_name, tmp_path_)) {
2761*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to add text entry to .zip file\n");
2762*38e8c45fSAndroid Build Coastguard Worker         return false;
2763*38e8c45fSAndroid Build Coastguard Worker     }
2764*38e8c45fSAndroid Build Coastguard Worker     if (!AddTextZipEntry("main_entry.txt", entry_name)) {
2765*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to add main_entry.txt to .zip file\n");
2766*38e8c45fSAndroid Build Coastguard Worker         return false;
2767*38e8c45fSAndroid Build Coastguard Worker     }
2768*38e8c45fSAndroid Build Coastguard Worker 
2769*38e8c45fSAndroid Build Coastguard Worker     // Add log file (which contains stderr output) to zip...
2770*38e8c45fSAndroid Build Coastguard Worker     fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
2771*38e8c45fSAndroid Build Coastguard Worker     if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
2772*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to add dumpstate log to .zip file\n");
2773*38e8c45fSAndroid Build Coastguard Worker         return false;
2774*38e8c45fSAndroid Build Coastguard Worker     }
2775*38e8c45fSAndroid Build Coastguard Worker     // TODO: Should truncate the existing file.
2776*38e8c45fSAndroid Build Coastguard Worker     // ... and re-open it for further logging.
2777*38e8c45fSAndroid Build Coastguard Worker     if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2778*38e8c45fSAndroid Build Coastguard Worker         return false;
2779*38e8c45fSAndroid Build Coastguard Worker     }
2780*38e8c45fSAndroid Build Coastguard Worker     fprintf(stderr, "\n");
2781*38e8c45fSAndroid Build Coastguard Worker 
2782*38e8c45fSAndroid Build Coastguard Worker     int32_t err = zip_writer_->Finish();
2783*38e8c45fSAndroid Build Coastguard Worker     if (err != 0) {
2784*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
2785*38e8c45fSAndroid Build Coastguard Worker         return false;
2786*38e8c45fSAndroid Build Coastguard Worker     }
2787*38e8c45fSAndroid Build Coastguard Worker 
2788*38e8c45fSAndroid Build Coastguard Worker     // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2789*38e8c45fSAndroid Build Coastguard Worker     ds.zip_file.reset(nullptr);
2790*38e8c45fSAndroid Build Coastguard Worker 
2791*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
2792*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(tmp_path_);
2793*38e8c45fSAndroid Build Coastguard Worker 
2794*38e8c45fSAndroid Build Coastguard Worker     return true;
2795*38e8c45fSAndroid Build Coastguard Worker }
2796*38e8c45fSAndroid Build Coastguard Worker 
SendBroadcast(const std::string & action,const std::vector<std::string> & args,int32_t user_id)2797*38e8c45fSAndroid Build Coastguard Worker static void SendBroadcast(const std::string& action,
2798*38e8c45fSAndroid Build Coastguard Worker                           const std::vector<std::string>& args,
2799*38e8c45fSAndroid Build Coastguard Worker                           int32_t user_id) {
2800*38e8c45fSAndroid Build Coastguard Worker     // clang-format off
2801*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2802*38e8c45fSAndroid Build Coastguard Worker                         std::to_string(user_id), "--receiver-foreground",
2803*38e8c45fSAndroid Build Coastguard Worker                         "--receiver-include-background", "-a", action};
2804*38e8c45fSAndroid Build Coastguard Worker     // clang-format on
2805*38e8c45fSAndroid Build Coastguard Worker 
2806*38e8c45fSAndroid Build Coastguard Worker     am.insert(am.end(), args.begin(), args.end());
2807*38e8c45fSAndroid Build Coastguard Worker 
2808*38e8c45fSAndroid Build Coastguard Worker     RunCommand("", am,
2809*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(20)
2810*38e8c45fSAndroid Build Coastguard Worker                    .Log("Sending broadcast: '%s'\n")
2811*38e8c45fSAndroid Build Coastguard Worker                    .Always()
2812*38e8c45fSAndroid Build Coastguard Worker                    .DropRoot()
2813*38e8c45fSAndroid Build Coastguard Worker                    .RedirectStderr()
2814*38e8c45fSAndroid Build Coastguard Worker                    .Build());
2815*38e8c45fSAndroid Build Coastguard Worker }
2816*38e8c45fSAndroid Build Coastguard Worker 
Vibrate(int duration_ms)2817*38e8c45fSAndroid Build Coastguard Worker static void Vibrate(int duration_ms) {
2818*38e8c45fSAndroid Build Coastguard Worker     // clang-format off
2819*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2820*38e8c45fSAndroid Build Coastguard Worker                                      "oneshot", std::to_string(duration_ms)};
2821*38e8c45fSAndroid Build Coastguard Worker     RunCommand("", args,
2822*38e8c45fSAndroid Build Coastguard Worker                CommandOptions::WithTimeout(10)
2823*38e8c45fSAndroid Build Coastguard Worker                    .Log("Vibrate: '%s'\n")
2824*38e8c45fSAndroid Build Coastguard Worker                    .Always()
2825*38e8c45fSAndroid Build Coastguard Worker                    .Build());
2826*38e8c45fSAndroid Build Coastguard Worker     // clang-format on
2827*38e8c45fSAndroid Build Coastguard Worker }
2828*38e8c45fSAndroid Build Coastguard Worker 
MaybeResolveSymlink(std::string * path)2829*38e8c45fSAndroid Build Coastguard Worker static void MaybeResolveSymlink(std::string* path) {
2830*38e8c45fSAndroid Build Coastguard Worker     std::string resolved_path;
2831*38e8c45fSAndroid Build Coastguard Worker     if (android::base::Readlink(*path, &resolved_path)) {
2832*38e8c45fSAndroid Build Coastguard Worker         *path = resolved_path;
2833*38e8c45fSAndroid Build Coastguard Worker     }
2834*38e8c45fSAndroid Build Coastguard Worker }
2835*38e8c45fSAndroid Build Coastguard Worker 
2836*38e8c45fSAndroid Build Coastguard Worker /*
2837*38e8c45fSAndroid Build Coastguard Worker  * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2838*38e8c45fSAndroid Build Coastguard Worker  * and adds the version file. Return false if zip_file could not be open to write.
2839*38e8c45fSAndroid Build Coastguard Worker  */
PrepareToWriteToFile()2840*38e8c45fSAndroid Build Coastguard Worker static bool PrepareToWriteToFile() {
2841*38e8c45fSAndroid Build Coastguard Worker     MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2842*38e8c45fSAndroid Build Coastguard Worker 
2843*38e8c45fSAndroid Build Coastguard Worker     std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2844*38e8c45fSAndroid Build Coastguard Worker     std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
2845*38e8c45fSAndroid Build Coastguard Worker     ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
2846*38e8c45fSAndroid Build Coastguard Worker     char date[80];
2847*38e8c45fSAndroid Build Coastguard Worker     strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2848*38e8c45fSAndroid Build Coastguard Worker     ds.name_ = date;
2849*38e8c45fSAndroid Build Coastguard Worker 
2850*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->telephony_only) {
2851*38e8c45fSAndroid Build Coastguard Worker         ds.base_name_ += "-telephony";
2852*38e8c45fSAndroid Build Coastguard Worker     } else if (ds.options_->wifi_only) {
2853*38e8c45fSAndroid Build Coastguard Worker         ds.base_name_ += "-wifi";
2854*38e8c45fSAndroid Build Coastguard Worker     }
2855*38e8c45fSAndroid Build Coastguard Worker 
2856*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->do_screenshot) {
2857*38e8c45fSAndroid Build Coastguard Worker         ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
2858*38e8c45fSAndroid Build Coastguard Worker     }
2859*38e8c45fSAndroid Build Coastguard Worker     ds.tmp_path_ = ds.GetPath(".tmp");
2860*38e8c45fSAndroid Build Coastguard Worker     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2861*38e8c45fSAndroid Build Coastguard Worker 
2862*38e8c45fSAndroid Build Coastguard Worker     std::string destination = ds.CalledByApi()
2863*38e8c45fSAndroid Build Coastguard Worker                                   ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
2864*38e8c45fSAndroid Build Coastguard Worker                                   : ds.bugreport_internal_dir_.c_str();
2865*38e8c45fSAndroid Build Coastguard Worker     MYLOGD(
2866*38e8c45fSAndroid Build Coastguard Worker         "Bugreport dir: [%s] "
2867*38e8c45fSAndroid Build Coastguard Worker         "Base name: [%s] "
2868*38e8c45fSAndroid Build Coastguard Worker         "Suffix: [%s] "
2869*38e8c45fSAndroid Build Coastguard Worker         "Log path: [%s] "
2870*38e8c45fSAndroid Build Coastguard Worker         "Temporary path: [%s] "
2871*38e8c45fSAndroid Build Coastguard Worker         "Screenshot path: [%s]\n",
2872*38e8c45fSAndroid Build Coastguard Worker         destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2873*38e8c45fSAndroid Build Coastguard Worker         ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
2874*38e8c45fSAndroid Build Coastguard Worker 
2875*38e8c45fSAndroid Build Coastguard Worker     ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2876*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2877*38e8c45fSAndroid Build Coastguard Worker     create_parent_dirs(ds.path_.c_str());
2878*38e8c45fSAndroid Build Coastguard Worker     ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2879*38e8c45fSAndroid Build Coastguard Worker     if (ds.zip_file == nullptr) {
2880*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2881*38e8c45fSAndroid Build Coastguard Worker         return false;
2882*38e8c45fSAndroid Build Coastguard Worker     }
2883*38e8c45fSAndroid Build Coastguard Worker     ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2884*38e8c45fSAndroid Build Coastguard Worker     ds.AddTextZipEntry("version.txt", ds.version_);
2885*38e8c45fSAndroid Build Coastguard Worker     return true;
2886*38e8c45fSAndroid Build Coastguard Worker }
2887*38e8c45fSAndroid Build Coastguard Worker 
2888*38e8c45fSAndroid Build Coastguard Worker /*
2889*38e8c45fSAndroid Build Coastguard Worker  * Finalizes writing to the file by zipping the tmp file to the final location,
2890*38e8c45fSAndroid Build Coastguard Worker  * printing zipped file status, etc.
2891*38e8c45fSAndroid Build Coastguard Worker  */
FinalizeFile()2892*38e8c45fSAndroid Build Coastguard Worker static void FinalizeFile() {
2893*38e8c45fSAndroid Build Coastguard Worker     bool do_text_file = !ds.FinishZipFile();
2894*38e8c45fSAndroid Build Coastguard Worker     if (do_text_file) {
2895*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2896*38e8c45fSAndroid Build Coastguard Worker     }
2897*38e8c45fSAndroid Build Coastguard Worker 
2898*38e8c45fSAndroid Build Coastguard Worker     std::string final_path = ds.path_;
2899*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->OutputToCustomFile()) {
2900*38e8c45fSAndroid Build Coastguard Worker         final_path = ds.GetPath(ds.options_->out_dir, ".zip");
2901*38e8c45fSAndroid Build Coastguard Worker         android::os::CopyFileToFile(ds.path_, final_path);
2902*38e8c45fSAndroid Build Coastguard Worker     }
2903*38e8c45fSAndroid Build Coastguard Worker 
2904*38e8c45fSAndroid Build Coastguard Worker     if (ds.options_->stream_to_socket) {
2905*38e8c45fSAndroid Build Coastguard Worker         android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2906*38e8c45fSAndroid Build Coastguard Worker     } else if (ds.options_->progress_updates_to_socket) {
2907*38e8c45fSAndroid Build Coastguard Worker         if (do_text_file) {
2908*38e8c45fSAndroid Build Coastguard Worker             dprintf(ds.control_socket_fd_,
2909*38e8c45fSAndroid Build Coastguard Worker                     "FAIL:could not create zip file, check %s "
2910*38e8c45fSAndroid Build Coastguard Worker                     "for more details\n",
2911*38e8c45fSAndroid Build Coastguard Worker                     ds.log_path_.c_str());
2912*38e8c45fSAndroid Build Coastguard Worker         } else {
2913*38e8c45fSAndroid Build Coastguard Worker             dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
2914*38e8c45fSAndroid Build Coastguard Worker         }
2915*38e8c45fSAndroid Build Coastguard Worker     }
2916*38e8c45fSAndroid Build Coastguard Worker }
2917*38e8c45fSAndroid Build Coastguard Worker 
2918*38e8c45fSAndroid Build Coastguard Worker 
ModeToString(Dumpstate::BugreportMode mode)2919*38e8c45fSAndroid Build Coastguard Worker static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2920*38e8c45fSAndroid Build Coastguard Worker     switch (mode) {
2921*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2922*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_FULL";
2923*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2924*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_INTERACTIVE";
2925*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2926*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_REMOTE";
2927*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2928*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_WEAR";
2929*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2930*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_TELEPHONY";
2931*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2932*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_WIFI";
2933*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2934*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_ONBOARDING";
2935*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2936*38e8c45fSAndroid Build Coastguard Worker             return "BUGREPORT_DEFAULT";
2937*38e8c45fSAndroid Build Coastguard Worker     }
2938*38e8c45fSAndroid Build Coastguard Worker }
2939*38e8c45fSAndroid Build Coastguard Worker 
IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions & options)2940*38e8c45fSAndroid Build Coastguard Worker static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2941*38e8c45fSAndroid Build Coastguard Worker     // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2942*38e8c45fSAndroid Build Coastguard Worker     return !options.telephony_only;
2943*38e8c45fSAndroid Build Coastguard Worker }
2944*38e8c45fSAndroid Build Coastguard Worker 
SetOptionsFromMode(Dumpstate::BugreportMode mode,Dumpstate::DumpOptions * options,bool is_screenshot_requested)2945*38e8c45fSAndroid Build Coastguard Worker static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2946*38e8c45fSAndroid Build Coastguard Worker                                bool is_screenshot_requested) {
2947*38e8c45fSAndroid Build Coastguard Worker     // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2948*38e8c45fSAndroid Build Coastguard Worker     // default system screenshots.
2949*38e8c45fSAndroid Build Coastguard Worker     options->bugreport_mode = mode;
2950*38e8c45fSAndroid Build Coastguard Worker     options->bugreport_mode_string = ModeToString(mode);
2951*38e8c45fSAndroid Build Coastguard Worker     switch (mode) {
2952*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2953*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = is_screenshot_requested;
2954*38e8c45fSAndroid Build Coastguard Worker             break;
2955*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2956*38e8c45fSAndroid Build Coastguard Worker             // Currently, the dumpstate binder is only used by Shell to update progress.
2957*38e8c45fSAndroid Build Coastguard Worker             options->do_progress_updates = true;
2958*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = is_screenshot_requested;
2959*38e8c45fSAndroid Build Coastguard Worker             break;
2960*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2961*38e8c45fSAndroid Build Coastguard Worker             options->do_vibrate = false;
2962*38e8c45fSAndroid Build Coastguard Worker             options->is_remote_mode = true;
2963*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = false;
2964*38e8c45fSAndroid Build Coastguard Worker             break;
2965*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2966*38e8c45fSAndroid Build Coastguard Worker             options->do_vibrate = false;
2967*38e8c45fSAndroid Build Coastguard Worker             options->do_progress_updates = true;
2968*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = is_screenshot_requested;
2969*38e8c45fSAndroid Build Coastguard Worker             break;
2970*38e8c45fSAndroid Build Coastguard Worker         // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
2971*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2972*38e8c45fSAndroid Build Coastguard Worker             options->telephony_only = true;
2973*38e8c45fSAndroid Build Coastguard Worker             options->do_progress_updates = true;
2974*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = false;
2975*38e8c45fSAndroid Build Coastguard Worker             break;
2976*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2977*38e8c45fSAndroid Build Coastguard Worker             options->wifi_only = true;
2978*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = false;
2979*38e8c45fSAndroid Build Coastguard Worker             break;
2980*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2981*38e8c45fSAndroid Build Coastguard Worker             options->onboarding_only = true;
2982*38e8c45fSAndroid Build Coastguard Worker             options->do_screenshot = false;
2983*38e8c45fSAndroid Build Coastguard Worker             break;
2984*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2985*38e8c45fSAndroid Build Coastguard Worker             break;
2986*38e8c45fSAndroid Build Coastguard Worker     }
2987*38e8c45fSAndroid Build Coastguard Worker }
2988*38e8c45fSAndroid Build Coastguard Worker 
LogDumpOptions(const Dumpstate::DumpOptions & options)2989*38e8c45fSAndroid Build Coastguard Worker static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2990*38e8c45fSAndroid Build Coastguard Worker     MYLOGI(
2991*38e8c45fSAndroid Build Coastguard Worker         "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
2992*38e8c45fSAndroid Build Coastguard Worker         "is_remote_mode: %d show_header_only: %d telephony_only: %d "
2993*38e8c45fSAndroid Build Coastguard Worker         "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
2994*38e8c45fSAndroid Build Coastguard Worker         "limited_only: %d args: %s\n",
2995*38e8c45fSAndroid Build Coastguard Worker         options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
2996*38e8c45fSAndroid Build Coastguard Worker         options.do_screenshot, options.is_remote_mode, options.show_header_only,
2997*38e8c45fSAndroid Build Coastguard Worker         options.telephony_only, options.wifi_only,
2998*38e8c45fSAndroid Build Coastguard Worker         options.do_progress_updates, options.bugreport_fd.get(),
2999*38e8c45fSAndroid Build Coastguard Worker         options.bugreport_mode_string.c_str(),
3000*38e8c45fSAndroid Build Coastguard Worker         options.limited_only, options.args.c_str());
3001*38e8c45fSAndroid Build Coastguard Worker }
3002*38e8c45fSAndroid Build Coastguard Worker 
Initialize(BugreportMode bugreport_mode,int bugreport_flags,const android::base::unique_fd & bugreport_fd_in,const android::base::unique_fd & screenshot_fd_in,bool is_screenshot_requested,bool skip_user_consent)3003*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
3004*38e8c45fSAndroid Build Coastguard Worker                                         int bugreport_flags,
3005*38e8c45fSAndroid Build Coastguard Worker                                         const android::base::unique_fd& bugreport_fd_in,
3006*38e8c45fSAndroid Build Coastguard Worker                                         const android::base::unique_fd& screenshot_fd_in,
3007*38e8c45fSAndroid Build Coastguard Worker                                         bool is_screenshot_requested,
3008*38e8c45fSAndroid Build Coastguard Worker                                         bool skip_user_consent) {
3009*38e8c45fSAndroid Build Coastguard Worker     this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
3010*38e8c45fSAndroid Build Coastguard Worker     this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
3011*38e8c45fSAndroid Build Coastguard Worker     this->skip_user_consent = skip_user_consent;
3012*38e8c45fSAndroid Build Coastguard Worker     // Duplicate the fds because the passed in fds don't outlive the binder transaction.
3013*38e8c45fSAndroid Build Coastguard Worker     bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3014*38e8c45fSAndroid Build Coastguard Worker     screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3015*38e8c45fSAndroid Build Coastguard Worker 
3016*38e8c45fSAndroid Build Coastguard Worker     SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
3017*38e8c45fSAndroid Build Coastguard Worker }
3018*38e8c45fSAndroid Build Coastguard Worker 
Initialize(int argc,char * argv[])3019*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3020*38e8c45fSAndroid Build Coastguard Worker     RunStatus status = RunStatus::OK;
3021*38e8c45fSAndroid Build Coastguard Worker     int c;
3022*38e8c45fSAndroid Build Coastguard Worker     while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
3023*38e8c45fSAndroid Build Coastguard Worker         switch (c) {
3024*38e8c45fSAndroid Build Coastguard Worker             // clang-format off
3025*38e8c45fSAndroid Build Coastguard Worker             case 'o': out_dir = optarg;              break;
3026*38e8c45fSAndroid Build Coastguard Worker             case 's': stream_to_socket = true;       break;
3027*38e8c45fSAndroid Build Coastguard Worker             case 'S': progress_updates_to_socket = true;    break;
3028*38e8c45fSAndroid Build Coastguard Worker             case 'v': show_header_only = true;       break;
3029*38e8c45fSAndroid Build Coastguard Worker             case 'q': do_vibrate = false;            break;
3030*38e8c45fSAndroid Build Coastguard Worker             case 'p': do_screenshot = true;          break;
3031*38e8c45fSAndroid Build Coastguard Worker             case 'P': do_progress_updates = true;    break;
3032*38e8c45fSAndroid Build Coastguard Worker             case 'R': is_remote_mode = true;         break;
3033*38e8c45fSAndroid Build Coastguard Worker             case 'L': limited_only = true;           break;
3034*38e8c45fSAndroid Build Coastguard Worker             case 'V':
3035*38e8c45fSAndroid Build Coastguard Worker             case 'd':
3036*38e8c45fSAndroid Build Coastguard Worker             case 'z':
3037*38e8c45fSAndroid Build Coastguard Worker                 // compatibility no-op
3038*38e8c45fSAndroid Build Coastguard Worker                 break;
3039*38e8c45fSAndroid Build Coastguard Worker             case 'w':
3040*38e8c45fSAndroid Build Coastguard Worker                 // This was already processed
3041*38e8c45fSAndroid Build Coastguard Worker                 break;
3042*38e8c45fSAndroid Build Coastguard Worker             case 'h':
3043*38e8c45fSAndroid Build Coastguard Worker                 status = RunStatus::HELP;
3044*38e8c45fSAndroid Build Coastguard Worker                 break;
3045*38e8c45fSAndroid Build Coastguard Worker             default:
3046*38e8c45fSAndroid Build Coastguard Worker                 fprintf(stderr, "Invalid option: %c\n", c);
3047*38e8c45fSAndroid Build Coastguard Worker                 status = RunStatus::INVALID_INPUT;
3048*38e8c45fSAndroid Build Coastguard Worker                 break;
3049*38e8c45fSAndroid Build Coastguard Worker                 // clang-format on
3050*38e8c45fSAndroid Build Coastguard Worker         }
3051*38e8c45fSAndroid Build Coastguard Worker     }
3052*38e8c45fSAndroid Build Coastguard Worker 
3053*38e8c45fSAndroid Build Coastguard Worker     for (int i = 0; i < argc; i++) {
3054*38e8c45fSAndroid Build Coastguard Worker         args += argv[i];
3055*38e8c45fSAndroid Build Coastguard Worker         if (i < argc - 1) {
3056*38e8c45fSAndroid Build Coastguard Worker             args += " ";
3057*38e8c45fSAndroid Build Coastguard Worker         }
3058*38e8c45fSAndroid Build Coastguard Worker     }
3059*38e8c45fSAndroid Build Coastguard Worker 
3060*38e8c45fSAndroid Build Coastguard Worker     // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3061*38e8c45fSAndroid Build Coastguard Worker     optind = 1;
3062*38e8c45fSAndroid Build Coastguard Worker 
3063*38e8c45fSAndroid Build Coastguard Worker     return status;
3064*38e8c45fSAndroid Build Coastguard Worker }
3065*38e8c45fSAndroid Build Coastguard Worker 
ValidateOptions() const3066*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::DumpOptions::ValidateOptions() const {
3067*38e8c45fSAndroid Build Coastguard Worker     if (bugreport_fd.get() != -1 && stream_to_socket) {
3068*38e8c45fSAndroid Build Coastguard Worker         return false;
3069*38e8c45fSAndroid Build Coastguard Worker     }
3070*38e8c45fSAndroid Build Coastguard Worker 
3071*38e8c45fSAndroid Build Coastguard Worker     if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
3072*38e8c45fSAndroid Build Coastguard Worker         return false;
3073*38e8c45fSAndroid Build Coastguard Worker     }
3074*38e8c45fSAndroid Build Coastguard Worker 
3075*38e8c45fSAndroid Build Coastguard Worker     if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
3076*38e8c45fSAndroid Build Coastguard Worker         return false;
3077*38e8c45fSAndroid Build Coastguard Worker     }
3078*38e8c45fSAndroid Build Coastguard Worker     return true;
3079*38e8c45fSAndroid Build Coastguard Worker }
3080*38e8c45fSAndroid Build Coastguard Worker 
SetOptions(std::unique_ptr<DumpOptions> options)3081*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3082*38e8c45fSAndroid Build Coastguard Worker     options_ = std::move(options);
3083*38e8c45fSAndroid Build Coastguard Worker }
3084*38e8c45fSAndroid Build Coastguard Worker 
Initialize()3085*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::Initialize() {
3086*38e8c45fSAndroid Build Coastguard Worker     /* gets the sequential id */
3087*38e8c45fSAndroid Build Coastguard Worker     uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3088*38e8c45fSAndroid Build Coastguard Worker     id_ = ++last_id;
3089*38e8c45fSAndroid Build Coastguard Worker     android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3090*38e8c45fSAndroid Build Coastguard Worker }
3091*38e8c45fSAndroid Build Coastguard Worker 
Run(int32_t calling_uid,const std::string & calling_package)3092*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3093*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
3094*38e8c45fSAndroid Build Coastguard Worker     HandleRunStatus(status);
3095*38e8c45fSAndroid Build Coastguard Worker     return status;
3096*38e8c45fSAndroid Build Coastguard Worker }
3097*38e8c45fSAndroid Build Coastguard Worker 
Retrieve(int32_t calling_uid,const std::string & calling_package,const bool keep_bugreport_on_retrieval,const bool skip_user_consent)3098*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
3099*38e8c45fSAndroid Build Coastguard Worker                                          const bool keep_bugreport_on_retrieval,
3100*38e8c45fSAndroid Build Coastguard Worker                                          const bool skip_user_consent) {
3101*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
3102*38e8c45fSAndroid Build Coastguard Worker                                                     keep_bugreport_on_retrieval,
3103*38e8c45fSAndroid Build Coastguard Worker                                                     skip_user_consent);
3104*38e8c45fSAndroid Build Coastguard Worker     HandleRunStatus(status);
3105*38e8c45fSAndroid Build Coastguard Worker     return status;
3106*38e8c45fSAndroid Build Coastguard Worker }
3107*38e8c45fSAndroid Build Coastguard Worker 
RetrieveInternal(int32_t calling_uid,const std::string & calling_package,const bool keep_bugreport_on_retrieval,const bool skip_user_consent)3108*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus  Dumpstate::RetrieveInternal(int32_t calling_uid,
3109*38e8c45fSAndroid Build Coastguard Worker                                                   const std::string& calling_package,
3110*38e8c45fSAndroid Build Coastguard Worker                                                   const bool keep_bugreport_on_retrieval,
3111*38e8c45fSAndroid Build Coastguard Worker                                                   const bool skip_user_consent) {
3112*38e8c45fSAndroid Build Coastguard Worker   if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3113*38e8c45fSAndroid Build Coastguard Worker       consent_callback_ = new ConsentCallback();
3114*38e8c45fSAndroid Build Coastguard Worker       const String16 incidentcompanion("incidentcompanion");
3115*38e8c45fSAndroid Build Coastguard Worker       sp<android::IBinder> ics(
3116*38e8c45fSAndroid Build Coastguard Worker           defaultServiceManager()->checkService(incidentcompanion));
3117*38e8c45fSAndroid Build Coastguard Worker       android::String16 package(calling_package.c_str());
3118*38e8c45fSAndroid Build Coastguard Worker       if (ics != nullptr) {
3119*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Checking user consent via incidentcompanion service\n");
3120*38e8c45fSAndroid Build Coastguard Worker 
3121*38e8c45fSAndroid Build Coastguard Worker         android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3122*38e8c45fSAndroid Build Coastguard Worker             calling_uid, package, String16(), String16(),
3123*38e8c45fSAndroid Build Coastguard Worker             0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3124*38e8c45fSAndroid Build Coastguard Worker       } else {
3125*38e8c45fSAndroid Build Coastguard Worker         MYLOGD(
3126*38e8c45fSAndroid Build Coastguard Worker             "Unable to check user consent; incidentcompanion service unavailable\n");
3127*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::USER_CONSENT_TIMED_OUT;
3128*38e8c45fSAndroid Build Coastguard Worker       }
3129*38e8c45fSAndroid Build Coastguard Worker       UserConsentResult consent_result = consent_callback_->getResult();
3130*38e8c45fSAndroid Build Coastguard Worker       int timeout_ms = 30 * 1000;
3131*38e8c45fSAndroid Build Coastguard Worker       while (consent_result == UserConsentResult::UNAVAILABLE &&
3132*38e8c45fSAndroid Build Coastguard Worker           consent_callback_->getElapsedTimeMs() < timeout_ms) {
3133*38e8c45fSAndroid Build Coastguard Worker         sleep(1);
3134*38e8c45fSAndroid Build Coastguard Worker         consent_result = consent_callback_->getResult();
3135*38e8c45fSAndroid Build Coastguard Worker       }
3136*38e8c45fSAndroid Build Coastguard Worker       if (consent_result == UserConsentResult::DENIED) {
3137*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::USER_CONSENT_DENIED;
3138*38e8c45fSAndroid Build Coastguard Worker       }
3139*38e8c45fSAndroid Build Coastguard Worker       if (consent_result == UserConsentResult::UNAVAILABLE) {
3140*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Canceling user consent request via incidentcompanion service\n");
3141*38e8c45fSAndroid Build Coastguard Worker         android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3142*38e8c45fSAndroid Build Coastguard Worker             consent_callback_.get());
3143*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::USER_CONSENT_TIMED_OUT;
3144*38e8c45fSAndroid Build Coastguard Worker       }
3145*38e8c45fSAndroid Build Coastguard Worker   }
3146*38e8c45fSAndroid Build Coastguard Worker 
3147*38e8c45fSAndroid Build Coastguard Worker   bool copy_succeeded =
3148*38e8c45fSAndroid Build Coastguard Worker       android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3149*38e8c45fSAndroid Build Coastguard Worker 
3150*38e8c45fSAndroid Build Coastguard Worker   if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3151*38e8c45fSAndroid Build Coastguard Worker                          || !keep_bugreport_on_retrieval)) {
3152*38e8c45fSAndroid Build Coastguard Worker         android::os::UnlinkAndLogOnError(path_);
3153*38e8c45fSAndroid Build Coastguard Worker   }
3154*38e8c45fSAndroid Build Coastguard Worker 
3155*38e8c45fSAndroid Build Coastguard Worker   return copy_succeeded ? Dumpstate::RunStatus::OK
3156*38e8c45fSAndroid Build Coastguard Worker                         : Dumpstate::RunStatus::ERROR;
3157*38e8c45fSAndroid Build Coastguard Worker }
3158*38e8c45fSAndroid Build Coastguard Worker 
HandleRunStatus(Dumpstate::RunStatus status)3159*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3160*38e8c45fSAndroid Build Coastguard Worker       if (listener_ != nullptr) {
3161*38e8c45fSAndroid Build Coastguard Worker         switch (status) {
3162*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::OK:
3163*38e8c45fSAndroid Build Coastguard Worker                 listener_->onFinished(path_.c_str());
3164*38e8c45fSAndroid Build Coastguard Worker                 break;
3165*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::HELP:
3166*38e8c45fSAndroid Build Coastguard Worker                 break;
3167*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::INVALID_INPUT:
3168*38e8c45fSAndroid Build Coastguard Worker                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
3169*38e8c45fSAndroid Build Coastguard Worker                 break;
3170*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::ERROR:
3171*38e8c45fSAndroid Build Coastguard Worker                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3172*38e8c45fSAndroid Build Coastguard Worker                 break;
3173*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3174*38e8c45fSAndroid Build Coastguard Worker                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3175*38e8c45fSAndroid Build Coastguard Worker                 break;
3176*38e8c45fSAndroid Build Coastguard Worker             case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3177*38e8c45fSAndroid Build Coastguard Worker                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
3178*38e8c45fSAndroid Build Coastguard Worker                 break;
3179*38e8c45fSAndroid Build Coastguard Worker         }
3180*38e8c45fSAndroid Build Coastguard Worker     }
3181*38e8c45fSAndroid Build Coastguard Worker }
Cancel()3182*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::Cancel() {
3183*38e8c45fSAndroid Build Coastguard Worker     CleanupTmpFiles();
3184*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(log_path_);
3185*38e8c45fSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_OF_DUMPS; i++) {
3186*38e8c45fSAndroid Build Coastguard Worker         android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3187*38e8c45fSAndroid Build Coastguard Worker                                          kDumpstateBoardFiles[i]);
3188*38e8c45fSAndroid Build Coastguard Worker     }
3189*38e8c45fSAndroid Build Coastguard Worker     tombstone_data_.clear();
3190*38e8c45fSAndroid Build Coastguard Worker     anr_data_.clear();
3191*38e8c45fSAndroid Build Coastguard Worker     anr_trace_data_.clear();
3192*38e8c45fSAndroid Build Coastguard Worker     shutdown_checkpoints_.clear();
3193*38e8c45fSAndroid Build Coastguard Worker 
3194*38e8c45fSAndroid Build Coastguard Worker     // Instead of shutdown the pool, we delete temporary files directly since
3195*38e8c45fSAndroid Build Coastguard Worker     // shutdown blocking the call.
3196*38e8c45fSAndroid Build Coastguard Worker     if (dump_pool_) {
3197*38e8c45fSAndroid Build Coastguard Worker         dump_pool_->deleteTempFiles();
3198*38e8c45fSAndroid Build Coastguard Worker     }
3199*38e8c45fSAndroid Build Coastguard Worker     if (zip_entry_tasks_) {
3200*38e8c45fSAndroid Build Coastguard Worker         zip_entry_tasks_->run(/*do_cancel =*/ true);
3201*38e8c45fSAndroid Build Coastguard Worker     }
3202*38e8c45fSAndroid Build Coastguard Worker }
3203*38e8c45fSAndroid Build Coastguard Worker 
PreDumpUiData()3204*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::PreDumpUiData() {
3205*38e8c45fSAndroid Build Coastguard Worker     auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
3206*38e8c45fSAndroid Build Coastguard Worker     MaybeSnapshotUiTraces();
3207*38e8c45fSAndroid Build Coastguard Worker     MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
3208*38e8c45fSAndroid Build Coastguard Worker }
3209*38e8c45fSAndroid Build Coastguard Worker 
3210*38e8c45fSAndroid Build Coastguard Worker /*
3211*38e8c45fSAndroid Build Coastguard Worker  * Dumps relevant information to a bugreport based on the given options.
3212*38e8c45fSAndroid Build Coastguard Worker  *
3213*38e8c45fSAndroid Build Coastguard Worker  * The bugreport can be dumped to a file or streamed to a socket.
3214*38e8c45fSAndroid Build Coastguard Worker  *
3215*38e8c45fSAndroid Build Coastguard Worker  * How dumping to file works:
3216*38e8c45fSAndroid Build Coastguard Worker  * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3217*38e8c45fSAndroid Build Coastguard Worker  * stderr is redirected a log file.
3218*38e8c45fSAndroid Build Coastguard Worker  *
3219*38e8c45fSAndroid Build Coastguard Worker  * The temporary bugreport is then populated via printfs, dumping contents of files and
3220*38e8c45fSAndroid Build Coastguard Worker  * output of commands to stdout.
3221*38e8c45fSAndroid Build Coastguard Worker  *
3222*38e8c45fSAndroid Build Coastguard Worker  * A bunch of other files and dumps are added to the zip archive.
3223*38e8c45fSAndroid Build Coastguard Worker  *
3224*38e8c45fSAndroid Build Coastguard Worker  * The temporary bugreport file and the log file also get added to the archive.
3225*38e8c45fSAndroid Build Coastguard Worker  *
3226*38e8c45fSAndroid Build Coastguard Worker  * Bugreports are first generated in a local directory and later copied to the caller's fd
3227*38e8c45fSAndroid Build Coastguard Worker  * or directory if supplied.
3228*38e8c45fSAndroid Build Coastguard Worker  */
RunInternal(int32_t calling_uid,const std::string & calling_package)3229*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3230*38e8c45fSAndroid Build Coastguard Worker                                             const std::string& calling_package) {
3231*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
3232*38e8c45fSAndroid Build Coastguard Worker     LogDumpOptions(*options_);
3233*38e8c45fSAndroid Build Coastguard Worker     if (!options_->ValidateOptions()) {
3234*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Invalid options specified\n");
3235*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::INVALID_INPUT;
3236*38e8c45fSAndroid Build Coastguard Worker     }
3237*38e8c45fSAndroid Build Coastguard Worker     /* set as high priority, and protect from OOM killer */
3238*38e8c45fSAndroid Build Coastguard Worker     setpriority(PRIO_PROCESS, 0, -20);
3239*38e8c45fSAndroid Build Coastguard Worker 
3240*38e8c45fSAndroid Build Coastguard Worker     FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
3241*38e8c45fSAndroid Build Coastguard Worker     if (oom_adj) {
3242*38e8c45fSAndroid Build Coastguard Worker         fputs("-1000", oom_adj);
3243*38e8c45fSAndroid Build Coastguard Worker         fclose(oom_adj);
3244*38e8c45fSAndroid Build Coastguard Worker     } else {
3245*38e8c45fSAndroid Build Coastguard Worker         /* fallback to kernels <= 2.6.35 */
3246*38e8c45fSAndroid Build Coastguard Worker         oom_adj = fopen("/proc/self/oom_adj", "we");
3247*38e8c45fSAndroid Build Coastguard Worker         if (oom_adj) {
3248*38e8c45fSAndroid Build Coastguard Worker             fputs("-17", oom_adj);
3249*38e8c45fSAndroid Build Coastguard Worker             fclose(oom_adj);
3250*38e8c45fSAndroid Build Coastguard Worker         }
3251*38e8c45fSAndroid Build Coastguard Worker     }
3252*38e8c45fSAndroid Build Coastguard Worker 
3253*38e8c45fSAndroid Build Coastguard Worker     if (version_ == VERSION_DEFAULT) {
3254*38e8c45fSAndroid Build Coastguard Worker         version_ = VERSION_CURRENT;
3255*38e8c45fSAndroid Build Coastguard Worker     }
3256*38e8c45fSAndroid Build Coastguard Worker 
3257*38e8c45fSAndroid Build Coastguard Worker     if (version_ != VERSION_CURRENT) {
3258*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3259*38e8c45fSAndroid Build Coastguard Worker                version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
3260*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::INVALID_INPUT;
3261*38e8c45fSAndroid Build Coastguard Worker     }
3262*38e8c45fSAndroid Build Coastguard Worker 
3263*38e8c45fSAndroid Build Coastguard Worker     if (options_->show_header_only) {
3264*38e8c45fSAndroid Build Coastguard Worker         PrintHeader();
3265*38e8c45fSAndroid Build Coastguard Worker         return RunStatus::OK;
3266*38e8c45fSAndroid Build Coastguard Worker     }
3267*38e8c45fSAndroid Build Coastguard Worker 
3268*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3269*38e8c45fSAndroid Build Coastguard Worker             calling_uid, calling_package.c_str());
3270*38e8c45fSAndroid Build Coastguard Worker 
3271*38e8c45fSAndroid Build Coastguard Worker     // TODO: temporarily set progress until it's part of the Dumpstate constructor
3272*38e8c45fSAndroid Build Coastguard Worker     std::string stats_path =
3273*38e8c45fSAndroid Build Coastguard Worker         android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
3274*38e8c45fSAndroid Build Coastguard Worker     progress_.reset(new Progress(stats_path));
3275*38e8c45fSAndroid Build Coastguard Worker 
3276*38e8c45fSAndroid Build Coastguard Worker     if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3277*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3278*38e8c45fSAndroid Build Coastguard Worker     } else {
3279*38e8c45fSAndroid Build Coastguard Worker         // Wake lock will be released automatically on process death
3280*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Wake lock acquired.\n");
3281*38e8c45fSAndroid Build Coastguard Worker     }
3282*38e8c45fSAndroid Build Coastguard Worker 
3283*38e8c45fSAndroid Build Coastguard Worker     register_sig_handler();
3284*38e8c45fSAndroid Build Coastguard Worker 
3285*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) {
3286*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3287*38e8c45fSAndroid Build Coastguard Worker     }
3288*38e8c45fSAndroid Build Coastguard Worker 
3289*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsStrictRun()) {
3290*38e8c45fSAndroid Build Coastguard Worker         MYLOGI(
3291*38e8c45fSAndroid Build Coastguard Worker             "Running on strict-run mode, which has shorter timeouts "
3292*38e8c45fSAndroid Build Coastguard Worker             "(to disable, call 'setprop dumpstate.strict_run false')\n");
3293*38e8c45fSAndroid Build Coastguard Worker     }
3294*38e8c45fSAndroid Build Coastguard Worker 
3295*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
3296*38e8c45fSAndroid Build Coastguard Worker            id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
3297*38e8c45fSAndroid Build Coastguard Worker 
3298*38e8c45fSAndroid Build Coastguard Worker     do_early_screenshot_ = options_->do_progress_updates;
3299*38e8c45fSAndroid Build Coastguard Worker 
3300*38e8c45fSAndroid Build Coastguard Worker     // If we are going to use a socket, do it as early as possible
3301*38e8c45fSAndroid Build Coastguard Worker     // to avoid timeouts from bugreport.
3302*38e8c45fSAndroid Build Coastguard Worker     if (options_->stream_to_socket || options_->progress_updates_to_socket) {
3303*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Opening control socket\n");
3304*38e8c45fSAndroid Build Coastguard Worker         control_socket_fd_ = open_socket_fn_("dumpstate");
3305*38e8c45fSAndroid Build Coastguard Worker         if (control_socket_fd_ == -1) {
3306*38e8c45fSAndroid Build Coastguard Worker             return ERROR;
3307*38e8c45fSAndroid Build Coastguard Worker         }
3308*38e8c45fSAndroid Build Coastguard Worker         if (options_->progress_updates_to_socket) {
3309*38e8c45fSAndroid Build Coastguard Worker             options_->do_progress_updates = 1;
3310*38e8c45fSAndroid Build Coastguard Worker         }
3311*38e8c45fSAndroid Build Coastguard Worker     }
3312*38e8c45fSAndroid Build Coastguard Worker 
3313*38e8c45fSAndroid Build Coastguard Worker     if (!PrepareToWriteToFile()) {
3314*38e8c45fSAndroid Build Coastguard Worker         return ERROR;
3315*38e8c45fSAndroid Build Coastguard Worker     }
3316*38e8c45fSAndroid Build Coastguard Worker 
3317*38e8c45fSAndroid Build Coastguard Worker     // Interactive, wear & telephony modes are default to true.
3318*38e8c45fSAndroid Build Coastguard Worker     // and may enable from cli option or when using control socket
3319*38e8c45fSAndroid Build Coastguard Worker     if (options_->do_progress_updates) {
3320*38e8c45fSAndroid Build Coastguard Worker         // clang-format off
3321*38e8c45fSAndroid Build Coastguard Worker         std::vector<std::string> am_args = {
3322*38e8c45fSAndroid Build Coastguard Worker                 "--receiver-permission", "android.permission.DUMP",
3323*38e8c45fSAndroid Build Coastguard Worker         };
3324*38e8c45fSAndroid Build Coastguard Worker         // clang-format on
3325*38e8c45fSAndroid Build Coastguard Worker         // Send STARTED broadcast for apps that listen to bugreport generation events
3326*38e8c45fSAndroid Build Coastguard Worker         SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3327*38e8c45fSAndroid Build Coastguard Worker                       am_args, multiuser_get_user_id(calling_uid));
3328*38e8c45fSAndroid Build Coastguard Worker         if (options_->progress_updates_to_socket) {
3329*38e8c45fSAndroid Build Coastguard Worker             dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
3330*38e8c45fSAndroid Build Coastguard Worker         }
3331*38e8c45fSAndroid Build Coastguard Worker     }
3332*38e8c45fSAndroid Build Coastguard Worker 
3333*38e8c45fSAndroid Build Coastguard Worker     /* read /proc/cmdline before dropping root */
3334*38e8c45fSAndroid Build Coastguard Worker     FILE *cmdline = fopen("/proc/cmdline", "re");
3335*38e8c45fSAndroid Build Coastguard Worker     if (cmdline) {
3336*38e8c45fSAndroid Build Coastguard Worker         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3337*38e8c45fSAndroid Build Coastguard Worker         fclose(cmdline);
3338*38e8c45fSAndroid Build Coastguard Worker     }
3339*38e8c45fSAndroid Build Coastguard Worker 
3340*38e8c45fSAndroid Build Coastguard Worker     if (options_->do_vibrate) {
3341*38e8c45fSAndroid Build Coastguard Worker         Vibrate(150);
3342*38e8c45fSAndroid Build Coastguard Worker     }
3343*38e8c45fSAndroid Build Coastguard Worker 
3344*38e8c45fSAndroid Build Coastguard Worker     if (zip_file != nullptr) {
3345*38e8c45fSAndroid Build Coastguard Worker         if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3346*38e8c45fSAndroid Build Coastguard Worker             MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
3347*38e8c45fSAndroid Build Coastguard Worker                     strerror(errno));
3348*38e8c45fSAndroid Build Coastguard Worker         }
3349*38e8c45fSAndroid Build Coastguard Worker     }
3350*38e8c45fSAndroid Build Coastguard Worker 
3351*38e8c45fSAndroid Build Coastguard Worker     int dup_stdout_fd;
3352*38e8c45fSAndroid Build Coastguard Worker     int dup_stderr_fd;
3353*38e8c45fSAndroid Build Coastguard Worker     // Redirect stderr to log_path_ for debugging.
3354*38e8c45fSAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3355*38e8c45fSAndroid Build Coastguard Worker     if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3356*38e8c45fSAndroid Build Coastguard Worker         return ERROR;
3357*38e8c45fSAndroid Build Coastguard Worker     }
3358*38e8c45fSAndroid Build Coastguard Worker     if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3359*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3360*38e8c45fSAndroid Build Coastguard Worker                 strerror(errno));
3361*38e8c45fSAndroid Build Coastguard Worker     }
3362*38e8c45fSAndroid Build Coastguard Worker 
3363*38e8c45fSAndroid Build Coastguard Worker     // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3364*38e8c45fSAndroid Build Coastguard Worker     // moved into zip file later, if zipping.
3365*38e8c45fSAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3366*38e8c45fSAndroid Build Coastguard Worker     // TODO: why not write to a file instead of stdout to overcome this problem?
3367*38e8c45fSAndroid Build Coastguard Worker     /* TODO: rather than generating a text file now and zipping it later,
3368*38e8c45fSAndroid Build Coastguard Worker         it would be more efficient to redirect stdout to the zip entry
3369*38e8c45fSAndroid Build Coastguard Worker         directly, but the libziparchive doesn't support that option yet. */
3370*38e8c45fSAndroid Build Coastguard Worker     if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3371*38e8c45fSAndroid Build Coastguard Worker         return ERROR;
3372*38e8c45fSAndroid Build Coastguard Worker     }
3373*38e8c45fSAndroid Build Coastguard Worker     if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3374*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3375*38e8c45fSAndroid Build Coastguard Worker                 tmp_path_.c_str(), strerror(errno));
3376*38e8c45fSAndroid Build Coastguard Worker     }
3377*38e8c45fSAndroid Build Coastguard Worker 
3378*38e8c45fSAndroid Build Coastguard Worker     // Don't buffer stdout
3379*38e8c45fSAndroid Build Coastguard Worker     setvbuf(stdout, nullptr, _IONBF, 0);
3380*38e8c45fSAndroid Build Coastguard Worker 
3381*38e8c45fSAndroid Build Coastguard Worker     // Enable the parallel run if the client requests to output to a file.
3382*38e8c45fSAndroid Build Coastguard Worker     EnableParallelRunIfNeeded();
3383*38e8c45fSAndroid Build Coastguard Worker     // Using scope guard to make sure the dump pool can be shut down correctly.
3384*38e8c45fSAndroid Build Coastguard Worker     auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3385*38e8c45fSAndroid Build Coastguard Worker         ShutdownDumpPool();
3386*38e8c45fSAndroid Build Coastguard Worker     });
3387*38e8c45fSAndroid Build Coastguard Worker 
3388*38e8c45fSAndroid Build Coastguard Worker     // NOTE: there should be no stdout output until now, otherwise it would break the header.
3389*38e8c45fSAndroid Build Coastguard Worker     // In particular, DurationReport objects should be created passing 'title, NULL', so their
3390*38e8c45fSAndroid Build Coastguard Worker     // duration is logged into MYLOG instead.
3391*38e8c45fSAndroid Build Coastguard Worker     PrintHeader();
3392*38e8c45fSAndroid Build Coastguard Worker 
3393*38e8c45fSAndroid Build Coastguard Worker     bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3394*38e8c45fSAndroid Build Coastguard Worker     if (options_->use_predumped_ui_data && !system_trace_exists) {
3395*38e8c45fSAndroid Build Coastguard Worker         MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3396*38e8c45fSAndroid Build Coastguard Worker         options_->use_predumped_ui_data = false;
3397*38e8c45fSAndroid Build Coastguard Worker     }
3398*38e8c45fSAndroid Build Coastguard Worker 
3399*38e8c45fSAndroid Build Coastguard Worker     std::future<std::string> snapshot_system_trace;
3400*38e8c45fSAndroid Build Coastguard Worker 
3401*38e8c45fSAndroid Build Coastguard Worker     bool is_dumpstate_restricted =
3402*38e8c45fSAndroid Build Coastguard Worker         options_->telephony_only || options_->wifi_only || options_->limited_only;
3403*38e8c45fSAndroid Build Coastguard Worker     if (!is_dumpstate_restricted) {
3404*38e8c45fSAndroid Build Coastguard Worker         // Snapshot the system trace now (if running) to avoid that dumpstate's
3405*38e8c45fSAndroid Build Coastguard Worker         // own activity pushes out interesting data from the trace ring buffer.
3406*38e8c45fSAndroid Build Coastguard Worker         // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3407*38e8c45fSAndroid Build Coastguard Worker         snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
3408*38e8c45fSAndroid Build Coastguard Worker 
3409*38e8c45fSAndroid Build Coastguard Worker         // Invoke critical dumpsys to preserve system state, before doing anything else.
3410*38e8c45fSAndroid Build Coastguard Worker         RunDumpsysCritical();
3411*38e8c45fSAndroid Build Coastguard Worker 
3412*38e8c45fSAndroid Build Coastguard Worker         // Snapshot the UI traces now (if running).
3413*38e8c45fSAndroid Build Coastguard Worker         // The trace files will be added to bugreport later.
3414*38e8c45fSAndroid Build Coastguard Worker         MaybeSnapshotUiTraces();
3415*38e8c45fSAndroid Build Coastguard Worker     }
3416*38e8c45fSAndroid Build Coastguard Worker 
3417*38e8c45fSAndroid Build Coastguard Worker     MaybeTakeEarlyScreenshot();
3418*38e8c45fSAndroid Build Coastguard Worker     MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
3419*38e8c45fSAndroid Build Coastguard Worker     onUiIntensiveBugreportDumpsFinished(calling_uid);
3420*38e8c45fSAndroid Build Coastguard Worker     MaybeCheckUserConsent(calling_uid, calling_package);
3421*38e8c45fSAndroid Build Coastguard Worker     if (options_->telephony_only) {
3422*38e8c45fSAndroid Build Coastguard Worker         DumpstateTelephonyOnly(calling_package);
3423*38e8c45fSAndroid Build Coastguard Worker     } else if (options_->wifi_only) {
3424*38e8c45fSAndroid Build Coastguard Worker         DumpstateWifiOnly();
3425*38e8c45fSAndroid Build Coastguard Worker     } else if (options_->limited_only) {
3426*38e8c45fSAndroid Build Coastguard Worker         DumpstateLimitedOnly();
3427*38e8c45fSAndroid Build Coastguard Worker     } else if (options_->onboarding_only) {
3428*38e8c45fSAndroid Build Coastguard Worker         DumpstateOnboardingOnly();
3429*38e8c45fSAndroid Build Coastguard Worker     } else {
3430*38e8c45fSAndroid Build Coastguard Worker         // Dump state for the default case. This also drops root.
3431*38e8c45fSAndroid Build Coastguard Worker         RunStatus s = DumpstateDefaultAfterCritical();
3432*38e8c45fSAndroid Build Coastguard Worker         if (s != RunStatus::OK) {
3433*38e8c45fSAndroid Build Coastguard Worker             if (s == RunStatus::USER_CONSENT_DENIED) {
3434*38e8c45fSAndroid Build Coastguard Worker                 HandleUserConsentDenied();
3435*38e8c45fSAndroid Build Coastguard Worker             }
3436*38e8c45fSAndroid Build Coastguard Worker             return s;
3437*38e8c45fSAndroid Build Coastguard Worker         }
3438*38e8c45fSAndroid Build Coastguard Worker     }
3439*38e8c45fSAndroid Build Coastguard Worker 
3440*38e8c45fSAndroid Build Coastguard Worker     /* close output if needed */
3441*38e8c45fSAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
3442*38e8c45fSAndroid Build Coastguard Worker 
3443*38e8c45fSAndroid Build Coastguard Worker     // Zip the (now complete) .tmp file within the internal directory.
3444*38e8c45fSAndroid Build Coastguard Worker     ATRACE_BEGIN("FinalizeFile");
3445*38e8c45fSAndroid Build Coastguard Worker     FinalizeFile();
3446*38e8c45fSAndroid Build Coastguard Worker     ATRACE_END();
3447*38e8c45fSAndroid Build Coastguard Worker 
3448*38e8c45fSAndroid Build Coastguard Worker     // Share the final file with the caller if the user has consented or Shell is the caller.
3449*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
3450*38e8c45fSAndroid Build Coastguard Worker     if (CalledByApi() && !options_->is_consent_deferred) {
3451*38e8c45fSAndroid Build Coastguard Worker         status = CopyBugreportIfUserConsented(calling_uid);
3452*38e8c45fSAndroid Build Coastguard Worker         if (status != Dumpstate::RunStatus::OK &&
3453*38e8c45fSAndroid Build Coastguard Worker             status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3454*38e8c45fSAndroid Build Coastguard Worker             // Do an early return if there were errors. We make an exception for consent
3455*38e8c45fSAndroid Build Coastguard Worker             // timing out because it's possible the user got distracted. In this case the
3456*38e8c45fSAndroid Build Coastguard Worker             // bugreport is not shared but made available for manual retrieval.
3457*38e8c45fSAndroid Build Coastguard Worker             MYLOGI("Bug report generation failed, this could have been due to"
3458*38e8c45fSAndroid Build Coastguard Worker                    " several reasons such as BR copy failed, user consent was"
3459*38e8c45fSAndroid Build Coastguard Worker                    " not grated etc. Returning\n");
3460*38e8c45fSAndroid Build Coastguard Worker             return status;
3461*38e8c45fSAndroid Build Coastguard Worker         }
3462*38e8c45fSAndroid Build Coastguard Worker         if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3463*38e8c45fSAndroid Build Coastguard Worker             MYLOGI(
3464*38e8c45fSAndroid Build Coastguard Worker                 "Did not receive user consent yet."
3465*38e8c45fSAndroid Build Coastguard Worker                 " Will not copy the bugreport artifacts to caller.\n");
3466*38e8c45fSAndroid Build Coastguard Worker             const String16 incidentcompanion("incidentcompanion");
3467*38e8c45fSAndroid Build Coastguard Worker             sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3468*38e8c45fSAndroid Build Coastguard Worker             if (ics != nullptr) {
3469*38e8c45fSAndroid Build Coastguard Worker                 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3470*38e8c45fSAndroid Build Coastguard Worker                 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3471*38e8c45fSAndroid Build Coastguard Worker                         consent_callback_.get());
3472*38e8c45fSAndroid Build Coastguard Worker             } else {
3473*38e8c45fSAndroid Build Coastguard Worker                 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3474*38e8c45fSAndroid Build Coastguard Worker             }
3475*38e8c45fSAndroid Build Coastguard Worker         }
3476*38e8c45fSAndroid Build Coastguard Worker     }
3477*38e8c45fSAndroid Build Coastguard Worker 
3478*38e8c45fSAndroid Build Coastguard Worker     /* vibrate a few but shortly times to let user know it's finished */
3479*38e8c45fSAndroid Build Coastguard Worker     if (options_->do_vibrate) {
3480*38e8c45fSAndroid Build Coastguard Worker         for (int i = 0; i < 3; i++) {
3481*38e8c45fSAndroid Build Coastguard Worker             Vibrate(75);
3482*38e8c45fSAndroid Build Coastguard Worker             usleep((75 + 50) * 1000);
3483*38e8c45fSAndroid Build Coastguard Worker         }
3484*38e8c45fSAndroid Build Coastguard Worker     }
3485*38e8c45fSAndroid Build Coastguard Worker 
3486*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3487*38e8c45fSAndroid Build Coastguard Worker            progress_->GetInitialMax());
3488*38e8c45fSAndroid Build Coastguard Worker     progress_->Save();
3489*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("done (id %d)\n", id_);
3490*38e8c45fSAndroid Build Coastguard Worker 
3491*38e8c45fSAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
3492*38e8c45fSAndroid Build Coastguard Worker 
3493*38e8c45fSAndroid Build Coastguard Worker     if (control_socket_fd_ != -1) {
3494*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Closing control socket\n");
3495*38e8c45fSAndroid Build Coastguard Worker         close(control_socket_fd_);
3496*38e8c45fSAndroid Build Coastguard Worker     }
3497*38e8c45fSAndroid Build Coastguard Worker 
3498*38e8c45fSAndroid Build Coastguard Worker     tombstone_data_.clear();
3499*38e8c45fSAndroid Build Coastguard Worker     anr_data_.clear();
3500*38e8c45fSAndroid Build Coastguard Worker     anr_trace_data_.clear();
3501*38e8c45fSAndroid Build Coastguard Worker     shutdown_checkpoints_.clear();
3502*38e8c45fSAndroid Build Coastguard Worker 
3503*38e8c45fSAndroid Build Coastguard Worker     return (consent_callback_ != nullptr &&
3504*38e8c45fSAndroid Build Coastguard Worker             consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3505*38e8c45fSAndroid Build Coastguard Worker                ? USER_CONSENT_TIMED_OUT
3506*38e8c45fSAndroid Build Coastguard Worker                : RunStatus::OK;
3507*38e8c45fSAndroid Build Coastguard Worker }
3508*38e8c45fSAndroid Build Coastguard Worker 
MaybeTakeEarlyScreenshot()3509*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::MaybeTakeEarlyScreenshot() {
3510*38e8c45fSAndroid Build Coastguard Worker     if (!options_->do_screenshot || !do_early_screenshot_) {
3511*38e8c45fSAndroid Build Coastguard Worker         return;
3512*38e8c45fSAndroid Build Coastguard Worker     }
3513*38e8c45fSAndroid Build Coastguard Worker 
3514*38e8c45fSAndroid Build Coastguard Worker     TakeScreenshot();
3515*38e8c45fSAndroid Build Coastguard Worker }
3516*38e8c45fSAndroid Build Coastguard Worker 
MaybeSnapshotSystemTraceAsync()3517*38e8c45fSAndroid Build Coastguard Worker std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
3518*38e8c45fSAndroid Build Coastguard Worker     // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3519*38e8c45fSAndroid Build Coastguard Worker     // 1) When BH invokes IDumpstate::PreDumpUiData()
3520*38e8c45fSAndroid Build Coastguard Worker     // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3521*38e8c45fSAndroid Build Coastguard Worker     // In this case we don't want to re-invoke perfetto in step 2.
3522*38e8c45fSAndroid Build Coastguard Worker     // In all other standard invocation states, this function is invoked once
3523*38e8c45fSAndroid Build Coastguard Worker     // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
3524*38e8c45fSAndroid Build Coastguard Worker     // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3525*38e8c45fSAndroid Build Coastguard Worker     // standard invocation states (b/316110955).
3526*38e8c45fSAndroid Build Coastguard Worker     if (options_->use_predumped_ui_data) {
3527*38e8c45fSAndroid Build Coastguard Worker         return {};
3528*38e8c45fSAndroid Build Coastguard Worker     }
3529*38e8c45fSAndroid Build Coastguard Worker 
3530*38e8c45fSAndroid Build Coastguard Worker     // Create temporary file for the command's output
3531*38e8c45fSAndroid Build Coastguard Worker     std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3532*38e8c45fSAndroid Build Coastguard Worker     auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3533*38e8c45fSAndroid Build Coastguard Worker         open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3534*38e8c45fSAndroid Build Coastguard Worker              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3535*38e8c45fSAndroid Build Coastguard Worker     if (outFd < 0) {
3536*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3537*38e8c45fSAndroid Build Coastguard Worker         return {};
3538*38e8c45fSAndroid Build Coastguard Worker     }
3539*38e8c45fSAndroid Build Coastguard Worker 
3540*38e8c45fSAndroid Build Coastguard Worker     // If a stale file exists already, remove it.
3541*38e8c45fSAndroid Build Coastguard Worker     unlink(SYSTEM_TRACE_SNAPSHOT);
3542*38e8c45fSAndroid Build Coastguard Worker 
3543*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3544*38e8c45fSAndroid Build Coastguard Worker     return std::async(
3545*38e8c45fSAndroid Build Coastguard Worker         std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3546*38e8c45fSAndroid Build Coastguard Worker             // If a background system trace is happening and is marked as "suitable for
3547*38e8c45fSAndroid Build Coastguard Worker             // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3548*38e8c45fSAndroid Build Coastguard Worker             // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3549*38e8c45fSAndroid Build Coastguard Worker             // case that no trace is ongoing, this command is a no-op.
3550*38e8c45fSAndroid Build Coastguard Worker             // Note: this should not be enqueued as we need to freeze the trace before
3551*38e8c45fSAndroid Build Coastguard Worker             // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3552*38e8c45fSAndroid Build Coastguard Worker             // the dumpstate's own activity which is irrelevant.
3553*38e8c45fSAndroid Build Coastguard Worker             RunCommand(
3554*38e8c45fSAndroid Build Coastguard Worker                 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3555*38e8c45fSAndroid Build Coastguard Worker                 CommandOptions::WithTimeout(30).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3556*38e8c45fSAndroid Build Coastguard Worker                 false, outFd);
3557*38e8c45fSAndroid Build Coastguard Worker             // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3558*38e8c45fSAndroid Build Coastguard Worker             // file in the later stages.
3559*38e8c45fSAndroid Build Coastguard Worker 
3560*38e8c45fSAndroid Build Coastguard Worker             return outPath;
3561*38e8c45fSAndroid Build Coastguard Worker         });
3562*38e8c45fSAndroid Build Coastguard Worker }
3563*38e8c45fSAndroid Build Coastguard Worker 
MaybeWaitForSnapshotSystemTrace(std::future<std::string> task)3564*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3565*38e8c45fSAndroid Build Coastguard Worker     if (!task.valid()) {
3566*38e8c45fSAndroid Build Coastguard Worker         return;
3567*38e8c45fSAndroid Build Coastguard Worker     }
3568*38e8c45fSAndroid Build Coastguard Worker 
3569*38e8c45fSAndroid Build Coastguard Worker     WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
3570*38e8c45fSAndroid Build Coastguard Worker }
3571*38e8c45fSAndroid Build Coastguard Worker 
MaybeSnapshotUiTraces()3572*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::MaybeSnapshotUiTraces() {
3573*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3574*38e8c45fSAndroid Build Coastguard Worker         return;
3575*38e8c45fSAndroid Build Coastguard Worker     }
3576*38e8c45fSAndroid Build Coastguard Worker 
3577*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3578*38e8c45fSAndroid Build Coastguard Worker         {"cmd", "input_method", "tracing", "save-for-bugreport"},
3579*38e8c45fSAndroid Build Coastguard Worker         {"cmd", "window", "tracing", "save-for-bugreport"},
3580*38e8c45fSAndroid Build Coastguard Worker         {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3581*38e8c45fSAndroid Build Coastguard Worker     };
3582*38e8c45fSAndroid Build Coastguard Worker 
3583*38e8c45fSAndroid Build Coastguard Worker     if (!android_tracing_perfetto_transition_tracing()) {
3584*38e8c45fSAndroid Build Coastguard Worker         dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3585*38e8c45fSAndroid Build Coastguard Worker                                                   "SystemUIService", "WMShell", "transitions",
3586*38e8c45fSAndroid Build Coastguard Worker                                                   "tracing", "save-for-bugreport"});
3587*38e8c45fSAndroid Build Coastguard Worker     }
3588*38e8c45fSAndroid Build Coastguard Worker 
3589*38e8c45fSAndroid Build Coastguard Worker     if (!android_tracing_perfetto_protolog_tracing()) {
3590*38e8c45fSAndroid Build Coastguard Worker         dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3591*38e8c45fSAndroid Build Coastguard Worker                                                   "SystemUIService", "WMShell", "protolog",
3592*38e8c45fSAndroid Build Coastguard Worker                                                   "save-for-bugreport"});
3593*38e8c45fSAndroid Build Coastguard Worker     }
3594*38e8c45fSAndroid Build Coastguard Worker 
3595*38e8c45fSAndroid Build Coastguard Worker     for (const auto& command : dumpTracesForBugReportCommands) {
3596*38e8c45fSAndroid Build Coastguard Worker         RunCommand(
3597*38e8c45fSAndroid Build Coastguard Worker             // Empty name because it's not intended to be classified as a bugreport section.
3598*38e8c45fSAndroid Build Coastguard Worker             // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3599*38e8c45fSAndroid Build Coastguard Worker             "", command,
3600*38e8c45fSAndroid Build Coastguard Worker             CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3601*38e8c45fSAndroid Build Coastguard Worker     }
3602*38e8c45fSAndroid Build Coastguard Worker }
3603*38e8c45fSAndroid Build Coastguard Worker 
MaybeAddUiTracesToZip()3604*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::MaybeAddUiTracesToZip() {
3605*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsUserBuild()) {
3606*38e8c45fSAndroid Build Coastguard Worker         return;
3607*38e8c45fSAndroid Build Coastguard Worker     }
3608*38e8c45fSAndroid Build Coastguard Worker 
3609*38e8c45fSAndroid Build Coastguard Worker     ds.AddDir(WMTRACE_DATA_DIR, false);
3610*38e8c45fSAndroid Build Coastguard Worker }
3611*38e8c45fSAndroid Build Coastguard Worker 
onUiIntensiveBugreportDumpsFinished(int32_t calling_uid)3612*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
3613*38e8c45fSAndroid Build Coastguard Worker     if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
3614*38e8c45fSAndroid Build Coastguard Worker         return;
3615*38e8c45fSAndroid Build Coastguard Worker     }
3616*38e8c45fSAndroid Build Coastguard Worker     if (listener_ != nullptr) {
3617*38e8c45fSAndroid Build Coastguard Worker         // Let listener know ui intensive bugreport dumps are finished, then it can do event
3618*38e8c45fSAndroid Build Coastguard Worker         // handling if required.
3619*38e8c45fSAndroid Build Coastguard Worker         listener_->onUiIntensiveBugreportDumpsFinished();
3620*38e8c45fSAndroid Build Coastguard Worker     }
3621*38e8c45fSAndroid Build Coastguard Worker }
3622*38e8c45fSAndroid Build Coastguard Worker 
MaybeCheckUserConsent(int32_t calling_uid,const std::string & calling_package)3623*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3624*38e8c45fSAndroid Build Coastguard Worker     if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3625*38e8c45fSAndroid Build Coastguard Worker         !CalledByApi() || options_->is_consent_deferred ||
3626*38e8c45fSAndroid Build Coastguard Worker         (android::app::admin::flags::onboarding_consentless_bugreports() &&
3627*38e8c45fSAndroid Build Coastguard Worker         options_->skip_user_consent)) {
3628*38e8c45fSAndroid Build Coastguard Worker         // No need to get consent for shell triggered dumpstates, or not
3629*38e8c45fSAndroid Build Coastguard Worker         // through bugreporting API (i.e. no fd to copy back), or when consent
3630*38e8c45fSAndroid Build Coastguard Worker         // is deferred.
3631*38e8c45fSAndroid Build Coastguard Worker         return;
3632*38e8c45fSAndroid Build Coastguard Worker     }
3633*38e8c45fSAndroid Build Coastguard Worker     consent_callback_ = new ConsentCallback();
3634*38e8c45fSAndroid Build Coastguard Worker     const String16 incidentcompanion("incidentcompanion");
3635*38e8c45fSAndroid Build Coastguard Worker     sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3636*38e8c45fSAndroid Build Coastguard Worker     android::String16 package(calling_package.c_str());
3637*38e8c45fSAndroid Build Coastguard Worker     if (ics != nullptr) {
3638*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Checking user consent via incidentcompanion service\n");
3639*38e8c45fSAndroid Build Coastguard Worker         int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3640*38e8c45fSAndroid Build Coastguard Worker         if (IsConsentlessBugreportAllowed(*options_)) {
3641*38e8c45fSAndroid Build Coastguard Worker             flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3642*38e8c45fSAndroid Build Coastguard Worker         }
3643*38e8c45fSAndroid Build Coastguard Worker         android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3644*38e8c45fSAndroid Build Coastguard Worker             calling_uid, package, String16(), String16(), flags, consent_callback_.get());
3645*38e8c45fSAndroid Build Coastguard Worker     } else {
3646*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3647*38e8c45fSAndroid Build Coastguard Worker     }
3648*38e8c45fSAndroid Build Coastguard Worker }
3649*38e8c45fSAndroid Build Coastguard Worker 
IsUserConsentDenied() const3650*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::IsUserConsentDenied() const {
3651*38e8c45fSAndroid Build Coastguard Worker     return ds.consent_callback_ != nullptr &&
3652*38e8c45fSAndroid Build Coastguard Worker            ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3653*38e8c45fSAndroid Build Coastguard Worker }
3654*38e8c45fSAndroid Build Coastguard Worker 
CalledByApi() const3655*38e8c45fSAndroid Build Coastguard Worker bool Dumpstate::CalledByApi() const {
3656*38e8c45fSAndroid Build Coastguard Worker     return ds.options_->bugreport_fd.get() != -1 ? true : false;
3657*38e8c45fSAndroid Build Coastguard Worker }
3658*38e8c45fSAndroid Build Coastguard Worker 
CleanupTmpFiles()3659*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::CleanupTmpFiles() {
3660*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(tmp_path_);
3661*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(screenshot_path_);
3662*38e8c45fSAndroid Build Coastguard Worker     android::os::UnlinkAndLogOnError(path_);
3663*38e8c45fSAndroid Build Coastguard Worker     if (dump_traces_path != nullptr) {
3664*38e8c45fSAndroid Build Coastguard Worker         android::os::UnlinkAndLogOnError(dump_traces_path);
3665*38e8c45fSAndroid Build Coastguard Worker     }
3666*38e8c45fSAndroid Build Coastguard Worker }
3667*38e8c45fSAndroid Build Coastguard Worker 
EnableParallelRunIfNeeded()3668*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::EnableParallelRunIfNeeded() {
3669*38e8c45fSAndroid Build Coastguard Worker     if (!PropertiesHelper::IsParallelRun()) {
3670*38e8c45fSAndroid Build Coastguard Worker         return;
3671*38e8c45fSAndroid Build Coastguard Worker     }
3672*38e8c45fSAndroid Build Coastguard Worker     dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
3673*38e8c45fSAndroid Build Coastguard Worker     zip_entry_tasks_ = std::make_unique<TaskQueue>();
3674*38e8c45fSAndroid Build Coastguard Worker }
3675*38e8c45fSAndroid Build Coastguard Worker 
ShutdownDumpPool()3676*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::ShutdownDumpPool() {
3677*38e8c45fSAndroid Build Coastguard Worker     if (dump_pool_) {
3678*38e8c45fSAndroid Build Coastguard Worker         dump_pool_.reset();
3679*38e8c45fSAndroid Build Coastguard Worker     }
3680*38e8c45fSAndroid Build Coastguard Worker     if (zip_entry_tasks_) {
3681*38e8c45fSAndroid Build Coastguard Worker         zip_entry_tasks_->run(/* do_cancel = */true);
3682*38e8c45fSAndroid Build Coastguard Worker         zip_entry_tasks_ = nullptr;
3683*38e8c45fSAndroid Build Coastguard Worker     }
3684*38e8c45fSAndroid Build Coastguard Worker }
3685*38e8c45fSAndroid Build Coastguard Worker 
EnqueueAddZipEntryAndCleanupIfNeeded(const std::string & entry_name,const std::string & entry_path)3686*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3687*38e8c45fSAndroid Build Coastguard Worker         const std::string& entry_path) {
3688*38e8c45fSAndroid Build Coastguard Worker     auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3689*38e8c45fSAndroid Build Coastguard Worker         if (!task_cancelled) {
3690*38e8c45fSAndroid Build Coastguard Worker             AddZipEntry(entry_name, entry_path);
3691*38e8c45fSAndroid Build Coastguard Worker         }
3692*38e8c45fSAndroid Build Coastguard Worker         android::os::UnlinkAndLogOnError(entry_path);
3693*38e8c45fSAndroid Build Coastguard Worker     };
3694*38e8c45fSAndroid Build Coastguard Worker     if (zip_entry_tasks_) {
3695*38e8c45fSAndroid Build Coastguard Worker         // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3696*38e8c45fSAndroid Build Coastguard Worker         zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3697*38e8c45fSAndroid Build Coastguard Worker     } else {
3698*38e8c45fSAndroid Build Coastguard Worker         // Invokes AddZipEntryAndCleanup immediately
3699*38e8c45fSAndroid Build Coastguard Worker         std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3700*38e8c45fSAndroid Build Coastguard Worker     }
3701*38e8c45fSAndroid Build Coastguard Worker }
3702*38e8c45fSAndroid Build Coastguard Worker 
HandleUserConsentDenied()3703*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3704*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("User denied consent; deleting files and returning\n");
3705*38e8c45fSAndroid Build Coastguard Worker     CleanupTmpFiles();
3706*38e8c45fSAndroid Build Coastguard Worker     return USER_CONSENT_DENIED;
3707*38e8c45fSAndroid Build Coastguard Worker }
3708*38e8c45fSAndroid Build Coastguard Worker 
CopyBugreportIfUserConsented(int32_t calling_uid)3709*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
3710*38e8c45fSAndroid Build Coastguard Worker     // If the caller has asked to copy the bugreport over to their directory, we need explicit
3711*38e8c45fSAndroid Build Coastguard Worker     // user consent (unless the caller is Shell).
3712*38e8c45fSAndroid Build Coastguard Worker     UserConsentResult consent_result;
3713*38e8c45fSAndroid Build Coastguard Worker     if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3714*38e8c45fSAndroid Build Coastguard Worker     && android::app::admin::flags::onboarding_consentless_bugreports())) {
3715*38e8c45fSAndroid Build Coastguard Worker         consent_result = UserConsentResult::APPROVED;
3716*38e8c45fSAndroid Build Coastguard Worker     } else {
3717*38e8c45fSAndroid Build Coastguard Worker         consent_result = consent_callback_->getResult();
3718*38e8c45fSAndroid Build Coastguard Worker     }
3719*38e8c45fSAndroid Build Coastguard Worker     if (consent_result == UserConsentResult::UNAVAILABLE) {
3720*38e8c45fSAndroid Build Coastguard Worker         // User has not responded yet.
3721*38e8c45fSAndroid Build Coastguard Worker         uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
3722*38e8c45fSAndroid Build Coastguard Worker         // Telephony is a fast report type, particularly on user builds where information may be
3723*38e8c45fSAndroid Build Coastguard Worker         // more aggressively limited. To give the user time to read the consent dialog, increase the
3724*38e8c45fSAndroid Build Coastguard Worker         // timeout.
3725*38e8c45fSAndroid Build Coastguard Worker         uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3726*38e8c45fSAndroid Build Coastguard Worker                                                        : USER_CONSENT_TIMEOUT_MS;
3727*38e8c45fSAndroid Build Coastguard Worker         if (elapsed_ms < timeout_ms) {
3728*38e8c45fSAndroid Build Coastguard Worker             uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
3729*38e8c45fSAndroid Build Coastguard Worker             MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3730*38e8c45fSAndroid Build Coastguard Worker             sleep(delay_seconds);
3731*38e8c45fSAndroid Build Coastguard Worker         }
3732*38e8c45fSAndroid Build Coastguard Worker         consent_result = consent_callback_->getResult();
3733*38e8c45fSAndroid Build Coastguard Worker     }
3734*38e8c45fSAndroid Build Coastguard Worker     if (consent_result == UserConsentResult::DENIED) {
3735*38e8c45fSAndroid Build Coastguard Worker         // User has explicitly denied sharing with the app. To be safe delete the
3736*38e8c45fSAndroid Build Coastguard Worker         // internal bugreport & tmp files.
3737*38e8c45fSAndroid Build Coastguard Worker         return HandleUserConsentDenied();
3738*38e8c45fSAndroid Build Coastguard Worker     }
3739*38e8c45fSAndroid Build Coastguard Worker     if (consent_result == UserConsentResult::APPROVED) {
3740*38e8c45fSAndroid Build Coastguard Worker         bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3741*38e8c45fSAndroid Build Coastguard Worker         if (copy_succeeded) {
3742*38e8c45fSAndroid Build Coastguard Worker             android::os::UnlinkAndLogOnError(path_);
3743*38e8c45fSAndroid Build Coastguard Worker             if (options_->do_screenshot &&
3744*38e8c45fSAndroid Build Coastguard Worker                 options_->screenshot_fd.get() != -1 &&
3745*38e8c45fSAndroid Build Coastguard Worker                 !options_->is_screenshot_copied) {
3746*38e8c45fSAndroid Build Coastguard Worker                 bool is_screenshot_copied = android::os::CopyFileToFd(screenshot_path_,
3747*38e8c45fSAndroid Build Coastguard Worker                                                            options_->screenshot_fd.get());
3748*38e8c45fSAndroid Build Coastguard Worker                 if (is_screenshot_copied) {
3749*38e8c45fSAndroid Build Coastguard Worker                     android::os::UnlinkAndLogOnError(screenshot_path_);
3750*38e8c45fSAndroid Build Coastguard Worker                 } else {
3751*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("Failed to copy screenshot to a permanent file.\n");
3752*38e8c45fSAndroid Build Coastguard Worker                     is_screenshot_copied = android::os::CopyFileToFd(DEFAULT_SCREENSHOT_PATH,
3753*38e8c45fSAndroid Build Coastguard Worker                                                            options_->screenshot_fd.get());
3754*38e8c45fSAndroid Build Coastguard Worker                 }
3755*38e8c45fSAndroid Build Coastguard Worker                 options_->is_screenshot_copied = is_screenshot_copied;
3756*38e8c45fSAndroid Build Coastguard Worker             }
3757*38e8c45fSAndroid Build Coastguard Worker         }
3758*38e8c45fSAndroid Build Coastguard Worker         return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3759*38e8c45fSAndroid Build Coastguard Worker     } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3760*38e8c45fSAndroid Build Coastguard Worker         // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3761*38e8c45fSAndroid Build Coastguard Worker         // Since we do not have user consent to share the bugreport it does not get
3762*38e8c45fSAndroid Build Coastguard Worker         // copied over to the calling app but remains in the internal directory from
3763*38e8c45fSAndroid Build Coastguard Worker         // where the user can manually pull it.
3764*38e8c45fSAndroid Build Coastguard Worker         std::string final_path = GetPath(".zip");
3765*38e8c45fSAndroid Build Coastguard Worker         bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3766*38e8c45fSAndroid Build Coastguard Worker         if (copy_succeeded) {
3767*38e8c45fSAndroid Build Coastguard Worker             android::os::UnlinkAndLogOnError(path_);
3768*38e8c45fSAndroid Build Coastguard Worker         }
3769*38e8c45fSAndroid Build Coastguard Worker         return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3770*38e8c45fSAndroid Build Coastguard Worker     }
3771*38e8c45fSAndroid Build Coastguard Worker     // Unknown result; must be a programming error.
3772*38e8c45fSAndroid Build Coastguard Worker     MYLOGE("Unknown user consent result:%d\n", consent_result);
3773*38e8c45fSAndroid Build Coastguard Worker     return Dumpstate::RunStatus::ERROR;
3774*38e8c45fSAndroid Build Coastguard Worker }
3775*38e8c45fSAndroid Build Coastguard Worker 
ParseCommandlineAndRun(int argc,char * argv[])3776*38e8c45fSAndroid Build Coastguard Worker Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
3777*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3778*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = options->Initialize(argc, argv);
3779*38e8c45fSAndroid Build Coastguard Worker     if (status == Dumpstate::RunStatus::OK) {
3780*38e8c45fSAndroid Build Coastguard Worker         SetOptions(std::move(options));
3781*38e8c45fSAndroid Build Coastguard Worker         // When directly running dumpstate binary, the output is not expected to be written
3782*38e8c45fSAndroid Build Coastguard Worker         // to any external file descriptor.
3783*38e8c45fSAndroid Build Coastguard Worker         assert(options_->bugreport_fd.get() == -1);
3784*38e8c45fSAndroid Build Coastguard Worker 
3785*38e8c45fSAndroid Build Coastguard Worker         // calling_uid and calling_package are for user consent to share the bugreport with
3786*38e8c45fSAndroid Build Coastguard Worker         // an app; they are irrelevant here because bugreport is triggered via command line.
3787*38e8c45fSAndroid Build Coastguard Worker         // Update Last ID before calling Run().
3788*38e8c45fSAndroid Build Coastguard Worker         Initialize();
3789*38e8c45fSAndroid Build Coastguard Worker         status = Run(0 /* calling_uid */, "" /* calling_package */);
3790*38e8c45fSAndroid Build Coastguard Worker     }
3791*38e8c45fSAndroid Build Coastguard Worker     return status;
3792*38e8c45fSAndroid Build Coastguard Worker }
3793*38e8c45fSAndroid Build Coastguard Worker 
3794*38e8c45fSAndroid Build Coastguard Worker /* Main entry point for dumpstate binary. */
run_main(int argc,char * argv[])3795*38e8c45fSAndroid Build Coastguard Worker int run_main(int argc, char* argv[]) {
3796*38e8c45fSAndroid Build Coastguard Worker     Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
3797*38e8c45fSAndroid Build Coastguard Worker 
3798*38e8c45fSAndroid Build Coastguard Worker     switch (status) {
3799*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::OK:
3800*38e8c45fSAndroid Build Coastguard Worker             exit(0);
3801*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::HELP:
3802*38e8c45fSAndroid Build Coastguard Worker             ShowUsage();
3803*38e8c45fSAndroid Build Coastguard Worker             exit(0);
3804*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::INVALID_INPUT:
3805*38e8c45fSAndroid Build Coastguard Worker             fprintf(stderr, "Invalid combination of args\n");
3806*38e8c45fSAndroid Build Coastguard Worker             ShowUsage();
3807*38e8c45fSAndroid Build Coastguard Worker             exit(1);
3808*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::ERROR:
3809*38e8c45fSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
3810*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3811*38e8c45fSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
3812*38e8c45fSAndroid Build Coastguard Worker         case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3813*38e8c45fSAndroid Build Coastguard Worker             exit(2);
3814*38e8c45fSAndroid Build Coastguard Worker     }
3815*38e8c45fSAndroid Build Coastguard Worker }
3816*38e8c45fSAndroid Build Coastguard Worker 
3817*38e8c45fSAndroid Build Coastguard Worker // TODO(111441001): Default DumpOptions to sensible values.
Dumpstate(const std::string & version)3818*38e8c45fSAndroid Build Coastguard Worker Dumpstate::Dumpstate(const std::string& version)
3819*38e8c45fSAndroid Build Coastguard Worker     : pid_(getpid()),
3820*38e8c45fSAndroid Build Coastguard Worker       options_(new Dumpstate::DumpOptions()),
3821*38e8c45fSAndroid Build Coastguard Worker       last_reported_percent_progress_(0),
3822*38e8c45fSAndroid Build Coastguard Worker       version_(version),
3823*38e8c45fSAndroid Build Coastguard Worker       now_(time(nullptr)),
3824*38e8c45fSAndroid Build Coastguard Worker       open_socket_fn_(open_socket) {
3825*38e8c45fSAndroid Build Coastguard Worker }
3826*38e8c45fSAndroid Build Coastguard Worker 
GetInstance()3827*38e8c45fSAndroid Build Coastguard Worker Dumpstate& Dumpstate::GetInstance() {
3828*38e8c45fSAndroid Build Coastguard Worker     static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3829*38e8c45fSAndroid Build Coastguard Worker     return singleton_;
3830*38e8c45fSAndroid Build Coastguard Worker }
3831*38e8c45fSAndroid Build Coastguard Worker 
DurationReporter(const std::string & title,bool logcat_only,bool verbose,int duration_fd)3832*38e8c45fSAndroid Build Coastguard Worker DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3833*38e8c45fSAndroid Build Coastguard Worker         int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3834*38e8c45fSAndroid Build Coastguard Worker         duration_fd_(duration_fd) {
3835*38e8c45fSAndroid Build Coastguard Worker     if (!title_.empty()) {
3836*38e8c45fSAndroid Build Coastguard Worker         started_ = Nanotime();
3837*38e8c45fSAndroid Build Coastguard Worker         if (title_.find("SHOW MAP") == std::string::npos) {
3838*38e8c45fSAndroid Build Coastguard Worker             ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3839*38e8c45fSAndroid Build Coastguard Worker         }
3840*38e8c45fSAndroid Build Coastguard Worker     }
3841*38e8c45fSAndroid Build Coastguard Worker }
3842*38e8c45fSAndroid Build Coastguard Worker 
~DurationReporter()3843*38e8c45fSAndroid Build Coastguard Worker DurationReporter::~DurationReporter() {
3844*38e8c45fSAndroid Build Coastguard Worker     if (!title_.empty()) {
3845*38e8c45fSAndroid Build Coastguard Worker         float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
3846*38e8c45fSAndroid Build Coastguard Worker         if (elapsed >= 1.0f || verbose_) {
3847*38e8c45fSAndroid Build Coastguard Worker             MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
3848*38e8c45fSAndroid Build Coastguard Worker         }
3849*38e8c45fSAndroid Build Coastguard Worker         if (!logcat_only_) {
3850*38e8c45fSAndroid Build Coastguard Worker             // Use "Yoda grammar" to make it easier to grep|sort sections.
3851*38e8c45fSAndroid Build Coastguard Worker             dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3852*38e8c45fSAndroid Build Coastguard Worker                     elapsed, title_.c_str());
3853*38e8c45fSAndroid Build Coastguard Worker         }
3854*38e8c45fSAndroid Build Coastguard Worker         if (title_.find("SHOW MAP") == std::string::npos) {
3855*38e8c45fSAndroid Build Coastguard Worker             ATRACE_ASYNC_END(title_.c_str(), 0);
3856*38e8c45fSAndroid Build Coastguard Worker         }
3857*38e8c45fSAndroid Build Coastguard Worker     }
3858*38e8c45fSAndroid Build Coastguard Worker }
3859*38e8c45fSAndroid Build Coastguard Worker 
3860*38e8c45fSAndroid Build Coastguard Worker const int32_t Progress::kDefaultMax = 5000;
3861*38e8c45fSAndroid Build Coastguard Worker 
Progress(const std::string & path)3862*38e8c45fSAndroid Build Coastguard Worker Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3863*38e8c45fSAndroid Build Coastguard Worker }
3864*38e8c45fSAndroid Build Coastguard Worker 
Progress(int32_t initial_max,int32_t progress,float growth_factor)3865*38e8c45fSAndroid Build Coastguard Worker Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3866*38e8c45fSAndroid Build Coastguard Worker     : Progress(initial_max, growth_factor, "") {
3867*38e8c45fSAndroid Build Coastguard Worker     progress_ = progress;
3868*38e8c45fSAndroid Build Coastguard Worker }
3869*38e8c45fSAndroid Build Coastguard Worker 
Progress(int32_t initial_max,float growth_factor,const std::string & path)3870*38e8c45fSAndroid Build Coastguard Worker Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3871*38e8c45fSAndroid Build Coastguard Worker     : initial_max_(initial_max),
3872*38e8c45fSAndroid Build Coastguard Worker       progress_(0),
3873*38e8c45fSAndroid Build Coastguard Worker       max_(initial_max),
3874*38e8c45fSAndroid Build Coastguard Worker       growth_factor_(growth_factor),
3875*38e8c45fSAndroid Build Coastguard Worker       n_runs_(0),
3876*38e8c45fSAndroid Build Coastguard Worker       average_max_(0),
3877*38e8c45fSAndroid Build Coastguard Worker       path_(path) {
3878*38e8c45fSAndroid Build Coastguard Worker     if (!path_.empty()) {
3879*38e8c45fSAndroid Build Coastguard Worker         Load();
3880*38e8c45fSAndroid Build Coastguard Worker     }
3881*38e8c45fSAndroid Build Coastguard Worker }
3882*38e8c45fSAndroid Build Coastguard Worker 
Load()3883*38e8c45fSAndroid Build Coastguard Worker void Progress::Load() {
3884*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Loading stats from %s\n", path_.c_str());
3885*38e8c45fSAndroid Build Coastguard Worker     std::string content;
3886*38e8c45fSAndroid Build Coastguard Worker     if (!android::base::ReadFileToString(path_, &content)) {
3887*38e8c45fSAndroid Build Coastguard Worker         MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3888*38e8c45fSAndroid Build Coastguard Worker         return;
3889*38e8c45fSAndroid Build Coastguard Worker     }
3890*38e8c45fSAndroid Build Coastguard Worker     if (content.empty()) {
3891*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3892*38e8c45fSAndroid Build Coastguard Worker         return;
3893*38e8c45fSAndroid Build Coastguard Worker     }
3894*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> lines = android::base::Split(content, "\n");
3895*38e8c45fSAndroid Build Coastguard Worker 
3896*38e8c45fSAndroid Build Coastguard Worker     if (lines.size() < 1) {
3897*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3898*38e8c45fSAndroid Build Coastguard Worker                (int)lines.size(), max_);
3899*38e8c45fSAndroid Build Coastguard Worker         return;
3900*38e8c45fSAndroid Build Coastguard Worker     }
3901*38e8c45fSAndroid Build Coastguard Worker     char* ptr;
3902*38e8c45fSAndroid Build Coastguard Worker     n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3903*38e8c45fSAndroid Build Coastguard Worker     average_max_ = strtol(ptr, nullptr, 10);
3904*38e8c45fSAndroid Build Coastguard Worker     if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3905*38e8c45fSAndroid Build Coastguard Worker         average_max_ > STATS_MAX_AVERAGE) {
3906*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3907*38e8c45fSAndroid Build Coastguard Worker         initial_max_ = Progress::kDefaultMax;
3908*38e8c45fSAndroid Build Coastguard Worker     } else {
3909*38e8c45fSAndroid Build Coastguard Worker         initial_max_ = average_max_;
3910*38e8c45fSAndroid Build Coastguard Worker     }
3911*38e8c45fSAndroid Build Coastguard Worker     max_ = initial_max_;
3912*38e8c45fSAndroid Build Coastguard Worker 
3913*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3914*38e8c45fSAndroid Build Coastguard Worker }
3915*38e8c45fSAndroid Build Coastguard Worker 
Save()3916*38e8c45fSAndroid Build Coastguard Worker void Progress::Save() {
3917*38e8c45fSAndroid Build Coastguard Worker     int32_t total = n_runs_ * average_max_ + progress_;
3918*38e8c45fSAndroid Build Coastguard Worker     int32_t runs = n_runs_ + 1;
3919*38e8c45fSAndroid Build Coastguard Worker     int32_t average = floor(((float)total) / runs);
3920*38e8c45fSAndroid Build Coastguard Worker     MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3921*38e8c45fSAndroid Build Coastguard Worker            path_.c_str());
3922*38e8c45fSAndroid Build Coastguard Worker     if (path_.empty()) {
3923*38e8c45fSAndroid Build Coastguard Worker         return;
3924*38e8c45fSAndroid Build Coastguard Worker     }
3925*38e8c45fSAndroid Build Coastguard Worker 
3926*38e8c45fSAndroid Build Coastguard Worker     std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3927*38e8c45fSAndroid Build Coastguard Worker     if (!android::base::WriteStringToFile(content, path_)) {
3928*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Could not save stats on %s\n", path_.c_str());
3929*38e8c45fSAndroid Build Coastguard Worker     }
3930*38e8c45fSAndroid Build Coastguard Worker }
3931*38e8c45fSAndroid Build Coastguard Worker 
Get() const3932*38e8c45fSAndroid Build Coastguard Worker int32_t Progress::Get() const {
3933*38e8c45fSAndroid Build Coastguard Worker     return progress_;
3934*38e8c45fSAndroid Build Coastguard Worker }
3935*38e8c45fSAndroid Build Coastguard Worker 
Inc(int32_t delta_sec)3936*38e8c45fSAndroid Build Coastguard Worker bool Progress::Inc(int32_t delta_sec) {
3937*38e8c45fSAndroid Build Coastguard Worker     bool changed = false;
3938*38e8c45fSAndroid Build Coastguard Worker     if (delta_sec >= 0) {
3939*38e8c45fSAndroid Build Coastguard Worker         progress_ += delta_sec;
3940*38e8c45fSAndroid Build Coastguard Worker         if (progress_ > max_) {
3941*38e8c45fSAndroid Build Coastguard Worker             int32_t old_max = max_;
3942*38e8c45fSAndroid Build Coastguard Worker             max_ = floor((float)progress_ * growth_factor_);
3943*38e8c45fSAndroid Build Coastguard Worker             MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3944*38e8c45fSAndroid Build Coastguard Worker             changed = true;
3945*38e8c45fSAndroid Build Coastguard Worker         }
3946*38e8c45fSAndroid Build Coastguard Worker     }
3947*38e8c45fSAndroid Build Coastguard Worker     return changed;
3948*38e8c45fSAndroid Build Coastguard Worker }
3949*38e8c45fSAndroid Build Coastguard Worker 
GetMax() const3950*38e8c45fSAndroid Build Coastguard Worker int32_t Progress::GetMax() const {
3951*38e8c45fSAndroid Build Coastguard Worker     return max_;
3952*38e8c45fSAndroid Build Coastguard Worker }
3953*38e8c45fSAndroid Build Coastguard Worker 
GetInitialMax() const3954*38e8c45fSAndroid Build Coastguard Worker int32_t Progress::GetInitialMax() const {
3955*38e8c45fSAndroid Build Coastguard Worker     return initial_max_;
3956*38e8c45fSAndroid Build Coastguard Worker }
3957*38e8c45fSAndroid Build Coastguard Worker 
Dump(int fd,const std::string & prefix) const3958*38e8c45fSAndroid Build Coastguard Worker void Progress::Dump(int fd, const std::string& prefix) const {
3959*38e8c45fSAndroid Build Coastguard Worker     const char* pr = prefix.c_str();
3960*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%sprogress: %d\n", pr, progress_);
3961*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%smax: %d\n", pr, max_);
3962*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3963*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3964*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3965*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3966*38e8c45fSAndroid Build Coastguard Worker     dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3967*38e8c45fSAndroid Build Coastguard Worker }
3968*38e8c45fSAndroid Build Coastguard Worker 
GetPath(const std::string & suffix) const3969*38e8c45fSAndroid Build Coastguard Worker std::string Dumpstate::GetPath(const std::string& suffix) const {
3970*38e8c45fSAndroid Build Coastguard Worker     return GetPath(bugreport_internal_dir_, suffix);
3971*38e8c45fSAndroid Build Coastguard Worker }
3972*38e8c45fSAndroid Build Coastguard Worker 
GetPath(const std::string & directory,const std::string & suffix) const3973*38e8c45fSAndroid Build Coastguard Worker std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3974*38e8c45fSAndroid Build Coastguard Worker     return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3975*38e8c45fSAndroid Build Coastguard Worker                                        name_.c_str(), suffix.c_str());
3976*38e8c45fSAndroid Build Coastguard Worker }
3977*38e8c45fSAndroid Build Coastguard Worker 
SetProgress(std::unique_ptr<Progress> progress)3978*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3979*38e8c45fSAndroid Build Coastguard Worker     progress_ = std::move(progress);
3980*38e8c45fSAndroid Build Coastguard Worker }
3981*38e8c45fSAndroid Build Coastguard Worker 
for_each_userid(void (* func)(int),const char * header)3982*38e8c45fSAndroid Build Coastguard Worker void for_each_userid(void (*func)(int), const char *header) {
3983*38e8c45fSAndroid Build Coastguard Worker     std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3984*38e8c45fSAndroid Build Coastguard Worker                                                                     "for_each_userid(%s)", header);
3985*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
3986*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
3987*38e8c45fSAndroid Build Coastguard Worker 
3988*38e8c45fSAndroid Build Coastguard Worker     DIR *d;
3989*38e8c45fSAndroid Build Coastguard Worker     struct dirent *de;
3990*38e8c45fSAndroid Build Coastguard Worker 
3991*38e8c45fSAndroid Build Coastguard Worker     if (header) printf("\n------ %s ------\n", header);
3992*38e8c45fSAndroid Build Coastguard Worker     func(0);
3993*38e8c45fSAndroid Build Coastguard Worker 
3994*38e8c45fSAndroid Build Coastguard Worker     if (!(d = opendir("/data/system/users"))) {
3995*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3996*38e8c45fSAndroid Build Coastguard Worker         return;
3997*38e8c45fSAndroid Build Coastguard Worker     }
3998*38e8c45fSAndroid Build Coastguard Worker 
3999*38e8c45fSAndroid Build Coastguard Worker     while ((de = readdir(d))) {
4000*38e8c45fSAndroid Build Coastguard Worker         int userid;
4001*38e8c45fSAndroid Build Coastguard Worker         if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
4002*38e8c45fSAndroid Build Coastguard Worker             continue;
4003*38e8c45fSAndroid Build Coastguard Worker         }
4004*38e8c45fSAndroid Build Coastguard Worker         func(userid);
4005*38e8c45fSAndroid Build Coastguard Worker     }
4006*38e8c45fSAndroid Build Coastguard Worker 
4007*38e8c45fSAndroid Build Coastguard Worker     closedir(d);
4008*38e8c45fSAndroid Build Coastguard Worker }
4009*38e8c45fSAndroid Build Coastguard Worker 
__for_each_pid(void (* helper)(int,const char *,void *),const char * header,void * arg)4010*38e8c45fSAndroid Build Coastguard Worker static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
4011*38e8c45fSAndroid Build Coastguard Worker     DIR *d;
4012*38e8c45fSAndroid Build Coastguard Worker     struct dirent *de;
4013*38e8c45fSAndroid Build Coastguard Worker 
4014*38e8c45fSAndroid Build Coastguard Worker     if (!(d = opendir("/proc"))) {
4015*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to open /proc (%s)\n", strerror(errno));
4016*38e8c45fSAndroid Build Coastguard Worker         return;
4017*38e8c45fSAndroid Build Coastguard Worker     }
4018*38e8c45fSAndroid Build Coastguard Worker 
4019*38e8c45fSAndroid Build Coastguard Worker     if (header) printf("\n------ %s ------\n", header);
4020*38e8c45fSAndroid Build Coastguard Worker     while ((de = readdir(d))) {
4021*38e8c45fSAndroid Build Coastguard Worker         if (ds.IsUserConsentDenied()) {
4022*38e8c45fSAndroid Build Coastguard Worker             MYLOGE(
4023*38e8c45fSAndroid Build Coastguard Worker                 "Returning early because user denied consent to share bugreport with calling app.");
4024*38e8c45fSAndroid Build Coastguard Worker             closedir(d);
4025*38e8c45fSAndroid Build Coastguard Worker             return;
4026*38e8c45fSAndroid Build Coastguard Worker         }
4027*38e8c45fSAndroid Build Coastguard Worker         int pid;
4028*38e8c45fSAndroid Build Coastguard Worker         int fd;
4029*38e8c45fSAndroid Build Coastguard Worker         char cmdpath[255];
4030*38e8c45fSAndroid Build Coastguard Worker         char cmdline[255];
4031*38e8c45fSAndroid Build Coastguard Worker 
4032*38e8c45fSAndroid Build Coastguard Worker         if (!(pid = atoi(de->d_name))) {
4033*38e8c45fSAndroid Build Coastguard Worker             continue;
4034*38e8c45fSAndroid Build Coastguard Worker         }
4035*38e8c45fSAndroid Build Coastguard Worker 
4036*38e8c45fSAndroid Build Coastguard Worker         memset(cmdline, 0, sizeof(cmdline));
4037*38e8c45fSAndroid Build Coastguard Worker 
4038*38e8c45fSAndroid Build Coastguard Worker         snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4039*38e8c45fSAndroid Build Coastguard Worker         if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4040*38e8c45fSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4041*38e8c45fSAndroid Build Coastguard Worker             close(fd);
4042*38e8c45fSAndroid Build Coastguard Worker             if (cmdline[0]) {
4043*38e8c45fSAndroid Build Coastguard Worker                 helper(pid, cmdline, arg);
4044*38e8c45fSAndroid Build Coastguard Worker                 continue;
4045*38e8c45fSAndroid Build Coastguard Worker             }
4046*38e8c45fSAndroid Build Coastguard Worker         }
4047*38e8c45fSAndroid Build Coastguard Worker 
4048*38e8c45fSAndroid Build Coastguard Worker         // if no cmdline, a kernel thread has comm
4049*38e8c45fSAndroid Build Coastguard Worker         snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4050*38e8c45fSAndroid Build Coastguard Worker         if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4051*38e8c45fSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4052*38e8c45fSAndroid Build Coastguard Worker             close(fd);
4053*38e8c45fSAndroid Build Coastguard Worker             if (cmdline[1]) {
4054*38e8c45fSAndroid Build Coastguard Worker                 cmdline[0] = '[';
4055*38e8c45fSAndroid Build Coastguard Worker                 size_t len = strcspn(cmdline, "\f\b\r\n");
4056*38e8c45fSAndroid Build Coastguard Worker                 cmdline[len] = ']';
4057*38e8c45fSAndroid Build Coastguard Worker                 cmdline[len+1] = '\0';
4058*38e8c45fSAndroid Build Coastguard Worker             }
4059*38e8c45fSAndroid Build Coastguard Worker         }
4060*38e8c45fSAndroid Build Coastguard Worker         if (!cmdline[0]) {
4061*38e8c45fSAndroid Build Coastguard Worker             strcpy(cmdline, "N/A");
4062*38e8c45fSAndroid Build Coastguard Worker         }
4063*38e8c45fSAndroid Build Coastguard Worker         helper(pid, cmdline, arg);
4064*38e8c45fSAndroid Build Coastguard Worker     }
4065*38e8c45fSAndroid Build Coastguard Worker 
4066*38e8c45fSAndroid Build Coastguard Worker     closedir(d);
4067*38e8c45fSAndroid Build Coastguard Worker }
4068*38e8c45fSAndroid Build Coastguard Worker 
for_each_pid_helper(int pid,const char * cmdline,void * arg)4069*38e8c45fSAndroid Build Coastguard Worker static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4070*38e8c45fSAndroid Build Coastguard Worker     for_each_pid_func *func = (for_each_pid_func*) arg;
4071*38e8c45fSAndroid Build Coastguard Worker     func(pid, cmdline);
4072*38e8c45fSAndroid Build Coastguard Worker }
4073*38e8c45fSAndroid Build Coastguard Worker 
for_each_pid(for_each_pid_func func,const char * header)4074*38e8c45fSAndroid Build Coastguard Worker void for_each_pid(for_each_pid_func func, const char *header) {
4075*38e8c45fSAndroid Build Coastguard Worker     std::string title = header == nullptr ? "for_each_pid"
4076*38e8c45fSAndroid Build Coastguard Worker                                           : android::base::StringPrintf("for_each_pid(%s)", header);
4077*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
4078*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4079*38e8c45fSAndroid Build Coastguard Worker 
4080*38e8c45fSAndroid Build Coastguard Worker     __for_each_pid(for_each_pid_helper, header, (void *) func);
4081*38e8c45fSAndroid Build Coastguard Worker }
4082*38e8c45fSAndroid Build Coastguard Worker 
for_each_tid_helper(int pid,const char * cmdline,void * arg)4083*38e8c45fSAndroid Build Coastguard Worker static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4084*38e8c45fSAndroid Build Coastguard Worker     DIR *d;
4085*38e8c45fSAndroid Build Coastguard Worker     struct dirent *de;
4086*38e8c45fSAndroid Build Coastguard Worker     char taskpath[255];
4087*38e8c45fSAndroid Build Coastguard Worker     for_each_tid_func *func = (for_each_tid_func *) arg;
4088*38e8c45fSAndroid Build Coastguard Worker 
4089*38e8c45fSAndroid Build Coastguard Worker     snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4090*38e8c45fSAndroid Build Coastguard Worker 
4091*38e8c45fSAndroid Build Coastguard Worker     if (!(d = opendir(taskpath))) {
4092*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4093*38e8c45fSAndroid Build Coastguard Worker         return;
4094*38e8c45fSAndroid Build Coastguard Worker     }
4095*38e8c45fSAndroid Build Coastguard Worker 
4096*38e8c45fSAndroid Build Coastguard Worker     func(pid, pid, cmdline);
4097*38e8c45fSAndroid Build Coastguard Worker 
4098*38e8c45fSAndroid Build Coastguard Worker     while ((de = readdir(d))) {
4099*38e8c45fSAndroid Build Coastguard Worker         if (ds.IsUserConsentDenied()) {
4100*38e8c45fSAndroid Build Coastguard Worker             MYLOGE(
4101*38e8c45fSAndroid Build Coastguard Worker                 "Returning early because user denied consent to share bugreport with calling app.");
4102*38e8c45fSAndroid Build Coastguard Worker             closedir(d);
4103*38e8c45fSAndroid Build Coastguard Worker             return;
4104*38e8c45fSAndroid Build Coastguard Worker         }
4105*38e8c45fSAndroid Build Coastguard Worker         int tid;
4106*38e8c45fSAndroid Build Coastguard Worker         int fd;
4107*38e8c45fSAndroid Build Coastguard Worker         char commpath[255];
4108*38e8c45fSAndroid Build Coastguard Worker         char comm[255];
4109*38e8c45fSAndroid Build Coastguard Worker 
4110*38e8c45fSAndroid Build Coastguard Worker         if (!(tid = atoi(de->d_name))) {
4111*38e8c45fSAndroid Build Coastguard Worker             continue;
4112*38e8c45fSAndroid Build Coastguard Worker         }
4113*38e8c45fSAndroid Build Coastguard Worker 
4114*38e8c45fSAndroid Build Coastguard Worker         if (tid == pid)
4115*38e8c45fSAndroid Build Coastguard Worker             continue;
4116*38e8c45fSAndroid Build Coastguard Worker 
4117*38e8c45fSAndroid Build Coastguard Worker         snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4118*38e8c45fSAndroid Build Coastguard Worker         memset(comm, 0, sizeof(comm));
4119*38e8c45fSAndroid Build Coastguard Worker         if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4120*38e8c45fSAndroid Build Coastguard Worker             strcpy(comm, "N/A");
4121*38e8c45fSAndroid Build Coastguard Worker         } else {
4122*38e8c45fSAndroid Build Coastguard Worker             char *c;
4123*38e8c45fSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4124*38e8c45fSAndroid Build Coastguard Worker             close(fd);
4125*38e8c45fSAndroid Build Coastguard Worker 
4126*38e8c45fSAndroid Build Coastguard Worker             c = strrchr(comm, '\n');
4127*38e8c45fSAndroid Build Coastguard Worker             if (c) {
4128*38e8c45fSAndroid Build Coastguard Worker                 *c = '\0';
4129*38e8c45fSAndroid Build Coastguard Worker             }
4130*38e8c45fSAndroid Build Coastguard Worker         }
4131*38e8c45fSAndroid Build Coastguard Worker         func(pid, tid, comm);
4132*38e8c45fSAndroid Build Coastguard Worker     }
4133*38e8c45fSAndroid Build Coastguard Worker 
4134*38e8c45fSAndroid Build Coastguard Worker     closedir(d);
4135*38e8c45fSAndroid Build Coastguard Worker }
4136*38e8c45fSAndroid Build Coastguard Worker 
for_each_tid(for_each_tid_func func,const char * header)4137*38e8c45fSAndroid Build Coastguard Worker void for_each_tid(for_each_tid_func func, const char *header) {
4138*38e8c45fSAndroid Build Coastguard Worker     std::string title = header == nullptr ? "for_each_tid"
4139*38e8c45fSAndroid Build Coastguard Worker                                           : android::base::StringPrintf("for_each_tid(%s)", header);
4140*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
4141*38e8c45fSAndroid Build Coastguard Worker 
4142*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4143*38e8c45fSAndroid Build Coastguard Worker 
4144*38e8c45fSAndroid Build Coastguard Worker     __for_each_pid(for_each_tid_helper, header, (void *) func);
4145*38e8c45fSAndroid Build Coastguard Worker }
4146*38e8c45fSAndroid Build Coastguard Worker 
show_wchan(int pid,int tid,const char * name)4147*38e8c45fSAndroid Build Coastguard Worker void show_wchan(int pid, int tid, const char *name) {
4148*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4149*38e8c45fSAndroid Build Coastguard Worker 
4150*38e8c45fSAndroid Build Coastguard Worker     char path[255];
4151*38e8c45fSAndroid Build Coastguard Worker     char buffer[255];
4152*38e8c45fSAndroid Build Coastguard Worker     int fd, ret, save_errno;
4153*38e8c45fSAndroid Build Coastguard Worker     char name_buffer[255];
4154*38e8c45fSAndroid Build Coastguard Worker 
4155*38e8c45fSAndroid Build Coastguard Worker     memset(buffer, 0, sizeof(buffer));
4156*38e8c45fSAndroid Build Coastguard Worker 
4157*38e8c45fSAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4158*38e8c45fSAndroid Build Coastguard Worker     if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4159*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4160*38e8c45fSAndroid Build Coastguard Worker         return;
4161*38e8c45fSAndroid Build Coastguard Worker     }
4162*38e8c45fSAndroid Build Coastguard Worker 
4163*38e8c45fSAndroid Build Coastguard Worker     ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4164*38e8c45fSAndroid Build Coastguard Worker     save_errno = errno;
4165*38e8c45fSAndroid Build Coastguard Worker     close(fd);
4166*38e8c45fSAndroid Build Coastguard Worker 
4167*38e8c45fSAndroid Build Coastguard Worker     if (ret < 0) {
4168*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4169*38e8c45fSAndroid Build Coastguard Worker         return;
4170*38e8c45fSAndroid Build Coastguard Worker     }
4171*38e8c45fSAndroid Build Coastguard Worker 
4172*38e8c45fSAndroid Build Coastguard Worker     snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4173*38e8c45fSAndroid Build Coastguard Worker              pid == tid ? 0 : 3, "", name);
4174*38e8c45fSAndroid Build Coastguard Worker 
4175*38e8c45fSAndroid Build Coastguard Worker     printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4176*38e8c45fSAndroid Build Coastguard Worker 
4177*38e8c45fSAndroid Build Coastguard Worker     return;
4178*38e8c45fSAndroid Build Coastguard Worker }
4179*38e8c45fSAndroid Build Coastguard Worker 
4180*38e8c45fSAndroid Build Coastguard Worker // print time in centiseconds
snprcent(char * buffer,size_t len,size_t spc,unsigned long long time)4181*38e8c45fSAndroid Build Coastguard Worker static void snprcent(char *buffer, size_t len, size_t spc,
4182*38e8c45fSAndroid Build Coastguard Worker                      unsigned long long time) {
4183*38e8c45fSAndroid Build Coastguard Worker     static long hz; // cache discovered hz
4184*38e8c45fSAndroid Build Coastguard Worker 
4185*38e8c45fSAndroid Build Coastguard Worker     if (hz <= 0) {
4186*38e8c45fSAndroid Build Coastguard Worker         hz = sysconf(_SC_CLK_TCK);
4187*38e8c45fSAndroid Build Coastguard Worker         if (hz <= 0) {
4188*38e8c45fSAndroid Build Coastguard Worker             hz = 1000;
4189*38e8c45fSAndroid Build Coastguard Worker         }
4190*38e8c45fSAndroid Build Coastguard Worker     }
4191*38e8c45fSAndroid Build Coastguard Worker 
4192*38e8c45fSAndroid Build Coastguard Worker     // convert to centiseconds
4193*38e8c45fSAndroid Build Coastguard Worker     time = (time * 100 + (hz / 2)) / hz;
4194*38e8c45fSAndroid Build Coastguard Worker 
4195*38e8c45fSAndroid Build Coastguard Worker     char str[16];
4196*38e8c45fSAndroid Build Coastguard Worker 
4197*38e8c45fSAndroid Build Coastguard Worker     snprintf(str, sizeof(str), " %llu.%02u",
4198*38e8c45fSAndroid Build Coastguard Worker              time / 100, (unsigned)(time % 100));
4199*38e8c45fSAndroid Build Coastguard Worker     size_t offset = strlen(buffer);
4200*38e8c45fSAndroid Build Coastguard Worker     snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4201*38e8c45fSAndroid Build Coastguard Worker              "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4202*38e8c45fSAndroid Build Coastguard Worker }
4203*38e8c45fSAndroid Build Coastguard Worker 
4204*38e8c45fSAndroid Build Coastguard Worker // print permille as a percent
snprdec(char * buffer,size_t len,size_t spc,unsigned permille)4205*38e8c45fSAndroid Build Coastguard Worker static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4206*38e8c45fSAndroid Build Coastguard Worker     char str[16];
4207*38e8c45fSAndroid Build Coastguard Worker 
4208*38e8c45fSAndroid Build Coastguard Worker     snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4209*38e8c45fSAndroid Build Coastguard Worker     size_t offset = strlen(buffer);
4210*38e8c45fSAndroid Build Coastguard Worker     snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4211*38e8c45fSAndroid Build Coastguard Worker              "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4212*38e8c45fSAndroid Build Coastguard Worker }
4213*38e8c45fSAndroid Build Coastguard Worker 
show_showtime(int pid,const char * name)4214*38e8c45fSAndroid Build Coastguard Worker void show_showtime(int pid, const char *name) {
4215*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4216*38e8c45fSAndroid Build Coastguard Worker 
4217*38e8c45fSAndroid Build Coastguard Worker     char path[255];
4218*38e8c45fSAndroid Build Coastguard Worker     char buffer[1023];
4219*38e8c45fSAndroid Build Coastguard Worker     int fd, ret, save_errno;
4220*38e8c45fSAndroid Build Coastguard Worker 
4221*38e8c45fSAndroid Build Coastguard Worker     memset(buffer, 0, sizeof(buffer));
4222*38e8c45fSAndroid Build Coastguard Worker 
4223*38e8c45fSAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4224*38e8c45fSAndroid Build Coastguard Worker     if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4225*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4226*38e8c45fSAndroid Build Coastguard Worker         return;
4227*38e8c45fSAndroid Build Coastguard Worker     }
4228*38e8c45fSAndroid Build Coastguard Worker 
4229*38e8c45fSAndroid Build Coastguard Worker     ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4230*38e8c45fSAndroid Build Coastguard Worker     save_errno = errno;
4231*38e8c45fSAndroid Build Coastguard Worker     close(fd);
4232*38e8c45fSAndroid Build Coastguard Worker 
4233*38e8c45fSAndroid Build Coastguard Worker     if (ret < 0) {
4234*38e8c45fSAndroid Build Coastguard Worker         printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4235*38e8c45fSAndroid Build Coastguard Worker         return;
4236*38e8c45fSAndroid Build Coastguard Worker     }
4237*38e8c45fSAndroid Build Coastguard Worker 
4238*38e8c45fSAndroid Build Coastguard Worker     // field 14 is utime
4239*38e8c45fSAndroid Build Coastguard Worker     // field 15 is stime
4240*38e8c45fSAndroid Build Coastguard Worker     // field 42 is iotime
4241*38e8c45fSAndroid Build Coastguard Worker     unsigned long long utime = 0, stime = 0, iotime = 0;
4242*38e8c45fSAndroid Build Coastguard Worker     if (sscanf(buffer,
4243*38e8c45fSAndroid Build Coastguard Worker                "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4244*38e8c45fSAndroid Build Coastguard Worker                "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4245*38e8c45fSAndroid Build Coastguard Worker                "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4246*38e8c45fSAndroid Build Coastguard Worker                "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4247*38e8c45fSAndroid Build Coastguard Worker                &utime, &stime, &iotime) != 3) {
4248*38e8c45fSAndroid Build Coastguard Worker         return;
4249*38e8c45fSAndroid Build Coastguard Worker     }
4250*38e8c45fSAndroid Build Coastguard Worker 
4251*38e8c45fSAndroid Build Coastguard Worker     unsigned long long total = utime + stime;
4252*38e8c45fSAndroid Build Coastguard Worker     if (!total) {
4253*38e8c45fSAndroid Build Coastguard Worker         return;
4254*38e8c45fSAndroid Build Coastguard Worker     }
4255*38e8c45fSAndroid Build Coastguard Worker 
4256*38e8c45fSAndroid Build Coastguard Worker     unsigned permille = (iotime * 1000 + (total / 2)) / total;
4257*38e8c45fSAndroid Build Coastguard Worker     if (permille > 1000) {
4258*38e8c45fSAndroid Build Coastguard Worker         permille = 1000;
4259*38e8c45fSAndroid Build Coastguard Worker     }
4260*38e8c45fSAndroid Build Coastguard Worker 
4261*38e8c45fSAndroid Build Coastguard Worker     // try to beautify and stabilize columns at <80 characters
4262*38e8c45fSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4263*38e8c45fSAndroid Build Coastguard Worker     if ((name[0] != '[') || utime) {
4264*38e8c45fSAndroid Build Coastguard Worker         snprcent(buffer, sizeof(buffer), 57, utime);
4265*38e8c45fSAndroid Build Coastguard Worker     }
4266*38e8c45fSAndroid Build Coastguard Worker     snprcent(buffer, sizeof(buffer), 65, stime);
4267*38e8c45fSAndroid Build Coastguard Worker     if ((name[0] != '[') || iotime) {
4268*38e8c45fSAndroid Build Coastguard Worker         snprcent(buffer, sizeof(buffer), 73, iotime);
4269*38e8c45fSAndroid Build Coastguard Worker     }
4270*38e8c45fSAndroid Build Coastguard Worker     if (iotime) {
4271*38e8c45fSAndroid Build Coastguard Worker         snprdec(buffer, sizeof(buffer), 79, permille);
4272*38e8c45fSAndroid Build Coastguard Worker     }
4273*38e8c45fSAndroid Build Coastguard Worker     puts(buffer);  // adds a trailing newline
4274*38e8c45fSAndroid Build Coastguard Worker 
4275*38e8c45fSAndroid Build Coastguard Worker     return;
4276*38e8c45fSAndroid Build Coastguard Worker }
4277*38e8c45fSAndroid Build Coastguard Worker 
do_dmesg()4278*38e8c45fSAndroid Build Coastguard Worker void do_dmesg() {
4279*38e8c45fSAndroid Build Coastguard Worker     const char *title = "KERNEL LOG (dmesg)";
4280*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
4281*38e8c45fSAndroid Build Coastguard Worker     printf("------ %s ------\n", title);
4282*38e8c45fSAndroid Build Coastguard Worker 
4283*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4284*38e8c45fSAndroid Build Coastguard Worker 
4285*38e8c45fSAndroid Build Coastguard Worker     /* Get size of kernel buffer */
4286*38e8c45fSAndroid Build Coastguard Worker     int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4287*38e8c45fSAndroid Build Coastguard Worker     if (size <= 0) {
4288*38e8c45fSAndroid Build Coastguard Worker         printf("Unexpected klogctl return value: %d\n\n", size);
4289*38e8c45fSAndroid Build Coastguard Worker         return;
4290*38e8c45fSAndroid Build Coastguard Worker     }
4291*38e8c45fSAndroid Build Coastguard Worker     char *buf = (char *) malloc(size + 1);
4292*38e8c45fSAndroid Build Coastguard Worker     if (buf == nullptr) {
4293*38e8c45fSAndroid Build Coastguard Worker         printf("memory allocation failed\n\n");
4294*38e8c45fSAndroid Build Coastguard Worker         return;
4295*38e8c45fSAndroid Build Coastguard Worker     }
4296*38e8c45fSAndroid Build Coastguard Worker     int retval = klogctl(KLOG_READ_ALL, buf, size);
4297*38e8c45fSAndroid Build Coastguard Worker     if (retval < 0) {
4298*38e8c45fSAndroid Build Coastguard Worker         printf("klogctl failure\n\n");
4299*38e8c45fSAndroid Build Coastguard Worker         free(buf);
4300*38e8c45fSAndroid Build Coastguard Worker         return;
4301*38e8c45fSAndroid Build Coastguard Worker     }
4302*38e8c45fSAndroid Build Coastguard Worker     buf[retval] = '\0';
4303*38e8c45fSAndroid Build Coastguard Worker     printf("%s\n\n", buf);
4304*38e8c45fSAndroid Build Coastguard Worker     free(buf);
4305*38e8c45fSAndroid Build Coastguard Worker     return;
4306*38e8c45fSAndroid Build Coastguard Worker }
4307*38e8c45fSAndroid Build Coastguard Worker 
DumpFile(const std::string & title,const std::string & path)4308*38e8c45fSAndroid Build Coastguard Worker int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4309*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
4310*38e8c45fSAndroid Build Coastguard Worker 
4311*38e8c45fSAndroid Build Coastguard Worker     int status = DumpFileToFd(STDOUT_FILENO, title, path);
4312*38e8c45fSAndroid Build Coastguard Worker 
4313*38e8c45fSAndroid Build Coastguard Worker     UpdateProgress(WEIGHT_FILE);
4314*38e8c45fSAndroid Build Coastguard Worker 
4315*38e8c45fSAndroid Build Coastguard Worker     return status;
4316*38e8c45fSAndroid Build Coastguard Worker }
4317*38e8c45fSAndroid Build Coastguard Worker 
read_file_as_long(const char * path,long int * output)4318*38e8c45fSAndroid Build Coastguard Worker int read_file_as_long(const char *path, long int *output) {
4319*38e8c45fSAndroid Build Coastguard Worker     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4320*38e8c45fSAndroid Build Coastguard Worker     if (fd.get() < 0) {
4321*38e8c45fSAndroid Build Coastguard Worker         int err = errno;
4322*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4323*38e8c45fSAndroid Build Coastguard Worker         return -1;
4324*38e8c45fSAndroid Build Coastguard Worker     }
4325*38e8c45fSAndroid Build Coastguard Worker     char buffer[50];
4326*38e8c45fSAndroid Build Coastguard Worker     ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
4327*38e8c45fSAndroid Build Coastguard Worker     if (bytes_read == -1) {
4328*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4329*38e8c45fSAndroid Build Coastguard Worker         return -2;
4330*38e8c45fSAndroid Build Coastguard Worker     }
4331*38e8c45fSAndroid Build Coastguard Worker     if (bytes_read == 0) {
4332*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("File %s is empty\n", path);
4333*38e8c45fSAndroid Build Coastguard Worker         return -3;
4334*38e8c45fSAndroid Build Coastguard Worker     }
4335*38e8c45fSAndroid Build Coastguard Worker     *output = atoi(buffer);
4336*38e8c45fSAndroid Build Coastguard Worker     return 0;
4337*38e8c45fSAndroid Build Coastguard Worker }
4338*38e8c45fSAndroid Build Coastguard Worker 
4339*38e8c45fSAndroid Build Coastguard Worker /* calls skip to gate calling dump_from_fd recursively
4340*38e8c45fSAndroid Build Coastguard Worker  * in the specified directory. dump_from_fd defaults to
4341*38e8c45fSAndroid Build Coastguard Worker  * dump_file_from_fd above when set to NULL. skip defaults
4342*38e8c45fSAndroid Build Coastguard Worker  * to false when set to NULL. dump_from_fd will always be
4343*38e8c45fSAndroid Build Coastguard Worker  * called with title NULL.
4344*38e8c45fSAndroid Build Coastguard Worker  */
dump_files(const std::string & title,const char * dir,bool (* skip)(const char * path),int (* dump_from_fd)(const char * title,const char * path,int fd))4345*38e8c45fSAndroid Build Coastguard Worker int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4346*38e8c45fSAndroid Build Coastguard Worker                int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4347*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title);
4348*38e8c45fSAndroid Build Coastguard Worker     DIR *dirp;
4349*38e8c45fSAndroid Build Coastguard Worker     struct dirent *d;
4350*38e8c45fSAndroid Build Coastguard Worker     char *newpath = nullptr;
4351*38e8c45fSAndroid Build Coastguard Worker     const char *slash = "/";
4352*38e8c45fSAndroid Build Coastguard Worker     int retval = 0;
4353*38e8c45fSAndroid Build Coastguard Worker 
4354*38e8c45fSAndroid Build Coastguard Worker     if (!title.empty()) {
4355*38e8c45fSAndroid Build Coastguard Worker         printf("------ %s (%s) ------\n", title.c_str(), dir);
4356*38e8c45fSAndroid Build Coastguard Worker     }
4357*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return 0;
4358*38e8c45fSAndroid Build Coastguard Worker 
4359*38e8c45fSAndroid Build Coastguard Worker     if (dir[strlen(dir) - 1] == '/') {
4360*38e8c45fSAndroid Build Coastguard Worker         ++slash;
4361*38e8c45fSAndroid Build Coastguard Worker     }
4362*38e8c45fSAndroid Build Coastguard Worker     dirp = opendir(dir);
4363*38e8c45fSAndroid Build Coastguard Worker     if (dirp == nullptr) {
4364*38e8c45fSAndroid Build Coastguard Worker         retval = -errno;
4365*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("%s: %s\n", dir, strerror(errno));
4366*38e8c45fSAndroid Build Coastguard Worker         return retval;
4367*38e8c45fSAndroid Build Coastguard Worker     }
4368*38e8c45fSAndroid Build Coastguard Worker 
4369*38e8c45fSAndroid Build Coastguard Worker     if (!dump_from_fd) {
4370*38e8c45fSAndroid Build Coastguard Worker         dump_from_fd = dump_file_from_fd;
4371*38e8c45fSAndroid Build Coastguard Worker     }
4372*38e8c45fSAndroid Build Coastguard Worker     for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4373*38e8c45fSAndroid Build Coastguard Worker         if ((d->d_name[0] == '.')
4374*38e8c45fSAndroid Build Coastguard Worker          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4375*38e8c45fSAndroid Build Coastguard Worker           || (d->d_name[1] == '\0'))) {
4376*38e8c45fSAndroid Build Coastguard Worker             continue;
4377*38e8c45fSAndroid Build Coastguard Worker         }
4378*38e8c45fSAndroid Build Coastguard Worker         asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4379*38e8c45fSAndroid Build Coastguard Worker                  (d->d_type == DT_DIR) ? "/" : "");
4380*38e8c45fSAndroid Build Coastguard Worker         if (!newpath) {
4381*38e8c45fSAndroid Build Coastguard Worker             retval = -errno;
4382*38e8c45fSAndroid Build Coastguard Worker             continue;
4383*38e8c45fSAndroid Build Coastguard Worker         }
4384*38e8c45fSAndroid Build Coastguard Worker         if (skip && (*skip)(newpath)) {
4385*38e8c45fSAndroid Build Coastguard Worker             continue;
4386*38e8c45fSAndroid Build Coastguard Worker         }
4387*38e8c45fSAndroid Build Coastguard Worker         if (d->d_type == DT_DIR) {
4388*38e8c45fSAndroid Build Coastguard Worker             int ret = dump_files("", newpath, skip, dump_from_fd);
4389*38e8c45fSAndroid Build Coastguard Worker             if (ret < 0) {
4390*38e8c45fSAndroid Build Coastguard Worker                 retval = ret;
4391*38e8c45fSAndroid Build Coastguard Worker             }
4392*38e8c45fSAndroid Build Coastguard Worker             continue;
4393*38e8c45fSAndroid Build Coastguard Worker         }
4394*38e8c45fSAndroid Build Coastguard Worker         android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4395*38e8c45fSAndroid Build Coastguard Worker         if (fd.get() < 0) {
4396*38e8c45fSAndroid Build Coastguard Worker             retval = -1;
4397*38e8c45fSAndroid Build Coastguard Worker             printf("*** %s: %s\n", newpath, strerror(errno));
4398*38e8c45fSAndroid Build Coastguard Worker             continue;
4399*38e8c45fSAndroid Build Coastguard Worker         }
4400*38e8c45fSAndroid Build Coastguard Worker         (*dump_from_fd)(nullptr, newpath, fd.get());
4401*38e8c45fSAndroid Build Coastguard Worker     }
4402*38e8c45fSAndroid Build Coastguard Worker     closedir(dirp);
4403*38e8c45fSAndroid Build Coastguard Worker     if (!title.empty()) {
4404*38e8c45fSAndroid Build Coastguard Worker         printf("\n");
4405*38e8c45fSAndroid Build Coastguard Worker     }
4406*38e8c45fSAndroid Build Coastguard Worker     return retval;
4407*38e8c45fSAndroid Build Coastguard Worker }
4408*38e8c45fSAndroid Build Coastguard Worker 
4409*38e8c45fSAndroid Build Coastguard Worker /* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4410*38e8c45fSAndroid Build Coastguard Worker  * it's possible to avoid issues where opening the file itself can get
4411*38e8c45fSAndroid Build Coastguard Worker  * stuck.
4412*38e8c45fSAndroid Build Coastguard Worker  */
dump_file_from_fd(const char * title,const char * path,int fd)4413*38e8c45fSAndroid Build Coastguard Worker int dump_file_from_fd(const char *title, const char *path, int fd) {
4414*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return 0;
4415*38e8c45fSAndroid Build Coastguard Worker 
4416*38e8c45fSAndroid Build Coastguard Worker     int flags = fcntl(fd, F_GETFL);
4417*38e8c45fSAndroid Build Coastguard Worker     if (flags == -1) {
4418*38e8c45fSAndroid Build Coastguard Worker         printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4419*38e8c45fSAndroid Build Coastguard Worker         return -1;
4420*38e8c45fSAndroid Build Coastguard Worker     } else if (!(flags & O_NONBLOCK)) {
4421*38e8c45fSAndroid Build Coastguard Worker         printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4422*38e8c45fSAndroid Build Coastguard Worker         return -1;
4423*38e8c45fSAndroid Build Coastguard Worker     }
4424*38e8c45fSAndroid Build Coastguard Worker     return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4425*38e8c45fSAndroid Build Coastguard Worker }
4426*38e8c45fSAndroid Build Coastguard Worker 
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options,bool verbose_duration,int out_fd)4427*38e8c45fSAndroid Build Coastguard Worker int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
4428*38e8c45fSAndroid Build Coastguard Worker                           const CommandOptions& options, bool verbose_duration, int out_fd) {
4429*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter(title, false /* logcat_only */,
4430*38e8c45fSAndroid Build Coastguard Worker                                        verbose_duration, out_fd);
4431*38e8c45fSAndroid Build Coastguard Worker 
4432*38e8c45fSAndroid Build Coastguard Worker     int status = RunCommandToFd(out_fd, title, full_command, options);
4433*38e8c45fSAndroid Build Coastguard Worker 
4434*38e8c45fSAndroid Build Coastguard Worker     /* TODO: for now we're simplifying the progress calculation by using the
4435*38e8c45fSAndroid Build Coastguard Worker      * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4436*38e8c45fSAndroid Build Coastguard Worker      * where its weight should be much higher proportionally to its timeout.
4437*38e8c45fSAndroid Build Coastguard Worker      * Ideally, it should use a options.EstimatedDuration() instead...*/
4438*38e8c45fSAndroid Build Coastguard Worker     UpdateProgress(options.Timeout());
4439*38e8c45fSAndroid Build Coastguard Worker 
4440*38e8c45fSAndroid Build Coastguard Worker     return status;
4441*38e8c45fSAndroid Build Coastguard Worker }
4442*38e8c45fSAndroid Build Coastguard Worker 
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsys_args,const CommandOptions & options,long dumpsysTimeoutMs,int out_fd)4443*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
4444*38e8c45fSAndroid Build Coastguard Worker                            const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
4445*38e8c45fSAndroid Build Coastguard Worker     long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4446*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4447*38e8c45fSAndroid Build Coastguard Worker     dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
4448*38e8c45fSAndroid Build Coastguard Worker     RunCommand(title, dumpsys, options, false, out_fd);
4449*38e8c45fSAndroid Build Coastguard Worker }
4450*38e8c45fSAndroid Build Coastguard Worker 
open_socket(const char * service)4451*38e8c45fSAndroid Build Coastguard Worker static int open_socket(const char* service) {
4452*38e8c45fSAndroid Build Coastguard Worker     int s = android_get_control_socket(service);
4453*38e8c45fSAndroid Build Coastguard Worker     if (s < 0) {
4454*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4455*38e8c45fSAndroid Build Coastguard Worker         return -1;
4456*38e8c45fSAndroid Build Coastguard Worker     }
4457*38e8c45fSAndroid Build Coastguard Worker     fcntl(s, F_SETFD, FD_CLOEXEC);
4458*38e8c45fSAndroid Build Coastguard Worker 
4459*38e8c45fSAndroid Build Coastguard Worker     // Set backlog to 0 to make sure that queue size will be minimum.
4460*38e8c45fSAndroid Build Coastguard Worker     // In Linux, because the minimum queue will be 1, connect() will be blocked
4461*38e8c45fSAndroid Build Coastguard Worker     // if the other clients already called connect() and the connection request was not accepted.
4462*38e8c45fSAndroid Build Coastguard Worker     if (listen(s, 0) < 0) {
4463*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("listen(control socket): %s\n", strerror(errno));
4464*38e8c45fSAndroid Build Coastguard Worker         return -1;
4465*38e8c45fSAndroid Build Coastguard Worker     }
4466*38e8c45fSAndroid Build Coastguard Worker 
4467*38e8c45fSAndroid Build Coastguard Worker     struct sockaddr addr;
4468*38e8c45fSAndroid Build Coastguard Worker     socklen_t alen = sizeof(addr);
4469*38e8c45fSAndroid Build Coastguard Worker     int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
4470*38e8c45fSAndroid Build Coastguard Worker 
4471*38e8c45fSAndroid Build Coastguard Worker     // Close socket just after accept(), to make sure that connect() by client will get error
4472*38e8c45fSAndroid Build Coastguard Worker     // when the socket is used by the other services.
4473*38e8c45fSAndroid Build Coastguard Worker     // There is still a race condition possibility between accept and close, but there is no way
4474*38e8c45fSAndroid Build Coastguard Worker     // to close-on-accept atomically.
4475*38e8c45fSAndroid Build Coastguard Worker     // See detail; b/123306389#comment25
4476*38e8c45fSAndroid Build Coastguard Worker     close(s);
4477*38e8c45fSAndroid Build Coastguard Worker 
4478*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
4479*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("accept(control socket): %s\n", strerror(errno));
4480*38e8c45fSAndroid Build Coastguard Worker         return -1;
4481*38e8c45fSAndroid Build Coastguard Worker     }
4482*38e8c45fSAndroid Build Coastguard Worker 
4483*38e8c45fSAndroid Build Coastguard Worker     return fd;
4484*38e8c45fSAndroid Build Coastguard Worker }
4485*38e8c45fSAndroid Build Coastguard Worker 
4486*38e8c45fSAndroid Build Coastguard Worker // TODO: should call is_valid_output_file and/or be merged into it.
create_parent_dirs(const char * path)4487*38e8c45fSAndroid Build Coastguard Worker void create_parent_dirs(const char *path) {
4488*38e8c45fSAndroid Build Coastguard Worker     char *chp = const_cast<char *> (path);
4489*38e8c45fSAndroid Build Coastguard Worker 
4490*38e8c45fSAndroid Build Coastguard Worker     /* skip initial slash */
4491*38e8c45fSAndroid Build Coastguard Worker     if (chp[0] == '/')
4492*38e8c45fSAndroid Build Coastguard Worker         chp++;
4493*38e8c45fSAndroid Build Coastguard Worker 
4494*38e8c45fSAndroid Build Coastguard Worker     /* create leading directories, if necessary */
4495*38e8c45fSAndroid Build Coastguard Worker     struct stat dir_stat;
4496*38e8c45fSAndroid Build Coastguard Worker     while (chp && chp[0]) {
4497*38e8c45fSAndroid Build Coastguard Worker         chp = strchr(chp, '/');
4498*38e8c45fSAndroid Build Coastguard Worker         if (chp) {
4499*38e8c45fSAndroid Build Coastguard Worker             *chp = 0;
4500*38e8c45fSAndroid Build Coastguard Worker             if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4501*38e8c45fSAndroid Build Coastguard Worker                 MYLOGI("Creating directory %s\n", path);
4502*38e8c45fSAndroid Build Coastguard Worker                 if (mkdir(path, 0770)) { /* drwxrwx--- */
4503*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4504*38e8c45fSAndroid Build Coastguard Worker                 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4505*38e8c45fSAndroid Build Coastguard Worker                     MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4506*38e8c45fSAndroid Build Coastguard Worker                 }
4507*38e8c45fSAndroid Build Coastguard Worker             }
4508*38e8c45fSAndroid Build Coastguard Worker             *chp++ = '/';
4509*38e8c45fSAndroid Build Coastguard Worker         }
4510*38e8c45fSAndroid Build Coastguard Worker     }
4511*38e8c45fSAndroid Build Coastguard Worker }
4512*38e8c45fSAndroid Build Coastguard Worker 
_redirect_to_file(FILE * redirect,char * path,int truncate_flag)4513*38e8c45fSAndroid Build Coastguard Worker bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4514*38e8c45fSAndroid Build Coastguard Worker     create_parent_dirs(path);
4515*38e8c45fSAndroid Build Coastguard Worker 
4516*38e8c45fSAndroid Build Coastguard Worker     int fd = TEMP_FAILURE_RETRY(open(path,
4517*38e8c45fSAndroid Build Coastguard Worker                                      O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4518*38e8c45fSAndroid Build Coastguard Worker                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4519*38e8c45fSAndroid Build Coastguard Worker     if (fd < 0) {
4520*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("%s: %s\n", path, strerror(errno));
4521*38e8c45fSAndroid Build Coastguard Worker         return false;
4522*38e8c45fSAndroid Build Coastguard Worker     }
4523*38e8c45fSAndroid Build Coastguard Worker 
4524*38e8c45fSAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4525*38e8c45fSAndroid Build Coastguard Worker     close(fd);
4526*38e8c45fSAndroid Build Coastguard Worker     return true;
4527*38e8c45fSAndroid Build Coastguard Worker }
4528*38e8c45fSAndroid Build Coastguard Worker 
redirect_to_file(FILE * redirect,char * path)4529*38e8c45fSAndroid Build Coastguard Worker bool redirect_to_file(FILE* redirect, char* path) {
4530*38e8c45fSAndroid Build Coastguard Worker     return _redirect_to_file(redirect, path, O_TRUNC);
4531*38e8c45fSAndroid Build Coastguard Worker }
4532*38e8c45fSAndroid Build Coastguard Worker 
redirect_to_existing_file(FILE * redirect,char * path)4533*38e8c45fSAndroid Build Coastguard Worker bool redirect_to_existing_file(FILE* redirect, char* path) {
4534*38e8c45fSAndroid Build Coastguard Worker     return _redirect_to_file(redirect, path, O_APPEND);
4535*38e8c45fSAndroid Build Coastguard Worker }
4536*38e8c45fSAndroid Build Coastguard Worker 
dump_route_tables()4537*38e8c45fSAndroid Build Coastguard Worker void dump_route_tables() {
4538*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("DUMP ROUTE TABLES");
4539*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4540*38e8c45fSAndroid Build Coastguard Worker     const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4541*38e8c45fSAndroid Build Coastguard Worker     ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4542*38e8c45fSAndroid Build Coastguard Worker     FILE* fp = fopen(RT_TABLES_PATH, "re");
4543*38e8c45fSAndroid Build Coastguard Worker     if (!fp) {
4544*38e8c45fSAndroid Build Coastguard Worker         printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4545*38e8c45fSAndroid Build Coastguard Worker         return;
4546*38e8c45fSAndroid Build Coastguard Worker     }
4547*38e8c45fSAndroid Build Coastguard Worker     char table[16];
4548*38e8c45fSAndroid Build Coastguard Worker     // Each line has an integer (the table number), a space, and a string (the table name). We only
4549*38e8c45fSAndroid Build Coastguard Worker     // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4550*38e8c45fSAndroid Build Coastguard Worker     // Add a fixed max limit so this doesn't go awry.
4551*38e8c45fSAndroid Build Coastguard Worker     for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4552*38e8c45fSAndroid Build Coastguard Worker         RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4553*38e8c45fSAndroid Build Coastguard Worker         RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4554*38e8c45fSAndroid Build Coastguard Worker     }
4555*38e8c45fSAndroid Build Coastguard Worker     fclose(fp);
4556*38e8c45fSAndroid Build Coastguard Worker }
4557*38e8c45fSAndroid Build Coastguard Worker 
dump_frozen_cgroupfs(const char * dir,int level,int (* dump_from_fd)(const char * title,const char * path,int fd))4558*38e8c45fSAndroid Build Coastguard Worker void dump_frozen_cgroupfs(const char *dir, int level,
4559*38e8c45fSAndroid Build Coastguard Worker         int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4560*38e8c45fSAndroid Build Coastguard Worker     DIR *dirp;
4561*38e8c45fSAndroid Build Coastguard Worker     struct dirent *d;
4562*38e8c45fSAndroid Build Coastguard Worker     char *newpath = nullptr;
4563*38e8c45fSAndroid Build Coastguard Worker 
4564*38e8c45fSAndroid Build Coastguard Worker     dirp = opendir(dir);
4565*38e8c45fSAndroid Build Coastguard Worker     if (dirp == nullptr) {
4566*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("%s: %s\n", dir, strerror(errno));
4567*38e8c45fSAndroid Build Coastguard Worker         return;
4568*38e8c45fSAndroid Build Coastguard Worker     }
4569*38e8c45fSAndroid Build Coastguard Worker 
4570*38e8c45fSAndroid Build Coastguard Worker     for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4571*38e8c45fSAndroid Build Coastguard Worker         if ((d->d_name[0] == '.')
4572*38e8c45fSAndroid Build Coastguard Worker          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4573*38e8c45fSAndroid Build Coastguard Worker           || (d->d_name[1] == '\0'))) {
4574*38e8c45fSAndroid Build Coastguard Worker             continue;
4575*38e8c45fSAndroid Build Coastguard Worker         }
4576*38e8c45fSAndroid Build Coastguard Worker         if (d->d_type == DT_DIR) {
4577*38e8c45fSAndroid Build Coastguard Worker             asprintf(&newpath, "%s/%s/", dir, d->d_name);
4578*38e8c45fSAndroid Build Coastguard Worker             if (!newpath) {
4579*38e8c45fSAndroid Build Coastguard Worker                 continue;
4580*38e8c45fSAndroid Build Coastguard Worker             }
4581*38e8c45fSAndroid Build Coastguard Worker             if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4582*38e8c45fSAndroid Build Coastguard Worker                 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4583*38e8c45fSAndroid Build Coastguard Worker             } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4584*38e8c45fSAndroid Build Coastguard Worker                 char *freezer = nullptr;
4585*38e8c45fSAndroid Build Coastguard Worker                 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4586*38e8c45fSAndroid Build Coastguard Worker                 if (freezer) {
4587*38e8c45fSAndroid Build Coastguard Worker                     FILE* fp = fopen(freezer, "r");
4588*38e8c45fSAndroid Build Coastguard Worker                     if (fp != NULL) {
4589*38e8c45fSAndroid Build Coastguard Worker                         int frozen;
4590*38e8c45fSAndroid Build Coastguard Worker                         fscanf(fp, "%d", &frozen);
4591*38e8c45fSAndroid Build Coastguard Worker                         if (frozen > 0) {
4592*38e8c45fSAndroid Build Coastguard Worker                             dump_files("", newpath, skip_none, dump_from_fd);
4593*38e8c45fSAndroid Build Coastguard Worker                         }
4594*38e8c45fSAndroid Build Coastguard Worker                         fclose(fp);
4595*38e8c45fSAndroid Build Coastguard Worker                     }
4596*38e8c45fSAndroid Build Coastguard Worker                     free(freezer);
4597*38e8c45fSAndroid Build Coastguard Worker                 }
4598*38e8c45fSAndroid Build Coastguard Worker             }
4599*38e8c45fSAndroid Build Coastguard Worker         }
4600*38e8c45fSAndroid Build Coastguard Worker     }
4601*38e8c45fSAndroid Build Coastguard Worker     closedir(dirp);
4602*38e8c45fSAndroid Build Coastguard Worker }
4603*38e8c45fSAndroid Build Coastguard Worker 
dump_frozen_cgroupfs()4604*38e8c45fSAndroid Build Coastguard Worker void dump_frozen_cgroupfs() {
4605*38e8c45fSAndroid Build Coastguard Worker     MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4606*38e8c45fSAndroid Build Coastguard Worker     DurationReporter duration_reporter("FROZEN CGROUPFS");
4607*38e8c45fSAndroid Build Coastguard Worker     if (PropertiesHelper::IsDryRun()) return;
4608*38e8c45fSAndroid Build Coastguard Worker     dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4609*38e8c45fSAndroid Build Coastguard Worker }
4610*38e8c45fSAndroid Build Coastguard Worker 
UpdateProgress(int32_t delta_sec)4611*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::UpdateProgress(int32_t delta_sec) {
4612*38e8c45fSAndroid Build Coastguard Worker     if (progress_ == nullptr) {
4613*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("UpdateProgress: progress_ not set\n");
4614*38e8c45fSAndroid Build Coastguard Worker         return;
4615*38e8c45fSAndroid Build Coastguard Worker     }
4616*38e8c45fSAndroid Build Coastguard Worker     // This function updates progress related members of the dumpstate and reports
4617*38e8c45fSAndroid Build Coastguard Worker     // progress percentage to the bugreport client. Since it could be called by
4618*38e8c45fSAndroid Build Coastguard Worker     // different dump tasks at the same time if the parallel run is enabled, a
4619*38e8c45fSAndroid Build Coastguard Worker     // mutex lock is necessary here to synchronize the call.
4620*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::recursive_mutex> lock(mutex_);
4621*38e8c45fSAndroid Build Coastguard Worker 
4622*38e8c45fSAndroid Build Coastguard Worker     // Always update progess so stats can be tuned...
4623*38e8c45fSAndroid Build Coastguard Worker     progress_->Inc(delta_sec);
4624*38e8c45fSAndroid Build Coastguard Worker 
4625*38e8c45fSAndroid Build Coastguard Worker     // ...but only notifiy listeners when necessary.
4626*38e8c45fSAndroid Build Coastguard Worker     if (!options_->do_progress_updates) return;
4627*38e8c45fSAndroid Build Coastguard Worker 
4628*38e8c45fSAndroid Build Coastguard Worker     int progress = progress_->Get();
4629*38e8c45fSAndroid Build Coastguard Worker     int max = progress_->GetMax();
4630*38e8c45fSAndroid Build Coastguard Worker     int percent = 100 * progress / max;
4631*38e8c45fSAndroid Build Coastguard Worker 
4632*38e8c45fSAndroid Build Coastguard Worker     if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
4633*38e8c45fSAndroid Build Coastguard Worker         return;
4634*38e8c45fSAndroid Build Coastguard Worker     }
4635*38e8c45fSAndroid Build Coastguard Worker     last_reported_percent_progress_ = percent;
4636*38e8c45fSAndroid Build Coastguard Worker 
4637*38e8c45fSAndroid Build Coastguard Worker     if (control_socket_fd_ >= 0) {
4638*38e8c45fSAndroid Build Coastguard Worker         dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4639*38e8c45fSAndroid Build Coastguard Worker         fsync(control_socket_fd_);
4640*38e8c45fSAndroid Build Coastguard Worker     }
4641*38e8c45fSAndroid Build Coastguard Worker 
4642*38e8c45fSAndroid Build Coastguard Worker     if (listener_ != nullptr) {
4643*38e8c45fSAndroid Build Coastguard Worker         if (percent % 10 == 0) {
4644*38e8c45fSAndroid Build Coastguard Worker             // We don't want to spam logcat, so only log multiples of 10.
4645*38e8c45fSAndroid Build Coastguard Worker             MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
4646*38e8c45fSAndroid Build Coastguard Worker         } else {
4647*38e8c45fSAndroid Build Coastguard Worker             // stderr is ignored on normal invocations, but useful when calling
4648*38e8c45fSAndroid Build Coastguard Worker             // /system/bin/dumpstate directly for debuggging.
4649*38e8c45fSAndroid Build Coastguard Worker             fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
4650*38e8c45fSAndroid Build Coastguard Worker         }
4651*38e8c45fSAndroid Build Coastguard Worker 
4652*38e8c45fSAndroid Build Coastguard Worker         listener_->onProgress(percent);
4653*38e8c45fSAndroid Build Coastguard Worker     }
4654*38e8c45fSAndroid Build Coastguard Worker }
4655*38e8c45fSAndroid Build Coastguard Worker 
TakeScreenshot(const std::string & path)4656*38e8c45fSAndroid Build Coastguard Worker void Dumpstate::TakeScreenshot(const std::string& path) {
4657*38e8c45fSAndroid Build Coastguard Worker     const std::string& real_path = path.empty() ? screenshot_path_ : path;
4658*38e8c45fSAndroid Build Coastguard Worker     int status =
4659*38e8c45fSAndroid Build Coastguard Worker         RunCommand("", {"screencap", "-p", real_path},
4660*38e8c45fSAndroid Build Coastguard Worker                    CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4661*38e8c45fSAndroid Build Coastguard Worker     if (status == 0) {
4662*38e8c45fSAndroid Build Coastguard Worker         MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4663*38e8c45fSAndroid Build Coastguard Worker     } else {
4664*38e8c45fSAndroid Build Coastguard Worker         MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4665*38e8c45fSAndroid Build Coastguard Worker     }
4666*38e8c45fSAndroid Build Coastguard Worker     if (listener_ != nullptr) {
4667*38e8c45fSAndroid Build Coastguard Worker         // Show a visual indication to indicate screenshot is taken via
4668*38e8c45fSAndroid Build Coastguard Worker         // IDumpstateListener.onScreenshotTaken()
4669*38e8c45fSAndroid Build Coastguard Worker         listener_->onScreenshotTaken(status == 0);
4670*38e8c45fSAndroid Build Coastguard Worker     }
4671*38e8c45fSAndroid Build Coastguard Worker }
4672*38e8c45fSAndroid Build Coastguard Worker 
is_dir(const char * pathname)4673*38e8c45fSAndroid Build Coastguard Worker bool is_dir(const char* pathname) {
4674*38e8c45fSAndroid Build Coastguard Worker     struct stat info;
4675*38e8c45fSAndroid Build Coastguard Worker     if (stat(pathname, &info) == -1) {
4676*38e8c45fSAndroid Build Coastguard Worker         return false;
4677*38e8c45fSAndroid Build Coastguard Worker     }
4678*38e8c45fSAndroid Build Coastguard Worker     return S_ISDIR(info.st_mode);
4679*38e8c45fSAndroid Build Coastguard Worker }
4680*38e8c45fSAndroid Build Coastguard Worker 
get_mtime(int fd,time_t default_mtime)4681*38e8c45fSAndroid Build Coastguard Worker time_t get_mtime(int fd, time_t default_mtime) {
4682*38e8c45fSAndroid Build Coastguard Worker     struct stat info;
4683*38e8c45fSAndroid Build Coastguard Worker     if (fstat(fd, &info) == -1) {
4684*38e8c45fSAndroid Build Coastguard Worker         return default_mtime;
4685*38e8c45fSAndroid Build Coastguard Worker     }
4686*38e8c45fSAndroid Build Coastguard Worker     return info.st_mtime;
4687*38e8c45fSAndroid Build Coastguard Worker }
4688