// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The following enables go generate to generate the doc.go file.
//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .

// The following generates the embedded_gradle.go file from the madb_init.gradle file.
//go:generate go run scripts/embed_gradle_script.go madb_init.gradle embedded_gradle.go gradleInitScript

// The following generates the version.go file with the version string defined in the MADB_VERSION file.
//go:generate go run scripts/update_version.go

package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"

	"v.io/x/lib/cmdline"
	"v.io/x/lib/gosh"
	"v.io/x/lib/textutil"
)

var (
	allDevicesFlag   bool
	allEmulatorsFlag bool
	devicesFlag      string
	sequentialFlag   bool
	prefixFlag       string

	clearCacheFlag bool
	moduleFlag     string
	variantFlag    string

	buildFlag bool

	wd string // working directory
)

func init() {
	cmdMadb.Flags.BoolVar(&allDevicesFlag, "d", false, `Restrict the command to only run on real devices.`)
	cmdMadb.Flags.BoolVar(&allEmulatorsFlag, "e", false, `Restrict the command to only run on emulators.`)
	cmdMadb.Flags.StringVar(&devicesFlag, "n", "", `Comma-separated device serials, qualifiers, device indices (e.g., '@1', '@2'), nicknames (set by 'madb name'), or group names (set by 'madb group'). A device index is specified by an '@' sign followed by the index of the device in the output of 'adb devices' command, starting from 1. Command will be run only on specified devices.`)
	cmdMadb.Flags.BoolVar(&sequentialFlag, "seq", false, `Run the command sequentially, instead of running it in parallel.`)
	cmdMadb.Flags.StringVar(&prefixFlag, "prefix", "name", `Specify which output prefix to use. You can choose from the following options:
    name   - Display the nickname of the device. The serial number is used instead if the
             nickname is not set for the given device.
    serial - Display the serial number of the device.
    none   - Do not display the output prefix.`)

	// Store the current working directory.
	var err error
	wd, err = os.Getwd()
	if err != nil {
		panic(err)
	}
}

// initializePropertyCacheFlags sets up the flags related to extracting and caching project properties.
func initializePropertyCacheFlags(flags *flag.FlagSet) {
	flags.BoolVar(&clearCacheFlag, "clear-cache", false, `Clear the cache and re-extract the variant properties such as the application ID and the main activity name. Only takes effect when no arguments are provided.`)
	flags.StringVar(&moduleFlag, "module", "", `Specify which application module to use, when the current directory is the top level Gradle project containing multiple sub-modules. When not specified, the first available application module is used. Only takes effect when no arguments are provided.`)
	flags.StringVar(&variantFlag, "variant", "", `Specify which build variant to use. When not specified, the first available build variant is used. Only takes effect when no arguments are provided.`)
}

// initializeBuildFlags sets up the flags related to running Gradle build tasks.
func initializeBuildFlags(flags *flag.FlagSet) {
	flags.BoolVar(&buildFlag, "build", true, `Build the target app variant before installing or running the app.`)
}

var cmdMadb = &cmdline.Command{
	Children: []*cmdline.Command{
		cmdMadbClearData,
		cmdMadbExec,
		cmdMadbExtern,
		cmdMadbGroup,
		cmdMadbInstall,
		cmdMadbName,
		cmdMadbResolve,
		cmdMadbShell,
		cmdMadbStart,
		cmdMadbStop,
		cmdMadbUninstall,
		cmdMadbUser,
		cmdMadbVersion,
	},
	Name:  "madb",
	Short: "Multi-device Android Debug Bridge",
	Long: `
Multi-device Android Debug Bridge

The madb command wraps Android Debug Bridge (adb) command line tool
and provides various features for controlling multiple Android devices concurrently.
`,
}

func main() {
	cmdline.Main(cmdMadb)
}

