Add a devicelab task that generates sample app screenshots, etc (#10303)

diff --git a/dev/devicelab/bin/tasks/android_sample_catalog_generator.dart b/dev/devicelab/bin/tasks/android_sample_catalog_generator.dart
new file mode 100644
index 0000000..b9550b3
--- /dev/null
+++ b/dev/devicelab/bin/tasks/android_sample_catalog_generator.dart
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/tasks/sample_catalog_generator.dart';
+
+Future<Null> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.android;
+  await task(samplePageCatalogGenerator);
+}
diff --git a/dev/devicelab/bin/tasks/ios_sample_catalog_generator.dart b/dev/devicelab/bin/tasks/ios_sample_catalog_generator.dart
new file mode 100644
index 0000000..94f1464
--- /dev/null
+++ b/dev/devicelab/bin/tasks/ios_sample_catalog_generator.dart
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/tasks/sample_catalog_generator.dart';
+
+Future<Null> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.ios;
+  await task(samplePageCatalogGenerator);
+}
diff --git a/dev/devicelab/lib/tasks/sample_catalog_generator.dart b/dev/devicelab/lib/tasks/sample_catalog_generator.dart
new file mode 100644
index 0000000..d0ea57a
--- /dev/null
+++ b/dev/devicelab/lib/tasks/sample_catalog_generator.dart
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import '../framework/adb.dart';
+import '../framework/framework.dart';
+import '../framework/ios.dart';
+import '../framework/utils.dart';
+
+Future<TaskResult> samplePageCatalogGenerator() async {
+  final Device device = await devices.workingDevice;
+  await device.unlock();
+  final String deviceId = device.deviceId;
+
+  final Directory catalogDirectory = dir('${flutterDirectory.path}/examples/catalog');
+  await inDirectory(catalogDirectory, () async {
+    await flutter('packages', options: <String>['get']);
+
+    if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
+      await prepareProvisioningCertificates(catalogDirectory.path);
+      // This causes an Xcode project to be created.
+      await flutter('build', options: <String>['ios', '--profile']);
+    }
+
+    await dart(<String>['bin/sample_page.dart']);
+
+    await flutter('drive', options: <String>[
+      'test_driver/screenshot.dart',
+      '-d',
+      deviceId,
+    ]);
+  });
+
+  return new TaskResult.success(null);
+}
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index d98fa2a..914f4fa 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -171,6 +171,13 @@
     stage: devicelab
     required_agent_capabilities: ["has-android-device"]
 
+  android_sample_catalog_generator:
+    description: >
+      Builds sample catalog markdown pages and Android screenshots
+    stage: devicelab
+    required_agent_capabilities: ["has-android-device"]
+    flaky: true
+
   # iOS on-device tests
 
   channels_integration_test_ios:
@@ -240,6 +247,13 @@
     stage: devicelab_ios
     required_agent_capabilities: ["has-ios-device"]
 
+  ios_sample_catalog_generator:
+    description: >
+      Builds sample catalog markdown pages and iOS screenshots
+    stage: devicelab_ios
+    required_agent_capabilities: ["has-ios-device"]
+    flaky: true
+
   # Tests running on Windows host
 
   channels_integration_test_win: