Replace jarsigner with apksigner (#8154)

diff --git a/dev/bots/README.md b/dev/bots/README.md
index c6047b5..3d3fa79 100644
--- a/dev/bots/README.md
+++ b/dev/bots/README.md
@@ -102,7 +102,7 @@
    The following packages are currently installed:
    * Android SDK Tools
    * Android SDK platform-tools
-   * Android SDK Build-tools 23.0.1
+   * Android SDK Build-tools 24.0.3
    * Android 6.0 (API 23)
      * SDK Platform 23
    * Extras
diff --git a/dev/bots/VERSION_LINUX_SDK b/dev/bots/VERSION_LINUX_SDK
index d24f5c1..9106828 100644
--- a/dev/bots/VERSION_LINUX_SDK
+++ b/dev/bots/VERSION_LINUX_SDK
@@ -1 +1 @@
-0d320c50b0ed188c7e1182388e2beb623a1d307d
+efeebca78800d6855e15a22c6087a54766d1d4e9
diff --git a/dev/bots/VERSION_MACOSX_SDK b/dev/bots/VERSION_MACOSX_SDK
index 2441d72..12fc3d7 100644
--- a/dev/bots/VERSION_MACOSX_SDK
+++ b/dev/bots/VERSION_MACOSX_SDK
@@ -1 +1 @@
-fa5ea0ca1e0c7c2e40914f3202c7545de4dbca9c
+7eb88931c39c05a3b140da769e67c216d45db2b9
diff --git a/dev/bots/VERSION_WIN_SDK b/dev/bots/VERSION_WIN_SDK
index 0ca540a..e63ec1f 100644
--- a/dev/bots/VERSION_WIN_SDK
+++ b/dev/bots/VERSION_WIN_SDK
@@ -1 +1 @@
-e5715e2cc0d5644a241a4b3281bfada92bc145c2
+4b0d8fa0dcacd537330149332a28e033edfd3ca8
diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index ac5d5d6..c703c56 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -24,6 +24,7 @@
 // $ANDROID_HOME/build-tools/22.0.1/aapt
 // $ANDROID_HOME/build-tools/23.0.2/aapt
 // $ANDROID_HOME/build-tools/24.0.0-preview/aapt
+// $ANDROID_HOME/build-tools/25.0.2/apksigner
 
 // $ANDROID_HOME/platforms/android-22/android.jar
 // $ANDROID_HOME/platforms/android-23/android.jar
@@ -225,6 +226,8 @@
 
   String get zipalignPath => getBuildToolsPath('zipalign');
 
+  String get apksignerPath => getBuildToolsPath('apksigner');
+
   List<String> validateSdkWellFormed() {
     if (_exists(androidJarPath) != null)
       return <String>[_exists(androidJarPath)];
@@ -238,6 +241,9 @@
     if (_canRun(zipalignPath) != null)
       return <String>[_canRun(zipalignPath)];
 
+    if (_canRun(apksignerPath) != null)
+      return <String>[_canRun(apksignerPath) + '\napksigner requires Android SDK Build Tools 24.0.3 or newer.'];
+
     return <String>[];
   }
 
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 2ad9b4d..40210d2 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import '../base/io.dart';
-import '../base/os.dart';
 import '../base/platform.dart';
 import '../base/process_manager.dart';
 import '../doctor.dart';
@@ -63,11 +62,11 @@
       }
 
       List<String> validationResult = androidSdk.validateSdkWellFormed();