// Makes sure that adb server is running.
// Intended to be called at the beginning of each subcommand.
func startAdbServer() error {
	// TODO(youngseokyoon): search for installed adb tool more rigourously.
	if err := exec.Command("adb", "start-server").Run(); err != nil {
		return fmt.Errorf("Failed to start adb server. Please make sure that adb is in your PATH: %v", err)
	}

	return nil
}

type deviceType string

const (
	emulator   deviceType = "Emulator"
	realDevice deviceType = "RealDevice"
)

type device struct {
	Serial     string
	Type       deviceType
	Qualifiers []string
	Nickname   string
	Index      int
	UserID     string
}

// Returns the display name which is intended to be used as the console output prefix.
// This would be the nickname of the device if there is one; otherwise, the serial number is used.
func (d device) displayName() string {
	if d.Nickname != "" {
		return d.Nickname
	}

	return d.Serial
}

// Runs "adb devices -l" command, and parses the result to get all the device serial numbers.
func getDevices(cfg *config) ([]device, error) {
	sh := gosh.NewShell(nil)
	defer sh.Cleanup()

	output := sh.Cmd("adb", "devices", "-l").Stdout()

	return parseDevicesOutput(output, cfg)
}

// Parses the output generated from "adb devices -l" command and return the list of device serial numbers
// Devices that are currently offline are excluded from the returned list.
func parseDevicesOutput(output string, cfg *config) ([]device, error) {
	lines := strings.Split(output, "\n")

	result := []device{}

	// Check the first line of the output
	if len(lines) <= 0 || strings.TrimSpace(lines[0]) != "List of devices attached" {
		return result, fmt.Errorf("The output from 'adb devices -l' command does not look as expected.")
	}

	// Iterate over all the device serial numbers, starting from the second line.
	for i, line := range lines[1:] {
		fields := strings.Fields(line)

		if len(fields) <= 1 || fields[1] == "offline" {
			continue
		}

		// Fill in the device serial, all the qualifiers, and the device index.
		d := device{
			Serial:     fields[0],
			Qualifiers: fields[2:],
			Index:      i + 1,
		}

		// Determine whether this device is an emulator or a real device.
		if strings.HasPrefix(d.Serial, "emulator") {
			d.Type = emulator
		} else {
			d.Type = realDevice
		}

		if cfg != nil {
			// Determine whether there is a nickname defined for this device,
			// so that the console output prefix can display the nickname instead of the serial.
		NSMLoop:
			for nickname, serial := range cfg.Names {
				if d.Serial == serial {
					d.Nickname = nickname
					break
				}

				for _, qualifier := range d.Qualifiers {
					if qualifier == serial {
						d.Nickname = nickname
						break NSMLoop
					}
				}
			}

			// Determine whether there is a default user ID set by 'madb user'.
			if userID, ok := cfg.UserIDs[d.Serial]; ok {
				d.UserID = userID
			}
		}

		result = append(result, d)
	}

	return result, nil
}

// Gets all the devices specified by the device specifier flags.
// Intended to be used by most of the madb sub-commands except for 'madb name'.
func getSpecifiedDevices() ([]device, error) {
	configFile, err := getDefaultConfigFilePath()
	if err != nil {
		return nil, err
	}

	cfg, err := readConfig(configFile)
	if err != nil {
		return nil, err
	}

	devices, err := getDevices(cfg)
	if err != nil {
		return nil, err
	}

	tokens := strings.Split(devicesFlag, ",")
	filtered, err := filterSpecifiedDevices(devices, cfg, allDevicesFlag, allEmulatorsFlag, tokens)
	if err != nil {
		return nil, err
	}

	if len(filtered) == 0 {
		return nil, fmt.Errorf("No devices matching the device specifiers.")
	}

	return filtered, nil
}

type deviceSpec struct {
	index int
	token string
}

