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