[skqp] More args for skqp related scripts

- allows to choose api versions in run_testlab.go
- adds api_version and work_arounds to generate_gn_args

Bug: skia:
Change-Id: I87516b493f4d8eef3689d1722a5dd864131a44f8
Reviewed-on: https://skia-review.googlesource.com/102900
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
Commit-Queue: Stephan Altmueller <stephana@google.com>
diff --git a/infra/cts/run_testlab.go b/infra/cts/run_testlab.go
index 98aa160..6a7f765 100644
--- a/infra/cts/run_testlab.go
+++ b/infra/cts/run_testlab.go
@@ -16,6 +16,7 @@
 	"os"
 	"os/exec"
 	"sort"
+	"strconv"
 	"strings"
 	"syscall"
 	"time"
@@ -51,19 +52,19 @@
 		"hammerhead": {"23"},
 		"harpia":     {"23"},
 		"hero2lte":   {"23"},
-		"herolte":    {"24v"},
+		"herolte":    {"24"},
 		"j1acevelte": {"22"},
 		"j5lte":      {"23"},
 		"j7xelte":    {"23"},
 		"lucye":      {"24"},
 		// "mako":        {"22"},   deprecated
 		"osprey_umts": {"22"},
-		"p1":          {"22"},
-		"sailfish":    {"26"},
-		"shamu":       {"23"},
-		"trelte":      {"22"},
-		"zeroflte":    {"22"},
-		"zerolte":     {"22"},
+		// "p1":          {"22"},   deprecated
+		"sailfish": {"26"},
+		"shamu":    {"23"},
+		"trelte":   {"22"},
+		"zeroflte": {"22"},
+		"zerolte":  {"22"},
 	}
 )
 
@@ -75,6 +76,8 @@
 var (
 	serviceAccountFile = flag.String("service_account_file", "", "Credentials file for service account.")
 	dryRun             = flag.Bool("dryrun", false, "Print out the command and quit without triggering tests.")
+	minAPIVersion      = flag.Int("min_api", 22, "Minimum API version required by device.")
+	maxAPIVersion      = flag.Int("max_api", 23, "Maximum API version required by device.")
 )
 
 const (
@@ -108,7 +111,7 @@
 	}
 
 	// Get list of all available devices.
-	devices, ignoredDevices, err := getAvailableDevices(WHITELIST_DEV_IDS)
+	devices, ignoredDevices, err := getAvailableDevices(WHITELIST_DEV_IDS, *minAPIVersion, *maxAPIVersion)
 	if err != nil {
 		sklog.Fatalf("Unable to retrieve available devices: %s", err)
 	}
@@ -124,7 +127,7 @@
 // getAvailableDevices is given a whitelist. It queries Firebase Testlab for all
 // available devices and then returns a list of devices to be tested and the list
 // of ignored devices.