func filterSpecifiedDevices(devices []device, cfg *config, allDevices, allEmulators bool, tokens []string) ([]device, error) {
	// If the tokens only contains one empty string, treat it as an empty slice.
	if len(tokens) == 1 && tokens[0] == "" {
		tokens = []string{}
	}

	// If no device specifier flags are set, run on all devices and emulators.
	if allDevices == false && allEmulators == false && len(tokens) == 0 {
		return devices, nil
	}

	result := make([]device, 0, len(devices))

	var specs = []deviceSpec{}
	if len(tokens) > 0 {
		// Check if the provided specifiers are all valid.
		for _, token := range tokens {
			if err := isValidDeviceSpecifier(token); err != nil {
				return nil, err
			}
		}

		// Expand all the groups and get the device specs.
		tokens = expandGroups(tokens, cfg)
		specs = getDeviceSpecsFromTokens(tokens, cfg)
	}

	for _, d := range devices {
		if shouldIncludeDevice(d, specs, allDevices, allEmulators) {
			result = append(result, d)
		}
	}

	return result, nil
}

// getDeviceSpecsFromTokens takes device specifier tokens and turns them into
// the corresponding deviceSpec structs.
func getDeviceSpecsFromTokens(tokens []string, cfg *config) []deviceSpec {
	specs := make([]deviceSpec, 0, len(tokens)*2)

	for _, token := range tokens {
		if strings.HasPrefix(token, "@") {
			index, _ := strconv.Atoi(token[1:])
			specs = append(specs, deviceSpec{index, ""})
		} else {
			specs = append(specs, deviceSpec{0, token})
		}
	}

	return specs
}

func shouldIncludeDevice(d device, specs []deviceSpec, allDevices, allEmulators bool) bool {
	if allDevices && d.Type == realDevice {
		return true
	}

	if allEmulators && d.Type == emulator {
		return true
	}

	for _, spec := range specs {
		// Ignore empty tokens
		if spec.index == 0 && spec.token == "" {
			continue
		}

		if spec.index > 0 {
			if d.Index == spec.index {
				return true
			}
			continue
		}

		if d.Serial == spec.token || d.Nickname == spec.token {
			return true
		}

		for _, qualifier := range d.Qualifiers {
			if qualifier == spec.token {
				return true
			}
		}
	}

	return false
}

// config contains various configuration information for madb.
type config struct {
	// Version indicates the version string of madb binary by which this config
	// was written to the file, in case it has to be migrated to a newer schema.
	Version string
	// Names keeps the mapping between device nicknames and their serials.
	Names map[string]string
	// Groups keeps the device group definitions. A group can contain multiple
	// devices, each of which is denoted by its name, serial, or index. A group
	// can also include other groups.
	Groups map[string][]string
	// UserIDs keeps the mapping between device serials and their default user
	// IDs.
	UserIDs map[string]string
}

func newConfig() *config {
	return &config{
		Names:   make(map[string]string),
		Groups:  make(map[string][]string),
		UserIDs: make(map[string]string),
	}
}

// Returns the config dir located at "~/.madb"
func getConfigDir() (string, error) {
	home := os.Getenv("HOME")
	if home == "" {
		return "", fmt.Errorf("Could not find the HOME directory.")
	}

	configDir := filepath.Join(home, ".madb")
	if err := os.MkdirAll(configDir, 0755); err != nil {
		return "", err
	}

	if err := migrateOldConfigFiles(configDir); err != nil {
		fmt.Fprintf(os.Stderr, "WARNING: Could not successfully migrate the old config files to the newer format: %v", err)
	}

	return configDir, nil
}

// migrateOldConfigFiles checks if there are old config files (for madb v1.x) in
// the provided config directory. If there are, it migrates these configs to the
// new format, so that users can preserve their device nicknames and user IDs
// when upgrading madb to a newer version.
// TODO(youngseokyoon): remove this migration code in the future.
func migrateOldConfigFiles(configDir string) error {
	// Do not try migrating if the new format "config" file already exists.
	configFile := filepath.Join(configDir, "config")
	if _, err := os.Stat(configFile); err == nil {
		return nil
	}

	cfg := newConfig()
	if err := migrateOldConfig(configDir, "nicknames", &cfg.Names); err != nil {
		return err
	}
	if err := migrateOldConfig(configDir, "users", &cfg.UserIDs); err != nil {
		return err
	}
	return writeConfig(cfg, configFile)
}

