1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_
18 #define FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_
19 
20 #include <time.h>
21 #include <unistd.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 
25 #include <string>
26 #include <vector>
27 
28 #include <android-base/macros.h>
29 #include <android-base/unique_fd.h>
30 #include <android/hardware/dumpstate/1.1/types.h>
31 #include <android/os/BnIncidentAuthListener.h>
32 #include <android/os/IDumpstate.h>
33 #include <android/os/IDumpstateListener.h>
34 #include <utils/StrongPointer.h>
35 #include <ziparchive/zip_writer.h>
36 
37 #include "DumpstateUtil.h"
38 
39 // Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
40 // std::vector<std::string>
41 // TODO: remove once not used
42 #define MAX_ARGS_ARRAY_SIZE 1000
43 
44 // TODO: move everything under this namespace
45 // TODO: and then remove explicitly android::os::dumpstate:: prefixes
46 namespace android {
47 namespace os {
48 
49 struct DumpstateOptions;
50 
51 namespace dumpstate {
52 
53 class DumpstateTest;
54 class ProgressTest;
55 
56 }  // namespace dumpstate
57 }  // namespace os
58 }  // namespace android
59 
60 class ZipWriter;
61 
62 // TODO: remove once moved to HAL
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66 
67 /*
68  * Helper class used to report how long it takes for a section to finish.
69  *
70  * Typical usage:
71  *
72  *    DurationReporter duration_reporter(title);
73  *
74  */
75 class DurationReporter {
76   public:
77     explicit DurationReporter(const std::string& title, bool logcat_only = false,
78                               bool verbose = false);
79 
80     ~DurationReporter();
81 
82   private:
83     std::string title_;
84     bool logcat_only_;
85     bool verbose_;
86     uint64_t started_;
87 
88     DISALLOW_COPY_AND_ASSIGN(DurationReporter);
89 };
90 
91 /*
92  * Keeps track of current progress and estimated max, saving stats on file to tune up future runs.
93  *
94  * Each `dumpstate` section contributes to the total weight by an individual weight, so the overall
95  * progress can be calculated by dividing the estimate max progress by the current progress.
96  *
97  * The estimated max progress is initially set to a value (`kDefaultMax) defined empirically, but
98  * it's adjusted after each dumpstate run by storing the average duration in a file.
99  *
100  */
101 class Progress {
102     friend class android::os::dumpstate::ProgressTest;
103     friend class android::os::dumpstate::DumpstateTest;
104 
105   public:
106     /*
107      * Default estimation of the max duration of a bugreport generation.
108      *
109      * It does not need to match the exact sum of all sections, but ideally it should to be slight
110      * more than such sum: a value too high will cause the bugreport to finish before the user
111      * expected (for example, jumping from 70% to 100%), while a value too low will cause the
112      * progress to get stuck at an almost-finished value (like 99%) for a while.
113      *
114      * This constant is only used when the average duration from previous runs cannot be used.
115      */
116     static const int kDefaultMax;
117 
118     explicit Progress(const std::string& path = "");
119 
120     // Gets the current progress.
121     int32_t Get() const;
122 
123     // Gets the current estimated max progress.
124     int32_t GetMax() const;
125 
126     // Gets the initial estimated max progress.
127     int32_t GetInitialMax() const;
128 
129     // Increments progress (ignored if not positive).
130     // Returns `true` if the max progress increased as well.
131     bool Inc(int32_t delta);
132 
133     // Persist the stats.
134     void Save();
135 
136     void Dump(int fd, const std::string& prefix) const;
137 
138   private:
139     Progress(int32_t initial_max, float growth_factor,
140              const std::string& path = "");                                // Used by test cases.
141     Progress(int32_t initial_max, int32_t progress, float growth_factor);  // Used by test cases.
142     void Load();
143     int32_t initial_max_;
144     int32_t progress_;
145     int32_t max_;
146     float growth_factor_;
147     int32_t n_runs_;
148     int32_t average_max_;
149     std::string path_;
150 };
151 
152 /*
153  * List of supported zip format versions.
154  *
155  * See bugreport-format.md for more info.
156  */
157 static std::string VERSION_CURRENT = "2.0";
158 
159 /*
160  * Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version
161  * will be bumped to 3.0.
162  */
163 static std::string VERSION_SPLIT_ANR = "3.0-dev-split-anr";
164 
165 /*
166  * "Alias" for the current version.
167  */
168 static std::string VERSION_DEFAULT = "default";
169 
170 /*
171  * Directory used by Dumpstate binary to keep its local files.
172  */
173 static const std::string DUMPSTATE_DIRECTORY = "/bugreports";
174 
175 /*
176  * Structure that contains the information of an open dump file.
177  */
178 struct DumpData {
179     // Path of the file.
180     std::string name;
181 
182     // Open file descriptor for the file.
183     android::base::unique_fd fd;
184 
185     // Modification time of the file.
186     time_t mtime;
187 };
188 
189 /*
190  * Main class driving a bugreport generation.
191  *
192  * Currently, it only contains variables that are accessed externally, but gradually the functions
193  * that are spread accross utils.cpp and dumpstate.cpp will be moved to it.
194  */
195 class Dumpstate {
196     friend class DumpstateTest;
197 
198   public:
199     enum RunStatus { OK, HELP, INVALID_INPUT, ERROR, USER_CONSENT_DENIED, USER_CONSENT_TIMED_OUT };
200 
201     // The mode under which the bugreport should be run. Each mode encapsulates a few options.
202     enum BugreportMode {
203         BUGREPORT_FULL = android::os::IDumpstate::BUGREPORT_MODE_FULL,
204         BUGREPORT_INTERACTIVE = android::os::IDumpstate::BUGREPORT_MODE_INTERACTIVE,
205         BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE,
206         BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR,
207         BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY,
208         BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI,
209         BUGREPORT_DEFAULT = android::os::IDumpstate::BUGREPORT_MODE_DEFAULT
210     };
211 
212     static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
213 
214     static Dumpstate& GetInstance();
215 
216     /* Checkes whether dumpstate is generating a zipped bugreport. */
217     bool IsZipping() const;
218 
219     /* Initialize dumpstate fields before starting bugreport generation */
220     void Initialize();
221 
222     /*
223      * Forks a command, waits for it to finish, and returns its status.
224      *
225      * |title| description of the command printed on `stdout` (or empty to skip
226      * description).
227      * |full_command| array containing the command (first entry) and its arguments.
228      * Must contain at least one element.
229      * |options| optional argument defining the command's behavior.
230      */
231     int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
232                    const android::os::dumpstate::CommandOptions& options =
233                        android::os::dumpstate::CommandOptions::DEFAULT,
234                    bool verbose_duration = false);
235 
236     /*
237      * Runs `dumpsys` with the given arguments, automatically setting its timeout
238      * (`-T` argument)
239      * according to the command options.
240      *
241      * |title| description of the command printed on `stdout` (or empty to skip
242      * description).
243      * |dumpsys_args| `dumpsys` arguments (except `-t`).
244      * |options| optional argument defining the command's behavior.
245      * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -T` (otherwise it uses the
246      * timeout from `options`)
247      */
248     void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
249                     const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS,
250                     long dumpsys_timeout_ms = 0);
251 
252     /*
253      * Prints the contents of a file.
254      *
255      * |title| description of the command printed on `stdout` (or empty to skip
256      * description).
257      * |path| location of the file to be dumped.
258      */
259     int DumpFile(const std::string& title, const std::string& path);
260 
261     /*
262      * Adds a new entry to the existing zip file.
263      * */
264     bool AddZipEntry(const std::string& entry_name, const std::string& entry_path);
265 
266     /*
267      * Adds a new entry to the existing zip file.
268      *
269      * |entry_name| destination path of the new entry.
270      * |fd| file descriptor to read from.
271      * |timeout| timeout to terminate the read if not completed. Set
272      * value of 0s (default) to disable timeout.
273      */
274     android::status_t AddZipEntryFromFd(const std::string& entry_name, int fd,
275                                         std::chrono::milliseconds timeout);
276 
277     /*
278      * Adds a text entry to the existing zip file.
279      */
280     bool AddTextZipEntry(const std::string& entry_name, const std::string& content);
281 
282     /*
283      * Adds all files from a directory to the zipped bugreport file.
284      */
285     void AddDir(const std::string& dir, bool recursive);
286 
287     /*
288      * Takes a screenshot and save it to the given `path`.
289      *
290      * If `path` is empty, uses a standard path based on the bugreport name.
291      */
292     void TakeScreenshot(const std::string& path = "");
293 
294     /////////////////////////////////////////////////////////////////////
295     // TODO: members below should be private once refactor is finished //
296     /////////////////////////////////////////////////////////////////////
297 
298     // TODO: temporary method until Dumpstate object is properly set
299     void SetProgress(std::unique_ptr<Progress> progress);
300 
301     // Dumps Dalvik and native stack traces, sets the trace file location to path
302     // if it succeeded.
303     // Note that it returns early if user consent is denied with status USER_CONSENT_DENIED.
304     // Returns OK in all other cases.
305     RunStatus DumpTraces(const char** path);
306 
307     void DumpstateBoard();
308 
309     /*
310      * Updates the overall progress of the bugreport generation by the given weight increment.
311      */
312     void UpdateProgress(int32_t delta);
313 
314     /* Prints the dumpstate header on `stdout`. */
315     void PrintHeader() const;
316 
317     /*
318      * Adds the temporary report to the existing .zip file, closes the .zip file, and removes the
319      * temporary file.
320      */
321     bool FinishZipFile();
322 
323     /* Constructs a full path inside directory with file name formatted using the given suffix. */
324     std::string GetPath(const std::string& directory, const std::string& suffix) const;
325 
326     /* Constructs a full path inside bugreport_internal_dir_ with file name formatted using the
327      * given suffix. */
328     std::string GetPath(const std::string& suffix) const;
329 
330     /* Returns true if the current version supports priority dump feature. */
331     bool CurrentVersionSupportsPriorityDumps() const;
332 
333     struct DumpOptions;
334 
335     /*
336      * Main entry point for running a complete bugreport.
337      *
338      * Initialize() dumpstate before calling this method.
339      *
340      */
341     RunStatus Run(int32_t calling_uid, const std::string& calling_package);
342 
343     RunStatus ParseCommandlineAndRun(int argc, char* argv[]);
344 
345     /* Deletes in-progress files */
346     void Cancel();
347 
348     /* Sets runtime options. */
349     void SetOptions(std::unique_ptr<DumpOptions> options);
350 
351     /*
352      * Returns true if user consent is necessary and has been denied.
353      * Consent is only necessary if the caller has asked to copy over the bugreport to a file they
354      * provided.
355      */
356     bool IsUserConsentDenied() const;
357 
358     /*
359      * Returns true if dumpstate is called by bugreporting API
360      */
361     bool CalledByApi() const;
362 
363     /*
364      * Structure to hold options that determine the behavior of dumpstate.
365      */
366     struct DumpOptions {
367         bool do_add_date = false;
368         bool do_zip_file = false;
369         bool do_vibrate = true;
370         // Writes bugreport content to a socket; only flatfile format is supported.
371         bool use_socket = false;
372         bool use_control_socket = false;
373         bool do_screenshot = false;
374         bool is_screenshot_copied = false;
375         bool is_remote_mode = false;
376         bool show_header_only = false;
377         bool do_start_service = false;
378         bool telephony_only = false;
379         bool wifi_only = false;
380         // Trimmed-down version of dumpstate to only include whitelisted logs.
381         bool limited_only = false;
382         // Whether progress updates should be published.
383         bool do_progress_updates = false;
384         // The mode we'll use when calling IDumpstateDevice::dumpstateBoard.
385         // TODO(b/148168577) get rid of the AIDL values, replace them with the HAL values instead.
386         // The HAL is actually an API surface that can be validated, while the AIDL is not (@hide).
387         ::android::hardware::dumpstate::V1_1::DumpstateMode dumpstate_hal_mode =
388             ::android::hardware::dumpstate::V1_1::DumpstateMode::DEFAULT;
389         // File descriptor to output zip file. Takes precedence over out_dir.
390         android::base::unique_fd bugreport_fd;
391         // File descriptor to screenshot file.
392         android::base::unique_fd screenshot_fd;
393         // Custom output directory.
394         std::string out_dir;
395         // Bugreport mode of the bugreport.
396         std::string bugreport_mode;
397         // Command-line arguments as string
398         std::string args;
399         // Notification title and description
400         std::string notification_title;
401         std::string notification_description;
402 
403         /* Initializes options from commandline arguments. */
404         RunStatus Initialize(int argc, char* argv[]);
405 
406         /* Initializes options from the requested mode. */
407         void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
408                         const android::base::unique_fd& screenshot_fd,
409                         bool is_screenshot_requested);
410 
411         /* Returns true if the options set so far are consistent. */
412         bool ValidateOptions() const;
413 
414         /* Returns if options specified require writing bugreport to a file */
OutputToFileDumpOptions415         bool OutputToFile() const {
416             // If we are not writing to socket, we will write to a file. If bugreport_fd is
417             // specified, it is preferred. If not bugreport is written to /bugreports.
418             return !use_socket;
419         }
420 
421         /* Returns if options specified require writing to custom file location */
OutputToCustomFileDumpOptions422         bool OutputToCustomFile() {
423             // Custom location is only honored in limited mode.
424             return limited_only && !out_dir.empty() && bugreport_fd.get() == -1;
425         }
426     };
427 
428     // TODO: initialize fields on constructor
429     // dumpstate id - unique after each device reboot.
430     uint32_t id_;
431 
432     // dumpstate pid
433     pid_t pid_;
434 
435     // Runtime options.
436     std::unique_ptr<DumpOptions> options_;
437 
438     // Last progress that was sent to the listener [0-100].
439     int last_reported_percent_progress_ = 0;
440 
441     // Whether it should take an screenshot earlier in the process.
442     bool do_early_screenshot_ = false;
443 
444     std::unique_ptr<Progress> progress_;
445 
446     // When set, defines a socket file-descriptor use to report progress to bugreportz.
447     int control_socket_fd_ = -1;
448 
449     // Bugreport format version;
450     std::string version_ = VERSION_CURRENT;
451 
452     time_t now_;
453 
454     // Base name (without suffix or extensions) of the bugreport files, typically
455     // `bugreport-BUILD_ID`.
456     std::string base_name_;
457 
458     // Name is the suffix part of the bugreport files - it's typically the date (when invoked with
459     // `-d`), but it could be changed by the user..
460     std::string name_;
461 
462     std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY;
463 
464     // Full path of the temporary file containing the bugreport, inside bugreport_internal_dir_.
465     // At the very end this file is pulled into the zip file.
466     std::string tmp_path_;
467 
468     // Full path of the file containing the dumpstate logs, inside bugreport_internal_dir_.
469     // This is useful for debugging.
470     std::string log_path_;
471 
472     // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
473     std::string path_;
474 
475     // Full path of the file containing the screenshot (when requested).
476     std::string screenshot_path_;
477 
478     // Pointer to the zipped file.
479     std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose};
480 
481     // Pointer to the zip structure.
482     std::unique_ptr<ZipWriter> zip_writer_;
483 
484     // Binder object listening to progress.
485     android::sp<android::os::IDumpstateListener> listener_;
486 
487     // List of open tombstone dump files.
488     std::vector<DumpData> tombstone_data_;
489 
490     // List of open ANR dump files.
491     std::vector<DumpData> anr_data_;
492 
493     // A callback to IncidentCompanion service, which checks user consent for sharing the
494     // bugreport with the calling app. If the user has not responded yet to the dialog it will
495     // be neither confirmed nor denied.
496     class ConsentCallback : public android::os::BnIncidentAuthListener {
497       public:
498         ConsentCallback();
499         android::binder::Status onReportApproved() override;
500         android::binder::Status onReportDenied() override;
501 
502         enum ConsentResult { APPROVED, DENIED, UNAVAILABLE };
503 
504         ConsentResult getResult();
505 
506         // Returns the time since creating this listener
507         uint64_t getElapsedTimeMs() const;
508 
509       private:
510         ConsentResult result_;
511         uint64_t start_time_;
512         std::mutex lock_;
513     };
514 
515   private:
516     RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package);
517 
518     RunStatus DumpstateDefaultAfterCritical();
519 
520     void MaybeTakeEarlyScreenshot();
521 
522     void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
523                                              const std::string& calling_package);
524 
525     void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package);
526 
527     // Removes the in progress files output files (tmp file, zip/txt file, screenshot),
528     // but leaves the log file alone.
529     void CleanupTmpFiles();
530 
531     RunStatus HandleUserConsentDenied();
532 
533     // Copies bugreport artifacts over to the caller's directories provided there is user consent or
534     // called by Shell.
535     RunStatus CopyBugreportIfUserConsented(int32_t calling_uid);
536 
537     // Used by GetInstance() only.
538     explicit Dumpstate(const std::string& version = VERSION_CURRENT);
539 
540     android::sp<ConsentCallback> consent_callback_;
541 
542     DISALLOW_COPY_AND_ASSIGN(Dumpstate);
543 };
544 
545 // for_each_pid_func = void (*)(int, const char*);
546 // for_each_tid_func = void (*)(int, int, const char*);
547 
548 typedef void(for_each_pid_func)(int, const char*);
549 typedef void(for_each_tid_func)(int, int, const char*);
550 
551 /* saves the the contents of a file as a long */
552 int read_file_as_long(const char *path, long int *output);
553 
554 /* prints the contents of the fd
555  * fd must have been opened with the flag O_NONBLOCK.
556  */
557 int dump_file_from_fd(const char *title, const char *path, int fd);
558 
559 /* calls skip to gate calling dump_from_fd recursively
560  * in the specified directory. dump_from_fd defaults to
561  * dump_file_from_fd above when set to NULL. skip defaults
562  * to false when set to NULL. dump_from_fd will always be
563  * called with title NULL.
564  */
565 int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
566                int (*dump_from_fd)(const char* title, const char* path, int fd));
567 
568 /** opens a socket and returns its file descriptor */
569 int open_socket(const char *service);
570 
571 /*
572  * Redirects 'redirect' to a service control socket.
573  *
574  * Returns true if redirect succeeds.
575  */
576 bool redirect_to_socket(FILE* redirect, const char* service);
577 
578 /*
579  * Redirects 'redirect' to a file indicated by 'path', truncating it.
580  *
581  * Returns true if redirect succeeds.
582  */
583 bool redirect_to_file(FILE* redirect, char* path);
584 
585 /*
586  * Redirects 'redirect' to an existing file indicated by 'path', appending it.
587  *
588  * Returns true if redirect succeeds.
589  */
590 bool redirect_to_existing_file(FILE* redirect, char* path);
591 
592 /* create leading directories, if necessary */
593 void create_parent_dirs(const char *path);
594 
595 /* for each process in the system, run the specified function */
596 void for_each_pid(for_each_pid_func func, const char *header);
597 
598 /* for each thread in the system, run the specified function */
599 void for_each_tid(for_each_tid_func func, const char *header);
600 
601 /* Displays a blocked processes in-kernel wait channel */
602 void show_wchan(int pid, int tid, const char *name);
603 
604 /* Displays a processes times */
605 void show_showtime(int pid, const char *name);
606 
607 /* Runs "showmap" for a process */
608 void do_showmap(int pid, const char *name);
609 
610 /* Gets the dmesg output for the kernel */
611 void do_dmesg();
612 
613 /* Prints the contents of all the routing tables, both IPv4 and IPv6. */
614 void dump_route_tables();
615 
616 /* Play a sound via Stagefright */
617 void play_sound(const char *path);
618 
619 /* Checks if a given path is a directory. */
620 bool is_dir(const char* pathname);
621 
622 /** Gets the last modification time of a file, or default time if file is not found. */
623 time_t get_mtime(int fd, time_t default_mtime);
624 
625 /** Gets command-line arguments. */
626 void format_args(int argc, const char *argv[], std::string *args);
627 
628 /** Main entry point for dumpstate. */
629 int run_main(int argc, char* argv[]);
630 
631 #ifdef __cplusplus
632 }
633 #endif
634 
635 #endif /* FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_ */
636