-func getAvailableDevices(whiteList map[string][]string) ([]*tsuite.DeviceVersions, []*tsuite.DeviceVersions, error) {
+func getAvailableDevices(whiteList map[string][]string, minAPIVersion, maxAPIVersion int) ([]*tsuite.DeviceVersions, []*tsuite.DeviceVersions, error) {
 	// Get the list of all devices in JSON format from Firebase testlab.
 	var buf bytes.Buffer
 	cmd := parseCommand(CMD_AVAILABE_DEVICES)
@@ -151,7 +154,7 @@
 			// Only include devices that are on the whitelist and have versions defined.
 			if foundVersions, ok := whiteList[dev.ID]; ok && (len(foundVersions) > 0) {
 				versionSet := util.NewStringSet(dev.VersionIDs)
-				reqVersions := util.NewStringSet(foundVersions)
+				reqVersions := util.NewStringSet(filterVersions(foundVersions, minAPIVersion, maxAPIVersion))
 				whiteListVersions := versionSet.Intersect(reqVersions).Keys()
 				ignoredVersions := versionSet.Complement(reqVersions).Keys()
 				sort.Strings(whiteListVersions)
@@ -171,6 +174,21 @@
 	return ret, ignored, nil
 }
 
+// filterVersions returns the elements in versionIDs where minVersion <= element <= maxVersion.
+func filterVersions(versionIDs []string, minVersion, maxVersion int) []string {
+	ret := make([]string, 0, len(versionIDs))
+	for _, versionID := range versionIDs {
+		id, err := strconv.Atoi(versionID)
+		if err != nil {
+			sklog.Fatalf("Error parsing version id '%s': %s", versionID, err)
+		}
+		if (id >= minVersion) && (id <= maxVersion) {
+			ret = append(ret, versionID)
+		}
+	}
+	return ret
+}
+
 // runTests runs the given apk on the given list of devices.
 func runTests(apk_path string, devices, ignoredDevices []*tsuite.DeviceVersions, client *http.Client, dryRun bool) error {
 	// Get the model-version we want to test. Assume on average each model has 5 supported versions.
diff --git a/tools/skqp/README.md b/tools/skqp/README.md
index 91d818e..da8f9ef 100644
--- a/tools/skqp/README.md
+++ b/tools/skqp/README.md
@@ -40,23 +40,31 @@
         cd skia
         git checkout origin/skqp/dev  # or whatever release tag you need
 
-3.  Download dependencies, the model, and configure the build.  (If you want to
-    test another architecture, replace `arm` with `x86`, `x64`, or `arm64`.)
+3.  Download dependencies and the model:
 
         python tools/skqp/download_model
         python tools/skqp/setup_resources
         python tools/git-sync-deps
-        python tools/skqp/generate_gn_args out/skqp-arm "$ANDROID_NDK" arm
+
+4.  Configure the build:
+
+        python tools/skqp/generate_gn_args out/skqp-arm "$ANDROID_NDK" \
+               --arch arm \
+               --api_level 26
         bin/gn gen out/skqp-arm
 
-4.  Build, install, and run.
+    If you want to test another architecture, replace `arm` with `x86`, `x64`
+    or `arm64`. Run 'python tools/skqp/generate_gn_args -h' for
+    all options.
+
+5.  Build, install, and run.
 
         platform_tools/android/bin/android_build_app -C out/skqp-arm skqp
         adb install -r out/skqp-arm/skqp.apk
         adb logcat -c
         adb shell am instrument -w org.skia.skqp/android.support.test.runner.AndroidJUnitRunner
 
-5.  Monitor the output with:
+6.  Monitor the output with:
 
         adb logcat org.skia.skqp skia "*:S"
 
@@ -65,7 +73,7 @@
         01-23 15:22:12.688 27158 27173 I org.skia.skqp:
         output written to "/storage/emulated/0/Android/data/org.skia.skqp/files/output"
 
-6.  Retrieve and view the report with:
+7.  Retrieve and view the report with:
 
         OUTPUT_LOCATION="/storage/emulated/0/Android/data/org.skia.skqp/files/output"
         adb pull $OUTPUT_LOCATION /tmp/
diff --git a/tools/skqp/generate_gn_args b/tools/skqp/generate_gn_args
index c527208..6a5c974 100755
--- a/tools/skqp/generate_gn_args
+++ b/tools/skqp/generate_gn_args
@@ -4,6 +4,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import argparse
 import os
 import sys
 
@@ -11,7 +12,7 @@
 target_cpu                       = "{arch}"
 is_debug                         = false
 ndk                              = "{ndk}"
-ndk_api                          = 26
+ndk_api                          = {api_level}
 skia_enable_fontmgr_empty        = true
 skia_enable_pdf                  = false
 skia_skqp_global_error_tolerance = 4
@@ -22,27 +23,38 @@
 skia_use_lua                     = false
 skia_use_piex                    = false
 skia_use_skcms                   = false
+skia_skqp_enable_driver_correctness_workarounds = {enable_workarounds}
 '''
 
-def make_args_gn(out_dir, ndk, arch):
+def parse_args():
+    parser = argparse.ArgumentParser(description='Generate args.gn file.')
+    parser.add_argument('target_build_dir')
+    parser.add_argument('android_ndk_dir' )
+    parser.add_argument('--arch',  metavar='architecture', default='arm',
+        help='defaults to "arm", valid values: "arm" "arm64" "x86" "x64"')
+    parser.add_argument('--api_level', type=int, metavar='api_level',
+        default=26, help='android API level, defaults to 26')
+    parser.add_argument('--enable_workarounds', default=False,
+        action='store_true', help="enable GPU work-arounds, defaults to false")
+
+    # parse the args and convert enable_workarounds to string.
+    args = parser.parse_args()
+    args.enable_workarounds =  'true' if args.enable_workarounds else 'false'
+    return args
+
+def make_args_gn(out_dir, ndk, arch, api_level, enable_workarounds):
     if not os.path.exists(out_dir):
         os.makedirs(out_dir)
     with open(os.path.join(out_dir, 'args.gn'), 'w') as o:
-        o.write(fmt.format(ndk=os.path.abspath(ndk), arch=arch))
-
-def usage():
-    sys.stderr.write(
-            'Usage:\n' +
-            '  {} TARGET_BUILD_DIR ANDROID_NDK_DIR ARCHITECTURE\n\n'.format(sys.argv[0]) +
-            'ARCHITECTURE should be "arm" "arm64" "x86" or "x64"\n\n')
-    exit(1)
+        o.write(fmt.format(ndk=os.path.abspath(ndk),
+                           arch=arch,
+                           api_level=api_level,
+                           enable_workarounds=enable_workarounds))
 
 if __name__ == '__main__':
-    if len(sys.argv) != 4:
-        usage()
-    build, android_ndk, arch = sys.argv[1:4]
-    if len(build) == 0 or len(arch) == 0 or not os.path.isdir(android_ndk):
-        usage()
-    make_args_gn(build, android_ndk, arch)
-
-
+    args = parse_args()
+    make_args_gn(args.target_build_dir,
+                 args.android_ndk_dir,
+                 args.arch,
+                 args.api_level,
+                 args.enable_workarounds)