// migrateOldConfig reads an old config file, which contains a JSON-encoded map,
// and writes the contents to the given map pointer (data).
func migrateOldConfig(configDir, filename string, data *map[string]string) error {
	configFile := filepath.Join(configDir, filename)
	if _, err := os.Stat(configFile); os.IsNotExist(err) {
		return nil
	}

	f, err := os.Open(configFile)
	if err != nil {
		return err
	}
	defer f.Close()

	decoder := json.NewDecoder(f)

	if err := decoder.Decode(data); err != nil {
		data = new(map[string]string)
		return fmt.Errorf("Could not read the old config file %q: %v", filename, err)
	}

	fmt.Printf("NOTE: Migrating the %q file to the newer format.\n", filename)

	// Rename the old config as a backup
	if err := os.Rename(configFile, configFile+".bak"); err != nil {
		return fmt.Errorf("Could not rename the %q file: %v", filename, err)
	}

	fmt.Printf("NOTE: The backup file can be found at %q.\n", filepath.Join(configDir, filename+".bak"))

	return nil
}

// getDefaultConfigFilePath returns the default location of the config file.
func getDefaultConfigFilePath() (string, error) {
	configDir, err := getConfigDir()
	if err != nil {
		return "", err
	}

	return filepath.Join(configDir, "config"), nil
}

// readConfig reads the provided file and reconstructs the config struct.
// When the file does not exist, it returns an empty config with the members
// initialized as empty maps.
func readConfig(filename string) (*config, error) {
	result := newConfig()

	// The file may not exist or be empty when there are no stored data.
	if stat, err := os.Stat(filename); os.IsNotExist(err) || (err == nil && stat.Size() == 0) {
		return result, nil
	}

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	decoder := json.NewDecoder(f)

	// Decoding might fail when the file is somehow corrupted, or when the schema is updated.
	// In such cases, move on after resetting the cache file instead of exiting the app.
	if err := decoder.Decode(result); err != nil {
		fmt.Fprintf(os.Stderr, "WARNING: Could not decode the file: %q. Resetting the file.\n", err)
		if err := os.Remove(f.Name()); err != nil {
			return nil, err
		}

		result = new(config)
	}

	if result.Names == nil {
		result.Names = make(map[string]string)
	}
	if result.Groups == nil {
		result.Groups = make(map[string][]string)
	}
	if result.UserIDs == nil {
		result.UserIDs = make(map[string]string)
	}

	return result, nil
}

// writeConfig takes a config and writes it into the provided file name.
func writeConfig(cfg *config, filename string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	cfg.Version = version

	encoder := json.NewEncoder(f)
	return encoder.Encode(*cfg)
}

func isNameInUse(name string, cfg *config) bool {
	return isDeviceNickname(name, cfg) || isGroupName(name, cfg)
}

func isDeviceNickname(name string, cfg *config) bool {
	_, ok := cfg.Names[name]
	return ok
}

func isGroupName(name string, cfg *config) bool {
	_, ok := cfg.Groups[name]
	return ok
}

func isValidSerial(serial string) bool {
	r := regexp.MustCompile(`^([A-Za-z0-9:\-\._]+|@\d+)$`)
	return r.MatchString(serial)
}

func isValidName(name string) bool {
	r := regexp.MustCompile(`^\w+$`)
	return r.MatchString(name)
}

// isValidMember takes a member string given as an argument, and returns nil
// when the member string is valid. Otherwise, an error is returned indicating
// the reason why the given member string is not valid.
func isValidDeviceSpecifier(member string) error {
	if strings.HasPrefix(member, "@") {
		index, err := strconv.Atoi(member[1:])
		if err != nil || index <= 0 {
			return fmt.Errorf("Invalid device specifier %q. '@' sign must be followed by a numeric device index starting from 1.", member)
		}
		return nil
	} else if !isValidSerial(member) && !isValidName(member) {
		return fmt.Errorf("Invalid device specifier %q. Not a valid serial or a nickname.", member)
	}

	return nil
}