-      // Empty result means SDK is well formated.
 
       if (validationResult.isEmpty) {
+        // Empty result means SDK is well formatted.
+        // The SDK also requires a valid Java JDK installation.
         const String _kJdkDownload = 'https://www.oracle.com/technetwork/java/javase/downloads/';
-
         String javaVersion;
 
         try {
@@ -82,27 +81,20 @@
         } catch (error) {
         }
 
-        if (javaVersion != null) {
-          messages.add(new ValidationMessage(javaVersion));
-
-          if (os.which('jarsigner') == null) {
-            messages.add(new ValidationMessage.error(
-              'The jarsigner utility was not found; this is used to build Android APKs. You may need to install\n'
-              'or re-install the Java JDK: $_kJdkDownload.'
-            ));
-          } else {
-            type = ValidationType.installed;
-          }
-        } else {
+        if (javaVersion == null) {
           messages.add(new ValidationMessage.error(
-            'No Java Development Kit (JDK) found; you can download the JDK from $_kJdkDownload.'
+              'No Java Development Kit (JDK) found; you can download the JDK from $_kJdkDownload.'
           ));
+        } else {
+          type = ValidationType.installed;
         }
       } else {
         messages.addAll(validationResult.map((String message) {
           return new ValidationMessage.error(message);
         }));
-        messages.add(new ValidationMessage('Try re-installing or updating your Android SDK.'));
+        messages.add(new ValidationMessage(
+          'Try re-installing or updating your Android SDK,\n'
+          'visit https://flutter.io/setup/#android-setup for detailed instructions.'));
       }
     }
 
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index 19b74d4..cea8dc7 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -10,7 +10,6 @@
 import '../base/common.dart';
 import '../base/file_system.dart';
 import '../base/logger.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/process_manager.dart';
 import '../base/utils.dart';
@@ -68,14 +67,14 @@
   File _aapt;
   File _dx;
   File _zipalign;
-  File _jarsigner;
+  File _apksigner;
 
   _ApkBuilder(this.sdk) {
     _androidJar = fs.file(sdk.androidJarPath);
     _aapt = fs.file(sdk.aaptPath);
     _dx = fs.file(sdk.dxPath);
     _zipalign = fs.file(sdk.zipalignPath);
-    _jarsigner = os.which('jarsigner');
+    _apksigner = fs.file(sdk.apksignerPath);
   }
 
   String checkDependencies() {
@@ -87,10 +86,8 @@
       return 'Cannot find dx at ${_dx.path}';
     if (!processManager.canRun(_zipalign.path))
       return 'Cannot find zipalign at ${_zipalign.path}';
-    if (_jarsigner == null)
-      return 'Cannot find jarsigner in PATH.';
-    if (!_jarsigner.existsSync())
-      return 'Cannot find jarsigner at ${_jarsigner.path}';
+    if (!processManager.canRun(_apksigner.path))
+      return 'Cannot find apksigner at ${_apksigner.path}';
     return null;
   }
 
@@ -123,15 +120,13 @@
   }
 
   void sign(File keystore, String keystorePassword, String keyAlias, String keyPassword, File outputApk) {
-    assert(_jarsigner != null);
-    runCheckedSync(<String>[_jarsigner.path,
-      '-keystore', keystore.path,
-      '-storepass', keystorePassword,
-      '-keypass', keyPassword,
-      '-digestalg', 'SHA1',
-      '-sigalg', 'MD5withRSA',
+    assert(_apksigner != null);
+    runCheckedSync(<String>[_apksigner.path, 'sign',
+      '--ks', keystore.path,
+      '--ks-key-alias', keyAlias,
+      '--ks-pass', 'pass:$keystorePassword',
+      '--key-pass', 'pass:$keyPassword',
       outputApk.path,
-      keyAlias,
     ]);
   }
 
@@ -371,15 +366,14 @@
       unalignedApk, components.manifest, assetBuilder.directory,
       artifactBuilder.directory, components.resources, buildMode
     );
-
-    int signResult = _signApk(builder, components, unalignedApk, keystore, buildMode);
-    if (signResult != 0)
-      return signResult;
-
     File finalApk = fs.file(outputFile);
     ensureDirectoryExists(finalApk.path);
     builder.align(unalignedApk, finalApk);
 
+    int signResult = _signApk(builder, components, finalApk, keystore, buildMode);
+    if (signResult != 0)
+      return signResult;
+
     printTrace('calculateSha: $outputFile');
     File apkShaFile = fs.file('$outputFile.sha1');
     apkShaFile.writeAsStringSync(calculateSha(finalApk));