2626
2727#include " absl/strings/str_join.h"
2828
29+ #include " cuttlefish/flag_parser/gflags_compat.h"
2930#include " cuttlefish/host/commands/cvd/cli/command_request.h"
3031#include " cuttlefish/host/commands/cvd/cli/commands/command_handler.h"
32+ #include " cuttlefish/host/commands/cvd/cli/help_format.h"
3133#include " cuttlefish/host/commands/cvd/cli/request_context.h"
34+ #include " cuttlefish/host/commands/cvd/cli/selector/selector_common_parser.h"
3235#include " cuttlefish/host/commands/cvd/cli/types.h"
3336#include " cuttlefish/result/result.h"
3437
3538namespace cuttlefish {
3639namespace {
3740
38- constexpr char kHelpIntroText [] = R"( Cuttlefish Virtual Device (CVD) CLI.
39-
40- Cuttlefish is a configurable virtual Android device offering high-fidelity
41- Android emulation for platform and app development, and automated testing.
42-
43- Device Organization:
44- Cuttlefish devices are organized into Instance Groups and Instances.
45- - An Instance represents a single virtual Android device.
46- - An Instance Group is a logical collection of one or more Instances created
47- and managed together.
48- - Group and Instance Naming:
49- - Each group and instance has a name. Names can be user-provided or
50- automatically generated by cvd.
51- - Group names must be unique across the host for the current user.
52- - Instance names must be unique within their containing group.
53-
54- Cuttlefish devices lifecycle:
55- - create: Cuttlefish devices must be "created" (`cvd create` command)
56- before they can be used. The instance group directory structure is created,
57- host resources like virtual networks and instance ids are allocated and
58- build artifacts are fetched during this step. Cuttlefish devices are
59- automatically started at the end of the creation process unless the user
60- passes the --nostart option.
61- - start|stop Turn the virtual devices ON or OFF respectively. These actions
62- can be performed repeatedly just like in a physical Android device. Virtual
63- device state and disks are preserved across a stop-start cycle.
64- - remove: The opposite of create, this action completely removes the
65- devices from the system. Logs and virtual disks in particular are deleted
66- during this step. Host resources, context ids and cuttlefish names are also
67- released.
68-
69- Selector Arguments:
70- Many commands act on an existing instance or group. If only one group or
71- instance exists, cvd will select that one as the command's target, otherwise
72- it will ask you to select one from a list. Selector options can be used
73- *before* the subcommand explicitly select a target and avoid the interactive
74- seleccion step:
75- cvd -group_name <group_name> <command>
76- cvd -instance_name <instance_name> <command>
77-
78- Build Fetching and Caching:
79- cvd can automatically download Android builds from the Android Build servers
80- (e.g., "@ab/aosp-android-latest-release/aosp_cf_x86_64_only_phone-userdebug").
81- cvd fetches the required host tools and device images, caching them locally to
82- accelerate future device creation.
83-
84- Usage:
85- cvd [selector/global options] <command> [args]
86-
87- Global Options:
88- -help Print this message
89- -verbosity=<LEVEL> Adjust Cvd verbosity level. LEVEL is one of ERROR,
90- WARNING, INFO, DEBUG, VERBOSE.
91- Selector Options:
92- -group_name <name> Specify the name of the instance group created
93- or selected.
94- -instance_name <name> Selects the device of the given name to perform the
95- commands for.
96- -instance_name <names> Takes the names of the devices to create within an
97- instance group. The 'names' is comma-separated.
98-
99- Commands (cvd help <command> for more information):
100-
101- )" ;
102-
103- constexpr char kHelpExamplesText [] = R"(
104- Typical Usage Examples:
41+ constexpr char kHelpExamplesText [] = R"( Typical Usage Examples:
10542
10643 Create from specification (Multi-Device / Config-driven):
44+
10745 1. Create a JSON configuration file (e.g., spec.json) containing:
10846 {
10947 "instances": [
11048 {
111- "name": "phone-ins",
49+ "name": "phone-ins-1 ",
11250 "disk": {
11351 "default_build": "@ab/aosp-android-latest-release/aosp_cf_x86_64_only_phone-userdebug"
11452 }
11553 },
11654 {
117- "name": "wearable -ins",
55+ "name": "phone -ins-2 ",
11856 "disk": {
119- "default_build": "@ab/aosp-android-latest-release/aosp_cf_x86_64_foldable -userdebug"
57+ "default_build": "@ab/aosp-android-latest-release/aosp_cf_x86_64_only_phone -userdebug"
12058 }
12159 }
12260 ]
12361 }
62+
12463 2. Launch the group:
12564 $ cvd create --config_file=spec.json
65+
12666 3. View the state of the running fleet:
12767 $ cvd fleet
68+
12869 4. View the log files:
12970 $ cvd logs
13071 $ cvd logs -p launcher.log
72+
13173 5. Open the web UI at https://localhost:1443
132- 6. Interact with the device via ADB (auto-connected on every start)
74+
75+ 6. Interact with the device via ADB (auto-connected on every start if the
76+ ADB server is running)
77+
13378 7. Control the lifecycle:
13479 $ cvd stop
13580 $ cvd start
81+
13682 8. Gather all logs for troubleshooting:
13783 $ cvd bugreport
84+
13885 9. Clean up and delete all resources:
13986 $ cvd remove
14087
14188 Create from local source (Platform Developer / AOSP build):
89+
14290 1. Build Android in your terminal (ensuring ANDROID_HOST_OUT and
14391 ANDROID_PRODUCT_OUT are set in the environment).
92+
14493 2. Launch the device:
14594 $ cvd create
95+
14696 3. After making changes, rebuild and restart:
14797 $ cvd stop
14898 $ m # Rebuild android
@@ -152,21 +102,11 @@ Typical Usage Examples:
152102 If virtual devices become unresponsive, or if 'cvd remove' fails to fully
153103 clean up the environment, use 'cvd reset' to forcefully terminate all
154104 Cuttlefish-related background processes and free up host resources:
155- $ cvd reset
156- )" ;
105+ $ cvd reset)" ;
157106
158107constexpr char kSummaryHelpText [] =
159108 " Used to display help information for other commands" ;
160109
161- constexpr char kDetailedHelpText [] =
162- R"( cvd help - used to display help text for cvd and its commands
163-
164- Example usage:
165- cvd help - displays summary help for available commands
166-
167- cvd help <command> - displays more detailed help for the specific command
168- )" ;
169-
170110void PrintHandler (std::stringstream& help_message,
171111 const CvdCommandHandler& handler) {
172112 help_message << " \t " << absl::StrJoin (handler.CmdList (), " , " ) << " - " ;
@@ -201,30 +141,110 @@ std::string CvdHelpHandler::SummaryHelp() const { return kSummaryHelpText; }
201141
202142bool CvdHelpHandler::RequiresHostConfiguration () const { return false ; }
203143
204- Result<std::string> CvdHelpHandler::DetailedHelp (
205- const CommandRequest& request) {
206- return kDetailedHelpText ;
144+ std::vector<HelpParagraph> CvdHelpHandler::Description () const {
145+ return {
146+ HelpParagraph (" Example usage:" ),
147+ HelpParagraph::Raw (
148+ " cvd help - displays summary help for available commands" ),
149+ HelpParagraph::Raw (" cvd help <command> - displays more detailed help "
150+ " for the specific command" ),
151+ };
207152}
208153
209154std::string CvdHelpHandler::TopLevelHelp () {
210- std::stringstream help_message;
211- help_message << kHelpIntroText ;
155+ std::vector<HelpParagraph> paragraphs;
156+ paragraphs.emplace_back (" Cuttlefish Virtual Device (CVD) CLI." );
157+ paragraphs.emplace_back (
158+ " Cuttlefish is a configurable virtual Android device offering "
159+ " high-fidelity Android emulation for platform and app development and "
160+ " automated testing." );
161+
162+ paragraphs.emplace_back (HelpParagraph::Raw (
163+ R"( Device Organization:
164+ Cuttlefish devices are organized into Instance Groups and Instances.
165+ - An Instance represents a single virtual Android device.
166+ - An Instance Group is a logical collection of one or more Instances created
167+ and managed together.
168+ - Group and Instance Naming:
169+ - Each group and instance has a name. Names can be user-provided or
170+ automatically generated by cvd.
171+ - Group names must be unique across the host for the current user.
172+ - Instance names must be unique within their containing group.)" ));
173+
174+ paragraphs.emplace_back (HelpParagraph::Raw (
175+ R"( Cuttlefish devices lifecycle:
176+ - create: Cuttlefish devices must be "created" (`cvd create` command)
177+ before they can be used. The instance group directory structure is created,
178+ host resources like virtual networks and instance ids are allocated and
179+ build artifacts are fetched during this step. Cuttlefish devices are
180+ automatically started at the end of the creation process unless the user
181+ passes the --nostart option.
182+ - start|stop Turn the virtual devices ON or OFF respectively. These actions
183+ can be performed repeatedly just like in a physical Android device. Virtual
184+ device state and disks are preserved across a stop-start cycle.
185+ - remove: The opposite of create, this action completely removes the
186+ devices from the system. Logs and virtual disks in particular are deleted
187+ during this step. Host resources, context ids and cuttlefish names are also
188+ released.)" ));
189+
190+ paragraphs.emplace_back (HelpParagraph::Raw (
191+ R"( Selector Arguments:
192+ Many commands act on an existing instance or group. If only one group or
193+ instance exists, cvd will select that one as the command's target, otherwise
194+ it will ask you to select one from a list. Selector options can be used
195+ to explicitly select a target and avoid the interactive selection step:
196+ cvd -group_name <group_name> <command>
197+ cvd -instance_name <instance_name> <command>)" ));
198+
199+ paragraphs.emplace_back (" Build Fetching and Caching:" );
200+ paragraphs.emplace_back (
201+ " cvd can automatically download Android builds from the Android Build "
202+ " servers (e.g., "
203+ " \" @ab/aosp-android-latest-release/"
204+ " aosp_cf_x86_64_only_phone-userdebug\" ). cvd fetches the required host "
205+ " tools and device images, caching them locally to accelerate future "
206+ " device creation." );
212207
208+ paragraphs.emplace_back (HelpParagraph::Raw (
209+ R"( Usage:
210+ cvd [selector/global options] <command> [args])" ));
211+
212+ std::stringstream help_message;
213+ help_message << FormatHelpText (paragraphs);
214+
215+ help_message << " Global Options:\n " ;
216+ bool help_val = false ;
217+ std::string verbosity_val = " INFO" ;
218+ std::vector<Flag> global_flags = {
219+ GflagsCompatFlag (" help" , help_val).Help (" Print this message" ),
220+ GflagsCompatFlag (" verbosity" , verbosity_val)
221+ .Help (" Adjust Cvd verbosity level. LEVEL is one of ERROR, WARNING, "
222+ " INFO, DEBUG, VERBOSE." ),
223+ };
224+ help_message << FormatFlagsHelp (global_flags);
225+
226+ help_message << " Selector Options:\n " ;
227+ selector::SelectorOptions dummy_selector_options;
228+ auto selector_flags =
229+ selector::BuildCommonSelectorFlags (dummy_selector_options);
230+ help_message << FormatFlagsHelp (selector_flags);
231+
232+ help_message << " Commands (cvd help <command> for more information):\n\n " ;
213233 for (const auto & handler : request_handlers_) {
214234 if (!handler->RequiresDeviceExists ()) {
215235 PrintHandler (help_message, *handler);
216236 }
217237 }
218238
219239 help_message << " \n Device-Specific Commands (cvd help <command> for more "
220- " information):\n " ;
240+ " information):\n\n " ;
221241 for (const auto & handler : request_handlers_) {
222242 if (handler->RequiresDeviceExists ()) {
223243 PrintHandler (help_message, *handler);
224244 }
225245 }
226246
227- help_message << kHelpExamplesText ;
247+ help_message << FormatHelpText ({ HelpParagraph::Raw ( kHelpExamplesText )}) ;
228248
229249 return help_message.str ();
230250}
0 commit comments