type subCommandRunner struct {
	// init is an optional function that does some initial work that should only
	// be performed once, before directing the command to all the devices.
	// The returned string slice becomes the new set of arguments passed into
	// the sub command.
	init func(env *cmdline.Env, args []string, properties variantProperties) ([]string, error)
	// subCmd defines the behavior of the sub command which will run on all the
	// devices in parallel.
	subCmd func(env *cmdline.Env, args []string, d device, properties variantProperties) error
	// extractProperties indicates whether this subCommand needs the extracted
	// project properties.
	extractProperties bool
}

var _ cmdline.Runner = (*subCommandRunner)(nil)

// Invokes the sub command on all the devices in parallel.
func (r subCommandRunner) Run(env *cmdline.Env, args []string) error {
	prefixFlag = strings.ToLower(prefixFlag)
	allowed := []string{"name", "serial", "none"}
	if !isStringInSlice(prefixFlag, allowed) {
		return fmt.Errorf("The -prefix flag value must be one of %v", strings.Join(allowed, ", "))
	}

	if err := startAdbServer(); err != nil {
		return err
	}

	devices, err := getSpecifiedDevices()
	if err != nil {
		return err
	}

	// Extract the properties if needed.
	properties := variantProperties{}
	if r.extractProperties && isGradleProject(wd) {
		properties, err = getProjectPropertiesUsingDefaultCache()
		if err != nil {
			return err
		}
	}

	// Run the init function when provided.
	if r.init != nil {
		newArgs, err := r.init(env, args, properties)
		if err != nil {
			return err
		}

		args = newArgs
	}

	var errs []error
	var errDevices []device

	if sequentialFlag {
		for _, d := range devices {
			if err := r.subCmd(env, args, d, properties); err != nil {
				errs = append(errs, err)
				errDevices = append(errDevices, d)
			}
		}
	} else {
		wg := sync.WaitGroup{}
		for _, d := range devices {
			// Capture the current device value, and run the command in a go-routine.
			deviceCopy := d

			wg.Add(1)
			go func() {
				if err := r.subCmd(env, args, deviceCopy, properties); err != nil {
					errs = append(errs, err)
					errDevices = append(errDevices, deviceCopy)
				}
				wg.Done()
			}()
		}
		wg.Wait()
	}

	// Report any errors returned from the go-routines.
	if errs != nil {
		buffer := bytes.Buffer{}
		buffer.WriteString("Error occurred while running the command on the following devices:")
		for i := 0; i < len(errs); i++ {
			buffer.WriteString("\n[" + errDevices[i].displayName() + "]\t" + errs[i].Error())
		}
		return fmt.Errorf(buffer.String())
	}

	return nil
}

func runGoshCommandForDevice(cmd *gosh.Cmd, d device, printUserID bool) error {
	return runGoshCommandForDeviceWithWriters(cmd, d, printUserID, os.Stdout, os.Stderr)
}

func runGoshCommandForDeviceWithWriters(cmd *gosh.Cmd, d device, printUserID bool, stdout, stderr io.Writer) error {
	prefix := ""
	if prefixFlag != "none" {
		name := d.Serial
		if prefixFlag == "name" {
			name = d.displayName()
		}
		if printUserID && d.UserID != "" {
			name = name + ":" + d.UserID
		}
		prefix = "[" + name + "]\t"
	}

	prefixedStdout := textutil.PrefixLineWriter(stdout, prefix)
	prefixedStderr := textutil.PrefixLineWriter(stderr, prefix)
	cmd.AddStdoutWriter(prefixedStdout)
	cmd.AddStderrWriter(prefixedStderr)
	cmd.Run()
	prefixedStdout.Flush()
	prefixedStderr.Flush()

	return cmd.Shell().Err
}

