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