Refactor android module to remove the need for a context.

Android module was using a context even though it was not doing anything
in the cleanup. Removing the context allows to pass android as a regular
dependency in a dynamic way.

This also uses android licenses from cipd instead of creating the files
at runtime to remove non necessary interations of recipes with configs.

Change-Id: I972832e870967e6944f5558a130f1b17177d3392
Bug: https://github.com/flutter/flutter/issues/65187
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/6280
Commit-Queue: Godofredo Contreras <godofredoc@google.com>
Reviewed-by: Tong Wu <wutong@google.com>
diff --git a/recipe_modules/android_sdk/api.py b/recipe_modules/android_sdk/api.py
index 4a501b0..50bdb40 100644
--- a/recipe_modules/android_sdk/api.py
+++ b/recipe_modules/android_sdk/api.py
@@ -11,67 +11,54 @@
   Expects the android29 cache to be mounted on the swarming bot.
   """
 
-  def install(self):
-    """Installs Android SDK in cache."""
+  def install(self, sdk_root, env, env_prefixes):
+    """Installs Android SDK in cache.
+
+    Args:
+      sdk_root(Path): The path to install the different android packages.
+      env(dict): Current environment variables.
+      env_prefixes(dict):  Current environment prefixes variables.
+    """
     with self.m.step.nest('download Android SDK components'):
       self.m.cipd.ensure(
-          self._root().join('tools'),
+          sdk_root.join('tools'),
           self.m.cipd.EnsureFile().add_package(
               'flutter/android/sdk/tools/${platform}',
               'version:26.1.1',
           ),
       )
       self.m.cipd.ensure(
-          self._root().join('platform-tools'),
+          sdk_root.join('platform-tools'),
           self.m.cipd.EnsureFile().add_package(
               'flutter/android/sdk/platform-tools/${platform}',
               'version:29.0.2',
           ),
       )
       self.m.cipd.ensure(
-          self._root().join('platforms'),
+          sdk_root.join('platforms'),
           self.m.cipd.EnsureFile().add_package(
               'flutter/android/sdk/platforms',
               'version:29r1',
           ),
       )
       self.m.cipd.ensure(
-          self._root().join('build-tools'),
+          sdk_root.join('build-tools'),
           self.m.cipd.EnsureFile().add_package(
               'flutter/android/sdk/build-tools/${platform}',
               'version:29.0.1',
           ),
       )
-
-    with self.m.step.nest('add Android SDK licenses'):
-      self.m.file.ensure_directory('mkdir licenses',
-                                   self._root().join('licenses'))
-      self.m.file.write_text(
-          'android sdk license',
-          self._root().join('licenses', 'android-sdk-license'),
-          str(self.m.properties['android_sdk_license']),
-      )
-      self.m.file.write_text(
-          'android sdk preview license',
-          self._root().join('licenses', 'android-sdk-preview-license'),
-          str(self.m.properties['android_sdk_preview_license']),
+      self.m.cipd.ensure(
+          sdk_root.join('licenses'),
+          self.m.cipd.EnsureFile().add_package(
+              'flutter_internal/android/sdk/licenses',
+              'latest',
+          ),
       )
 
-  @contextmanager
-  def context(self):
-    """Yields a context that contains Android SDK environment.
-
-    Must call api.android_sdk.install() first.
-    """
-    with self.m.context(
-        env={'ANDROID_SDK_ROOT': self._root()},
-        env_prefixes={
-            'PATH': [
-                self._root().join('platform-tools'),
-                self._root().join('tools')
-            ]
-        }):
-      yield
-
-  def _root(self):
-    return self.m.path['cache'].join('android29')
+    # Setup environment variables
+    env['ANDROID_SDK_ROOT'] = sdk_root
+    paths = env_prefixes.get('PATH', [])
+    paths.append(sdk_root.join('platform-tools'))
+    paths.append(sdk_root.join('tools'))
+    env_prefixes['PATH'] = paths
diff --git a/recipe_modules/android_sdk/examples/full.expected/demo.json b/recipe_modules/android_sdk/examples/full.expected/demo.json
index 95f8a93..9af710c 100644
--- a/recipe_modules/android_sdk/examples/full.expected/demo.json
+++ b/recipe_modules/android_sdk/examples/full.expected/demo.json
@@ -120,63 +120,32 @@
     ]
   },
   {
-    "cmd": [],
-    "name": "add Android SDK licenses"
-  },
-  {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/android29/licenses"
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android29/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
     ],
-    "infra_step": true,
-    "name": "add Android SDK licenses.mkdir licenses",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_hash",
-      "[CACHE]/android29/licenses/android-sdk-license"
-    ],
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk license",
+    "name": "download Android SDK components.ensure_installed (5)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-license@android_sdk_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-license@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_preview_hash",
-      "[CACHE]/android29/licenses/android-sdk-preview-license"
-    ],
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk preview license",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-preview-license@android_sdk_preview_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-preview-license@@@"
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
     ]
   },
   {
diff --git a/recipe_modules/android_sdk/examples/full.py b/recipe_modules/android_sdk/examples/full.py
index fa1eaf3..fa8ad7e 100644
--- a/recipe_modules/android_sdk/examples/full.py
+++ b/recipe_modules/android_sdk/examples/full.py
@@ -4,22 +4,25 @@
 
 DEPS = [
     'android_sdk',
+    'recipe_engine/context',
+    'recipe_engine/path',
     'recipe_engine/properties',
     'recipe_engine/step',
 ]
 
 
 def RunSteps(api):
-  api.android_sdk.install()
-  with api.android_sdk.context():
+  env = {}
+  env_prefixes = {}
+  root = api.path['cache'].join('android29')
+  api.android_sdk.install(
+      sdk_root=root,
+      env=env,
+      env_prefixes=env_prefixes
+  )
+  with api.context(env=env, env_prefixes=env_prefixes):
     api.step('adb devices -l', cmd=['adb', 'devices', '-l'])
 
 
 def GenTests(api):
-  yield (api.test(
-      'demo',
-      api.properties(
-          android_sdk_license='android_sdk_hash',
-          android_sdk_preview_license='android_sdk_preview_hash',
-      ),
-  ))
+  yield (api.test('demo',))
diff --git a/recipe_modules/flutter_deps/__init__.py b/recipe_modules/flutter_deps/__init__.py
index 425a4f5..ec31588 100644
--- a/recipe_modules/flutter_deps/__init__.py
+++ b/recipe_modules/flutter_deps/__init__.py
@@ -1,4 +1,5 @@
 DEPS = [
+    'flutter/android_sdk',
     'recipe_engine/cipd',
     'recipe_engine/context',
     'recipe_engine/file',
diff --git a/recipe_modules/flutter_deps/api.py b/recipe_modules/flutter_deps/api.py
index 145bf60..81f44a2 100644
--- a/recipe_modules/flutter_deps/api.py
+++ b/recipe_modules/flutter_deps/api.py
@@ -21,7 +21,8 @@
     available_deps = {
         'open_jdk': self.open_jdk, 'goldctl': self.goldctl,
         'chrome_and_driver': self.chrome_and_driver, 'go_sdk': self.go_sdk,
-        'dashing': self.dashing, 'vpython': self.vpython
+        'dashing': self.dashing, 'vpython': self.vpython,
+        'android_sdk': self.android_sdk
     }
     for dep in deps:
       dep_funct = available_deps.get(dep.get('dependency'))
@@ -138,3 +139,9 @@
     paths = env_prefixes.get('PATH', [])
     paths.append(vpython_path)
     env_prefixes['PATH'] = paths
+
+  def android_sdk(self, env, env_prefixes, version):
+    """Installs android sdk."""
+    version = version or '29.0.2'
+    root_path = self.m.path['cache'].join('android')
+    self.m.android_sdk.install(root_path, env, env_prefixes)
diff --git a/recipe_modules/flutter_deps/examples/full.expected/basic.json b/recipe_modules/flutter_deps/examples/full.expected/basic.json
index 9c8e07a..7a71197 100644
--- a/recipe_modules/flutter_deps/examples/full.expected/basic.json
+++ b/recipe_modules/flutter_deps/examples/full.expected/basic.json
@@ -328,6 +328,155 @@
     ]
   },
   {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
     "name": "$result"
   }
 ]
\ No newline at end of file
diff --git a/recipe_modules/flutter_deps/examples/full.expected/goldTryjob.json b/recipe_modules/flutter_deps/examples/full.expected/goldTryjob.json
index 9c8e07a..7a71197 100644
--- a/recipe_modules/flutter_deps/examples/full.expected/goldTryjob.json
+++ b/recipe_modules/flutter_deps/examples/full.expected/goldTryjob.json
@@ -328,6 +328,155 @@
     ]
   },
   {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
     "name": "$result"
   }
 ]
\ No newline at end of file
diff --git a/recipe_modules/flutter_deps/examples/full.py b/recipe_modules/flutter_deps/examples/full.py
index 47f3f16..b6fca85 100644
--- a/recipe_modules/flutter_deps/examples/full.py
+++ b/recipe_modules/flutter_deps/examples/full.py
@@ -43,6 +43,7 @@
     api.flutter_deps.required_deps(
         env, env_prefixes, [{'dependency': 'does_not_exist'}]
     )
+  api.flutter_deps.android_sdk(env, env_prefixes, '')
 
 
 def GenTests(api):
diff --git a/recipes/devicelab.expected/android_defines_test.json b/recipes/devicelab.expected/android_defines_test.json
index 786cae7..f251f47 100644
--- a/recipes/devicelab.expected/android_defines_test.json
+++ b/recipes/devicelab.expected/android_defines_test.json
@@ -155,7 +155,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/tools",
+      "[CACHE]/android/tools",
       "-ensure-file",
       "flutter/android/sdk/tools/${platform} version:26.1.1",
       "-max-threads",
@@ -195,7 +195,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platform-tools",
+      "[CACHE]/android/platform-tools",
       "-ensure-file",
       "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
       "-max-threads",
@@ -235,7 +235,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platforms",
+      "[CACHE]/android/platforms",
       "-ensure-file",
       "flutter/android/sdk/platforms version:29r1",
       "-max-threads",
@@ -275,7 +275,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/build-tools",
+      "[CACHE]/android/build-tools",
       "-ensure-file",
       "flutter/android/sdk/build-tools/${platform} version:29.0.1",
       "-max-threads",
@@ -311,20 +311,17 @@
     ]
   },
   {
-    "cmd": [],
-    "name": "add Android SDK licenses"
-  },
-  {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/android29/licenses"
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
     ],
     "cwd": "[START_DIR]/flutter/dev/devicelab",
     "env": {
@@ -337,70 +334,20 @@
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
       ]
     },
-    "infra_step": true,
-    "name": "add Android SDK licenses.mkdir licenses",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_hash",
-      "[CACHE]/android29/licenses/android-sdk-license"
-    ],
-    "cwd": "[START_DIR]/flutter/dev/devicelab",
-    "env": {
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "PUB_CACHE": "[CACHE]/.pub-cache"
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk license",
+    "name": "download Android SDK components.ensure_installed (5)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-license@android_sdk_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-license@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_preview_hash",
-      "[CACHE]/android29/licenses/android-sdk-preview-license"
-    ],
-    "cwd": "[START_DIR]/flutter/dev/devicelab",
-    "env": {
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "PUB_CACHE": "[CACHE]/.pub-cache"
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk preview license",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-preview-license@android_sdk_preview_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-preview-license@@@"
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
     ]
   },
   {
@@ -412,14 +359,16 @@
     ],
     "cwd": "[START_DIR]/flutter/dev/devicelab",
     "env": {
-      "ANDROID_SDK_ROOT": "[CACHE]/android29",
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
       "PUB_CACHE": "[CACHE]/.pub-cache"
     },
     "env_prefixes": {
       "PATH": [
-        "[CACHE]/android29/platform-tools",
-        "[CACHE]/android29/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
       ]
diff --git a/recipes/devicelab.expected/flavors_test.json b/recipes/devicelab.expected/flavors_test.json
index a55486f..bc91c31 100644
--- a/recipes/devicelab.expected/flavors_test.json
+++ b/recipes/devicelab.expected/flavors_test.json
@@ -155,7 +155,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/tools",
+      "[CACHE]/android/tools",
       "-ensure-file",
       "flutter/android/sdk/tools/${platform} version:26.1.1",
       "-max-threads",
@@ -195,7 +195,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platform-tools",
+      "[CACHE]/android/platform-tools",
       "-ensure-file",
       "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
       "-max-threads",
@@ -235,7 +235,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platforms",
+      "[CACHE]/android/platforms",
       "-ensure-file",
       "flutter/android/sdk/platforms version:29r1",
       "-max-threads",
@@ -275,7 +275,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/build-tools",
+      "[CACHE]/android/build-tools",
       "-ensure-file",
       "flutter/android/sdk/build-tools/${platform} version:29.0.1",
       "-max-threads",
@@ -311,20 +311,17 @@
     ]
   },
   {
-    "cmd": [],
-    "name": "add Android SDK licenses"
-  },
-  {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/android29/licenses"
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
     ],
     "cwd": "[START_DIR]/flutter/dev/devicelab",
     "env": {
@@ -337,70 +334,20 @@
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
       ]
     },
-    "infra_step": true,
-    "name": "add Android SDK licenses.mkdir licenses",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_hash",
-      "[CACHE]/android29/licenses/android-sdk-license"
-    ],
-    "cwd": "[START_DIR]/flutter/dev/devicelab",
-    "env": {
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "PUB_CACHE": "[CACHE]/.pub-cache"
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk license",
+    "name": "download Android SDK components.ensure_installed (5)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-license@android_sdk_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-license@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "android_sdk_preview_hash",
-      "[CACHE]/android29/licenses/android-sdk-preview-license"
-    ],
-    "cwd": "[START_DIR]/flutter/dev/devicelab",
-    "env": {
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "PUB_CACHE": "[CACHE]/.pub-cache"
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk preview license",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-preview-license@android_sdk_preview_hash@@@",
-      "@@@STEP_LOG_END@android-sdk-preview-license@@@"
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
     ]
   },
   {
@@ -412,14 +359,16 @@
     ],
     "cwd": "[START_DIR]/flutter/dev/devicelab",
     "env": {
-      "ANDROID_SDK_ROOT": "[CACHE]/android29",
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
       "PUB_CACHE": "[CACHE]/.pub-cache"
     },
     "env_prefixes": {
       "PATH": [
-        "[CACHE]/android29/platform-tools",
-        "[CACHE]/android29/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
       ]
diff --git a/recipes/devicelab.py b/recipes/devicelab.py
index 0f6dae7..ca99af9 100644
--- a/recipes/devicelab.py
+++ b/recipes/devicelab.py
@@ -6,7 +6,7 @@
 
 DEPS = [
     'depot_tools/git',
-    'flutter/android_sdk',
+    'flutter/flutter_deps',
     'flutter/repo_util',
     'flutter/yaml',
     'recipe_engine/context',
@@ -48,9 +48,9 @@
   sub_jobs = []
   with api.context(env=env, env_prefixes=env_prefixes, cwd=devicelab_path):
     # Reads the manifest.
-    result = api.yaml.read('read manifest',
-                           devicelab_path.join('manifest.yaml'),
-                           api.json.output())
+    result = api.yaml.read(
+        'read manifest', devicelab_path.join('manifest.yaml'), api.json.output()
+    )
     manifest = result.json.output
     for task_name, task_body in manifest['tasks'].iteritems():
       # Example first capability values: linux/android, mac/ios.
@@ -115,17 +115,15 @@
     # Runs a task.
     sdk = first_capability.split('/')[1]
     if sdk == 'android':
-      run_android_task(api, task_name)
+      api.flutter_deps.android_sdk(env, env_prefixes, '')
+      with api.context(env=env, env_prefixes=env_prefixes):
+        api.step(
+            'run %s' % task_name, ['dart', 'bin/run.dart', '-t', task_name]
+        )
     elif sdk == 'ios':
       run_ios_task(api, task_name)
 
 
-def run_android_task(api, task_name):
-  api.android_sdk.install()
-  with api.android_sdk.context():
-    api.step('run %s' % task_name, ['dart', 'bin/run.dart', '-t', task_name])
-
-
 def run_ios_task(api, task_name):
   api.step('unlock login keychain', ['unlock_login_keychain.sh'])
   # See go/googler-flutter-signing about how to renew the Apple development
@@ -167,7 +165,8 @@
       "schedule", api.properties(role="scheduler"),
       api.repo_util.flutter_environment_data(),
       api.step_data('read manifest.parse', api.json.output(sample_manifest)),
-      api.job.mock_collect(["fake-task-id"], "collect jobs"))
+      api.job.mock_collect(["fake-task-id"], "collect jobs")
+  )
 
 
 def gen_worker_tests(api):
@@ -199,8 +198,10 @@
         api.properties(
             role="worker",
             name=task_name,
-            first_capability=(sample_manifest["tasks"][task_name]
-                              ["required_agent_capabilities"][0]),
+            first_capability=(
+                sample_manifest["tasks"][task_name]
+                ["required_agent_capabilities"][0]
+            ),
             android_sdk_license='android_sdk_hash',
             android_sdk_preview_license='android_sdk_preview_hash',
         ),
diff --git a/recipes/flutter/flutter_drone.expected/android_sdk.json b/recipes/flutter/flutter_drone.expected/android_sdk.json
index 5cdcbdf..01f94d9 100644
--- a/recipes/flutter/flutter_drone.expected/android_sdk.json
+++ b/recipes/flutter/flutter_drone.expected/android_sdk.json
@@ -216,60 +216,6 @@
     ]
   },
   {
-    "cmd": [
-      "flutter",
-      "doctor"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "flutter doctor"
-  },
-  {
-    "cmd": [
-      "flutter",
-      "update-packages"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "download dependencies"
-  },
-  {
     "cmd": [],
     "name": "download Android SDK components"
   },
@@ -278,7 +224,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/tools",
+      "[CACHE]/android/tools",
       "-ensure-file",
       "flutter/android/sdk/tools/${platform} version:26.1.1",
       "-max-threads",
@@ -286,26 +232,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -327,7 +253,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platform-tools",
+      "[CACHE]/android/platform-tools",
       "-ensure-file",
       "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
       "-max-threads",
@@ -335,26 +261,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (2)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -376,7 +282,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platforms",
+      "[CACHE]/android/platforms",
       "-ensure-file",
       "flutter/android/sdk/platforms version:29r1",
       "-max-threads",
@@ -384,26 +290,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (3)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -425,7 +311,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/build-tools",
+      "[CACHE]/android/build-tools",
       "-ensure-file",
       "flutter/android/sdk/build-tools/${platform} version:29.0.1",
       "-max-threads",
@@ -433,26 +319,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (4)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -470,133 +336,42 @@
     ]
   },
   {
-    "cmd": [],
-    "name": "add Android SDK licenses"
-  },
-  {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/android29/licenses"
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.mkdir licenses",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "cde",
-      "[CACHE]/android29/licenses/android-sdk-license"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk license",
+    "name": "download Android SDK components.ensure_installed (5)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-license@cde@@@",
-      "@@@STEP_LOG_END@android-sdk-license@@@"
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
     ]
   },
   {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "abc",
-      "[CACHE]/android29/licenses/android-sdk-preview-license"
+      "flutter",
+      "doctor"
     ],
     "cwd": "[START_DIR]/flutter",
     "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk preview license",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-preview-license@abc@@@",
-      "@@@STEP_LOG_END@android-sdk-preview-license@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "dart",
-      "[START_DIR]/flutter/dev/bots/test.dart"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "ANDROID_SDK_ROOT": "[CACHE]/android29",
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
       "CHROME_NO_SANDBOX": "true",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
@@ -613,13 +388,75 @@
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
         "[CACHE]/java/bin",
-        "[CACHE]/android29/platform-tools",
-        "[CACHE]/android29/tools",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
       ]
     },
     "name": "run test.dart for None shard and subshard None"
diff --git a/recipes/flutter/flutter_drone.expected/no_requirements.json b/recipes/flutter/flutter_drone.expected/no_requirements.json
index 1fe0470..01f94d9 100644
--- a/recipes/flutter/flutter_drone.expected/no_requirements.json
+++ b/recipes/flutter/flutter_drone.expected/no_requirements.json
@@ -216,66 +216,162 @@
     ]
   },
   {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
     "cmd": [
       "flutter",
       "doctor"
     ],
     "cwd": "[START_DIR]/flutter",
     "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "flutter doctor"
-  },
-  {
-    "cmd": [
-      "flutter",
-      "update-packages"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "download dependencies"
-  },
-  {
-    "cmd": [
-      "dart",
-      "[START_DIR]/flutter/dev/bots/test.dart"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
       "CHROME_NO_SANDBOX": "true",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
@@ -292,11 +388,75 @@
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
         "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
       ]
     },
     "name": "run test.dart for None shard and subshard None"
diff --git a/recipes/flutter/flutter_drone.expected/xcode.json b/recipes/flutter/flutter_drone.expected/xcode.json
new file mode 100644
index 0000000..01f94d9
--- /dev/null
+++ b/recipes/flutter/flutter_drone.expected/xcode.json
@@ -0,0 +1,467 @@
+[
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+      "--path",
+      "[START_DIR]/flutter",
+      "--url",
+      "https://chromium.googlesource.com/external/github.com/flutter/flutter"
+    ],
+    "name": "git setup"
+  },
+  {
+    "cmd": [
+      "git",
+      "fetch",
+      "origin",
+      "master",
+      "--recurse-submodules",
+      "--progress",
+      "--tags"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+    },
+    "infra_step": true,
+    "name": "git fetch"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "-f",
+      "FETCH_HEAD"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "git checkout"
+  },
+  {
+    "cmd": [
+      "git",
+      "rev-parse",
+      "HEAD"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "read revision",
+    "~followup_annotations": [
+      "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@",
+      "@@@SET_BUILD_PROPERTY@got_revision@\"deadbeef\"@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "clean",
+      "-f",
+      "-d",
+      "-x"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "git clean"
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "sync"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "submodule sync"
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "update",
+      "--init",
+      "--recursive"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "submodule update"
+  },
+  {
+    "cmd": [],
+    "name": "Chrome and driver dependency"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/chrome/chrome",
+      "-ensure-file",
+      "flutter_internal/browsers/chrome/${platform} latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Chrome and driver dependency.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/browsers/chrome/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/chrome/drivers",
+      "-ensure-file",
+      "flutter_internal/browser-drivers/chrome/${platform} latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Chrome and driver dependency.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/browser-drivers/chrome/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "OpenJDK dependency"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/java",
+      "-ensure-file",
+      "flutter_internal/java/openjdk/${platform} version:1.8.0u202-b08",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "OpenJDK dependency.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:1.8.0u20\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/java/openjdk/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "Download goldctl"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/gold",
+      "-ensure-file",
+      "skia/tools/goldctl/${platform} git_revision:b57f561ad4ad624bd399b8b7b500aa1955276d41",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Download goldctl.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-git_revision:b57\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"skia/tools/goldctl/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "flutter",
+      "doctor"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "run test.dart for None shard and subshard None"
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipes/flutter/flutter_drone.py b/recipes/flutter/flutter_drone.py
index bf96a64..288745f 100644
--- a/recipes/flutter/flutter_drone.py
+++ b/recipes/flutter/flutter_drone.py
@@ -9,6 +9,7 @@
 import re
 
 DEPS = [
+    'depot_tools/osx_sdk',
     'flutter/android_sdk',
     'flutter/json_util',
     'flutter/repo_util',
@@ -32,12 +33,6 @@
     )
 
 
-def RunWithAndroid(api, env, env_prefixes, checkout_path):
-  api.android_sdk.install()
-  with api.android_sdk.context():
-    RunShard(api, env, env_prefixes, checkout_path)
-
-
 def RunSteps(api):
   checkout_path = api.path['start_dir'].join('flutter')
   api.repo_util.checkout(
@@ -53,7 +48,7 @@
 
   env, env_prefixes = api.repo_util.flutter_environment(checkout_path)
   deps = [{'dependency': 'chrome_and_driver'}, {'dependency': 'open_jdk'},
-          {'dependency': 'goldctl'}]
+          {'dependency': 'goldctl'}, {'dependency': 'android_sdk'}]
   api.flutter_deps.required_deps(env, env_prefixes, deps)
   # Add shard and subshard.
   env['SHARD'] = api.properties.get('shard')
@@ -61,8 +56,9 @@
   with api.context(env=env, env_prefixes=env_prefixes, cwd=checkout_path):
     api.step('flutter doctor', ['flutter', 'doctor'])
     api.step('download dependencies', ['flutter', 'update-packages'])
-    if 'android_sdk' in api.properties.get('dependencies', []):
-      RunWithAndroid(api, env, env_prefixes, checkout_path)
+    if 'xcode' in api.properties.get('dependencies', []):
+      with api.osx_sdk('ios'):
+        RunShard(api, env, env_prefixes, checkout_path)
     else:
       RunShard(api, env, env_prefixes, checkout_path)
 
@@ -81,3 +77,7 @@
           android_sdk_license='cde'
       )
   )
+  yield api.test(
+      'xcode', api.repo_util.flutter_environment_data(),
+      api.properties(dependencies=['xcode'],)
+  )
diff --git a/recipes/flutter/flutter_drone_1_21_0.expected/android_sdk.json b/recipes/flutter/flutter_drone_1_21_0.expected/android_sdk.json
index 5cdcbdf..01f94d9 100644
--- a/recipes/flutter/flutter_drone_1_21_0.expected/android_sdk.json
+++ b/recipes/flutter/flutter_drone_1_21_0.expected/android_sdk.json
@@ -216,60 +216,6 @@
     ]
   },
   {
-    "cmd": [
-      "flutter",
-      "doctor"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "flutter doctor"
-  },
-  {
-    "cmd": [
-      "flutter",
-      "update-packages"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "download dependencies"
-  },
-  {
     "cmd": [],
     "name": "download Android SDK components"
   },
@@ -278,7 +224,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/tools",
+      "[CACHE]/android/tools",
       "-ensure-file",
       "flutter/android/sdk/tools/${platform} version:26.1.1",
       "-max-threads",
@@ -286,26 +232,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -327,7 +253,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platform-tools",
+      "[CACHE]/android/platform-tools",
       "-ensure-file",
       "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
       "-max-threads",
@@ -335,26 +261,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (2)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -376,7 +282,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/platforms",
+      "[CACHE]/android/platforms",
       "-ensure-file",
       "flutter/android/sdk/platforms version:29r1",
       "-max-threads",
@@ -384,26 +290,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (3)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -425,7 +311,7 @@
       "cipd",
       "ensure",
       "-root",
-      "[CACHE]/android29/build-tools",
+      "[CACHE]/android/build-tools",
       "-ensure-file",
       "flutter/android/sdk/build-tools/${platform} version:29.0.1",
       "-max-threads",
@@ -433,26 +319,6 @@
       "-json-output",
       "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
     "name": "download Android SDK components.ensure_installed (4)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
@@ -470,133 +336,42 @@
     ]
   },
   {
-    "cmd": [],
-    "name": "add Android SDK licenses"
-  },
-  {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/android29/licenses"
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
     ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.mkdir licenses",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "cde",
-      "[CACHE]/android29/licenses/android-sdk-license"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk license",
+    "name": "download Android SDK components.ensure_installed (5)",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-license@cde@@@",
-      "@@@STEP_LOG_END@android-sdk-license@@@"
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
     ]
   },
   {
     "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "copy",
-      "abc",
-      "[CACHE]/android29/licenses/android-sdk-preview-license"
+      "flutter",
+      "doctor"
     ],
     "cwd": "[START_DIR]/flutter",
     "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "infra_step": true,
-    "name": "add Android SDK licenses.android sdk preview license",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@android-sdk-preview-license@abc@@@",
-      "@@@STEP_LOG_END@android-sdk-preview-license@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "dart",
-      "[START_DIR]/flutter/dev/bots/test.dart"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "ANDROID_SDK_ROOT": "[CACHE]/android29",
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
       "CHROME_NO_SANDBOX": "true",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
@@ -613,13 +388,75 @@
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
         "[CACHE]/java/bin",
-        "[CACHE]/android29/platform-tools",
-        "[CACHE]/android29/tools",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
       ]
     },
     "name": "run test.dart for None shard and subshard None"
diff --git a/recipes/flutter/flutter_drone_1_21_0.expected/no_requirements.json b/recipes/flutter/flutter_drone_1_21_0.expected/no_requirements.json
index 1fe0470..01f94d9 100644
--- a/recipes/flutter/flutter_drone_1_21_0.expected/no_requirements.json
+++ b/recipes/flutter/flutter_drone_1_21_0.expected/no_requirements.json
@@ -216,66 +216,162 @@
     ]
   },
   {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
     "cmd": [
       "flutter",
       "doctor"
     ],
     "cwd": "[START_DIR]/flutter",
     "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "flutter doctor"
-  },
-  {
-    "cmd": [
-      "flutter",
-      "update-packages"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
-      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
-      "CHROME_NO_SANDBOX": "true",
-      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
-      "GOLDCTL": "[CACHE]/gold/goldctl",
-      "JAVA_HOME": "[CACHE]/java",
-      "PUB_CACHE": "[CACHE]/.pub-cache",
-      "SHARD": null,
-      "SUBSHARD": null
-    },
-    "env_prefixes": {
-      "PATH": [
-        "[START_DIR]/flutter/bin",
-        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
-        "[CACHE]/chrome/chrome",
-        "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
-      ]
-    },
-    "name": "download dependencies"
-  },
-  {
-    "cmd": [
-      "dart",
-      "[START_DIR]/flutter/dev/bots/test.dart"
-    ],
-    "cwd": "[START_DIR]/flutter",
-    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
       "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
       "CHROME_NO_SANDBOX": "true",
       "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
@@ -292,11 +388,75 @@
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
         "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
         "[START_DIR]/flutter/bin",
         "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
         "[CACHE]/chrome/chrome",
         "[CACHE]/chrome/drivers",
-        "[CACHE]/java/bin"
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
       ]
     },
     "name": "run test.dart for None shard and subshard None"
diff --git a/recipes/flutter/flutter_drone_1_21_0.expected/xcode.json b/recipes/flutter/flutter_drone_1_21_0.expected/xcode.json
new file mode 100644
index 0000000..01f94d9
--- /dev/null
+++ b/recipes/flutter/flutter_drone_1_21_0.expected/xcode.json
@@ -0,0 +1,467 @@
+[
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+      "--path",
+      "[START_DIR]/flutter",
+      "--url",
+      "https://chromium.googlesource.com/external/github.com/flutter/flutter"
+    ],
+    "name": "git setup"
+  },
+  {
+    "cmd": [
+      "git",
+      "fetch",
+      "origin",
+      "master",
+      "--recurse-submodules",
+      "--progress",
+      "--tags"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+    },
+    "infra_step": true,
+    "name": "git fetch"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "-f",
+      "FETCH_HEAD"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "git checkout"
+  },
+  {
+    "cmd": [
+      "git",
+      "rev-parse",
+      "HEAD"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "read revision",
+    "~followup_annotations": [
+      "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@",
+      "@@@SET_BUILD_PROPERTY@got_revision@\"deadbeef\"@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "clean",
+      "-f",
+      "-d",
+      "-x"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "git clean"
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "sync"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "submodule sync"
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "update",
+      "--init",
+      "--recursive"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "infra_step": true,
+    "name": "submodule update"
+  },
+  {
+    "cmd": [],
+    "name": "Chrome and driver dependency"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/chrome/chrome",
+      "-ensure-file",
+      "flutter_internal/browsers/chrome/${platform} latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Chrome and driver dependency.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/browsers/chrome/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/chrome/drivers",
+      "-ensure-file",
+      "flutter_internal/browser-drivers/chrome/${platform} latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Chrome and driver dependency.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/browser-drivers/chrome/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "OpenJDK dependency"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/java",
+      "-ensure-file",
+      "flutter_internal/java/openjdk/${platform} version:1.8.0u202-b08",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "OpenJDK dependency.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:1.8.0u20\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/java/openjdk/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "Download goldctl"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/gold",
+      "-ensure-file",
+      "skia/tools/goldctl/${platform} git_revision:b57f561ad4ad624bd399b8b7b500aa1955276d41",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "Download goldctl.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-git_revision:b57\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"skia/tools/goldctl/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "download Android SDK components"
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/tools",
+      "-ensure-file",
+      "flutter/android/sdk/tools/${platform} version:26.1.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:26.1.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platform-tools",
+      "-ensure-file",
+      "flutter/android/sdk/platform-tools/${platform} version:29.0.2",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.2--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platform-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/platforms",
+      "-ensure-file",
+      "flutter/android/sdk/platforms version:29r1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (3)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29r1----\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/platforms\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/build-tools",
+      "-ensure-file",
+      "flutter/android/sdk/build-tools/${platform} version:29.0.1",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (4)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-version:29.0.1--\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter/android/sdk/build-tools/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[CACHE]/android/licenses",
+      "-ensure-file",
+      "flutter_internal/android/sdk/licenses latest",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "name": "download Android SDK components.ensure_installed (5)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"flutter_internal/android/sdk/licenses\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "flutter",
+      "doctor"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "flutter doctor"
+  },
+  {
+    "cmd": [
+      "flutter",
+      "update-packages"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "download dependencies"
+  },
+  {
+    "cmd": [
+      "dart",
+      "[START_DIR]/flutter/dev/bots/test.dart"
+    ],
+    "cwd": "[START_DIR]/flutter",
+    "env": {
+      "ANDROID_SDK_ROOT": "[CACHE]/android",
+      "CHROME_EXECUTABLE": "[CACHE]/chrome/chrome/chrome",
+      "CHROME_NO_SANDBOX": "true",
+      "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+      "GOLDCTL": "[CACHE]/gold/goldctl",
+      "JAVA_HOME": "[CACHE]/java",
+      "PUB_CACHE": "[CACHE]/.pub-cache",
+      "SHARD": null,
+      "SUBSHARD": null
+    },
+    "env_prefixes": {
+      "PATH": [
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools",
+        "[START_DIR]/flutter/bin",
+        "[START_DIR]/flutter/bin/cache/dart-sdk/bin",
+        "[CACHE]/chrome/chrome",
+        "[CACHE]/chrome/drivers",
+        "[CACHE]/java/bin",
+        "[CACHE]/android/platform-tools",
+        "[CACHE]/android/tools"
+      ]
+    },
+    "name": "run test.dart for None shard and subshard None"
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipes/flutter/flutter_drone_1_21_0.py b/recipes/flutter/flutter_drone_1_21_0.py
index 2a3e560..288745f 100644
--- a/recipes/flutter/flutter_drone_1_21_0.py
+++ b/recipes/flutter/flutter_drone_1_21_0.py
@@ -9,6 +9,7 @@
 import re
 
 DEPS = [
+    'depot_tools/osx_sdk',
     'flutter/android_sdk',
     'flutter/json_util',
     'flutter/repo_util',
@@ -32,12 +33,6 @@
     )
 
 
-def RunWithAndroid(api, env, env_prefixes, checkout_path):
-  api.android_sdk.install()
-  with api.android_sdk.context():
-    RunShard(api, env, env_prefixes, checkout_path)
-
-
 def RunSteps(api):
   checkout_path = api.path['start_dir'].join('flutter')
   api.repo_util.checkout(
@@ -52,17 +47,18 @@
     api.json_util.validate_json(checkout_path)
 
   env, env_prefixes = api.repo_util.flutter_environment(checkout_path)
-  api.flutter_deps.chrome_and_driver(env, env_prefixes, '')
-  api.flutter_deps.open_jdk(env, env_prefixes, '')
-  api.flutter_deps.goldctl(env, env_prefixes, '')
+  deps = [{'dependency': 'chrome_and_driver'}, {'dependency': 'open_jdk'},
+          {'dependency': 'goldctl'}, {'dependency': 'android_sdk'}]
+  api.flutter_deps.required_deps(env, env_prefixes, deps)
   # Add shard and subshard.
   env['SHARD'] = api.properties.get('shard')
   env['SUBSHARD'] = api.properties.get('subshard')
   with api.context(env=env, env_prefixes=env_prefixes, cwd=checkout_path):
     api.step('flutter doctor', ['flutter', 'doctor'])
     api.step('download dependencies', ['flutter', 'update-packages'])
-    if 'android_sdk' in api.properties.get('dependencies', []):
-      RunWithAndroid(api, env, env_prefixes, checkout_path)
+    if 'xcode' in api.properties.get('dependencies', []):
+      with api.osx_sdk('ios'):
+        RunShard(api, env, env_prefixes, checkout_path)
     else:
       RunShard(api, env, env_prefixes, checkout_path)
 
@@ -81,3 +77,7 @@
           android_sdk_license='cde'
       )
   )
+  yield api.test(
+      'xcode', api.repo_util.flutter_environment_data(),
+      api.properties(dependencies=['xcode'],)
+  )