func initMadbCommand(env *cmdline.Env, args []string, properties variantProperties, flutterPassthrough bool, activityNameRequired bool) ([]string, error) {
	var numRequiredArgs int
	var requiredArgsStr string

	if activityNameRequired {
		numRequiredArgs = 2
		requiredArgsStr = "two arguments"
	} else {
		numRequiredArgs = 1
		requiredArgsStr = "one argument"
	}

	// Pass the arguments through if all the required arguments are provided, or if it is a flutter project.
	if len(args) == numRequiredArgs || (flutterPassthrough && isFlutterProject(wd)) {
		return args, nil
	}

	if len(args) != 0 {
		return nil, fmt.Errorf("You mush provide either zero arguments or exactly %v.", requiredArgsStr)
	}

	// Try to extract the application ID and the main activity name from the Gradle scripts.
	if isGradleProject(wd) {
		args = []string{properties.AppID, properties.Activity}[:numRequiredArgs]
	}

	return args, nil
}

func getProjectPropertiesUsingDefaultCache() (variantProperties, error) {
	cacheFile, err := getDefaultCacheFilePath()
	if err != nil {
		return variantProperties{}, err
	}

	key := variantKey{wd, moduleFlag, variantFlag}
	return getProjectProperties(extractPropertiesFromGradle, key, clearCacheFlag, cacheFile)
}

type variantProperties struct {
	ProjectPath    string
	VariantName    string
	CleanTask      string
	AssembleTask   string
	AppID          string
	Activity       string
	AbiFilters     []string
	VariantOutputs []variantOutput
}

type variantOutput struct {
	Name           string
	OutputFilePath string
	VersionCode    int
	Filters        []filter
}

type filter struct {
	FilterType string
	Identifier string
}

type propertyExtractorFunc func(variantKey) (variantProperties, error)

// getProjectProperties returns the project properties for the given build variant.
// It returns the cached values when the variant is found in the cache file, unless the clearCache
// argument is true. Otherwise, it calls extractPropertiesFromGradle to extract those properties by
// running Gradle scripts.
func getProjectProperties(extractor propertyExtractorFunc, key variantKey, clearCache bool, cacheFile string) (variantProperties, error) {
	if clearCache {
		clearPropertyCacheEntry(key, cacheFile)
	} else {
		// See if the current configuration appears in the cache.
		cache, err := getPropertyCache(cacheFile)
		if err != nil {
			return variantProperties{}, err
		}

		if properties, ok := cache[key]; ok {
			fmt.Println("NOTE: Cached IDs are being used. Use '-clear-cache' flag to clear the cache and extract the IDs from Gradle scripts again.")
			return properties, nil
		}
	}

	fmt.Println("Running Gradle to extract the application ID and the main activity name...")
	properties, err := extractor(key)
	if err != nil {
		return variantProperties{}, err
	}

	// Write these properties to the cache.
	if err := writePropertyCacheEntry(key, properties, cacheFile); err != nil {
		return variantProperties{}, fmt.Errorf("Could not write properties to the cache file: %v", err)
	}

	return properties, nil
}

func isFlutterProject(dir string) bool {
	_, err := os.Stat(filepath.Join(dir, "flutter.yaml"))
	return err == nil
}

func isGradleProject(dir string) bool {
	_, err := os.Stat(filepath.Join(dir, "build.gradle"))
	return err == nil
}

// Looks for the Gradle wrapper script file ("gradlew"), starting from the current directory.
func findGradleWrapper(dir string) (string, error) {
	curDir, err := filepath.Abs(dir)
	if err != nil {
		return "", err
	}

	for {
		wrapperPath := filepath.Join(curDir, "gradlew")

		// Return the path of the gradle wrapper script if it is found.
		_, err := os.Stat(wrapperPath)
		if err == nil {
			// Found Gradle wrapper. Return the absolute path.
			return wrapperPath, nil
		} else if !os.IsNotExist(err) {
			// This is an unexpected error and should be returned.
			return "", err
		}

		// Search again in the parent directory.
		parentDir := path.Dir(curDir)
		if curDir == parentDir || parentDir == "." {
			break
		}

		curDir = parentDir
	}

	return "", fmt.Errorf("Could not find the Gradle wrapper in dir %q or its parent directories.", dir)
}

func extractPropertiesFromGradle(key variantKey) (variantProperties, error) {
	sh := gosh.NewShell(nil)
	defer sh.Cleanup()

	// Continue on error instead of panicking and check the sh.Err value afterwards.
	// Gradle build will finish with exit code other than 0, when it fails.
	// In such cases, we want to show users meaningful error messages instead of stacktraces.
	sh.PropagateChildOutput = true
	sh.ContinueOnError = true

	wrapper, err := findGradleWrapper(key.Dir)
	if err != nil {
		return variantProperties{}, err
	}

	// Write the init script in a temp file.
	initScript := sh.MakeTempFile()
	initScript.WriteString(gradleInitScript)
	initScript.Sync()

	// Create a temporary file in which Gradle can write the results.
	outputFile := sh.MakeTempFile()

	// Run the gradle wrapper to extract the application ID and the main activity name from the build scripts.
	cmdArgs := []string{"--daemon", "-q", "-I", initScript.Name(), "-PmadbOutputFile=" + outputFile.Name()}

	// Specify the project directory. If the module name is explicitly set, combine it with the base directory.
	cmdArgs = append(cmdArgs, "-p", filepath.Join(key.Dir, key.Module))

	// Specify the variant
	if key.Variant != "" {
		cmdArgs = append(cmdArgs, "-PmadbVariant="+key.Variant)
	}

	// Specify the tasks
	cmdArgs = append(cmdArgs, "madbExtractVariantProperties")

	cmd := sh.Cmd(wrapper, cmdArgs...)
	cmd.Run()

	if err = sh.Err; err != nil {
		return variantProperties{}, err
	}

	// Read what is written in the temporary file.
	// The file must be in JSON format.
	result := variantProperties{}
	decoder := json.NewDecoder(outputFile)
	if err = decoder.Decode(&result); err != nil {
		return variantProperties{}, fmt.Errorf("Could not extract the application ID and the main activity name: %v", err)
	}

	return result, nil
}

// expandKeywords takes a command line argument and a device configuration, and returns a new
// argument where the predefined keywords ("{{index}}", "{{name}}", "{{serial}}") are expanded.
func expandKeywords(arg string, d device) string {
	exp := regexp.MustCompile(`{{(index|name|serial)}}`)
	result := exp.ReplaceAllStringFunc(arg, func(keyword string) string {
		switch keyword {
		case "{{index}}":
			return strconv.Itoa(d.Index)
		case "{{name}}":
			return d.displayName()
		case "{{serial}}":
			return d.Serial
		default:
			return keyword
		}
	})

	return result
}

// isStringInSlice determines whether the given string appears in the slice.
func isStringInSlice(str string, slice []string) bool {
	for _, elem := range slice {
		if str == elem {
			return true
		}
	}

	return false
}

type pathProvider func() (string, error)

// subCommandRunnerWithFilepath is an adapter that turns the madb
// {group|name|user} subcommand functions into cmdline.Runners.
type subCommandRunnerWithFilepath struct {
	subCmd func(*cmdline.Env, []string, string) error
	pp     pathProvider
}

var _ cmdline.Runner = (*subCommandRunnerWithFilepath)(nil)

// Run implements the cmdline.Runner interface by providing the default name
// file path as the third string argument of the underlying run function.
func (f subCommandRunnerWithFilepath) Run(env *cmdline.Env, args []string) error {
	p, err := f.pp()
	if err != nil {
		return err
	}

	return f.subCmd(env, args, p)
}

// byFirstElement is used for sorting the groups by their names. Used in various
// list commands.
type byFirstElement [][]string

func (a byFirstElement) Len() int           { return len(a) }
func (a byFirstElement) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a byFirstElement) Less(i, j int) bool { return a[i][0] < a[j][0] }
