improve progress display when running apps; speed up startup (#9475) * improve progress display when running apps; speed up startup * review comments
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 9bc7f22..c83ad4a 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -222,7 +222,7 @@ } @override - bool installApp(ApplicationPackage app) { + Future<bool> installApp(ApplicationPackage app) async { final AndroidApk apk = app; if (!fs.isFileSync(apk.apkPath)) { printError('"${apk.apkPath}" does not exist.'); @@ -233,16 +233,18 @@ return false; final Status status = logger.startProgress('Installing ${apk.apkPath}...', expectSlowOperation: true); - final String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', apk.apkPath])); + final RunResult installResult = await runCheckedAsync(adbCommandForDevice(<String>['install', '-r', apk.apkPath])); status.stop(); final RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true); - final String failure = failureExp.stringMatch(installOut); + final String failure = failureExp.stringMatch(installResult.stdout); if (failure != null) { printError('Package install error: $failure'); return false; } - runCheckedSync(adbCommandForDevice(<String>['shell', 'echo', '-n', _getSourceSha1(app), '>', _getDeviceSha1Path(app)])); + await runCheckedAsync(adbCommandForDevice(<String>[ + 'shell', 'echo', '-n', _getSourceSha1(app), '>', _getDeviceSha1Path(app) + ])); return true; } @@ -262,7 +264,7 @@ return true; } - bool _installLatestApp(ApplicationPackage package) { + Future<bool> _installLatestApp(ApplicationPackage package) async { final bool wasInstalled = isAppInstalled(package); if (wasInstalled) { if (isLatestBuildInstalled(package)) { @@ -271,7 +273,7 @@ } } printTrace('Installing APK.'); - if (!installApp(package)) { + if (!await installApp(package)) { printTrace('Warning: Failed to install APK.'); if (wasInstalled) { printStatus('Uninstalling old version...'); @@ -279,7 +281,7 @@ printError('Error: Uninstalling old version failed.'); return false; } - if (!installApp(package)) { + if (!await installApp(package)) { printError('Error: Failed to install APK again.'); return false; } @@ -325,7 +327,7 @@ printTrace("Stopping app '${package.name}' on $name."); await stopApp(package); - if (!_installLatestApp(package)) + if (!await _installLatestApp(package)) return new LaunchResult.failed(); final bool traceStartup = platformArgs['trace-startup'] ?? false;
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index a4e0942..b712bda 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -23,6 +23,8 @@ const String gradleAppOutV1 = 'android/app/build/outputs/apk/app-debug.apk'; const String gradleAppOutDirV1 = 'android/app/build/outputs/apk'; +String _cachedGradleAppOutDirV2; + enum FlutterPluginVersion { none, v1, @@ -54,7 +56,7 @@ return FlutterPluginVersion.none; } -String get gradleAppOut { +String getGradleAppOut() { switch (flutterPluginVersion) { case FlutterPluginVersion.none: // Fall through. Pretend we're v1, and just go with it. @@ -63,12 +65,18 @@ case FlutterPluginVersion.managed: // Fall through. The managed plugin matches plugin v2 for now. case FlutterPluginVersion.v2: - return '$gradleAppOutDirV2/app.apk'; + return '${getGradleAppOutDirV2()}/app.apk'; } return null; } -String get gradleAppOutDirV2 { +String getGradleAppOutDirV2() { + _cachedGradleAppOutDirV2 ??= _calculateGradleAppOutDirV2(); + return _cachedGradleAppOutDirV2; +} + +// Note: this call takes about a second to complete. +String _calculateGradleAppOutDirV2() { final String gradle = ensureGradle(); ensureLocalProperties(); try { @@ -224,7 +232,7 @@ if (exitcode != 0) throwToolExit('Gradle build failed: $exitcode', exitCode: exitcode); - final String buildDirectory = gradleAppOutDirV2; + final String buildDirectory = getGradleAppOutDirV2(); final String apkFilename = 'app-$buildModeName.apk'; final File apkFile = fs.file('$buildDirectory/$apkFilename'); // Copy the APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 0c4a9a3..52923ba 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -83,16 +83,16 @@ String apkPath; if (isProjectUsingGradle()) { - if (fs.file(gradleAppOut).existsSync()) { + if (fs.file(getGradleAppOut()).existsSync()) { // Grab information from the .apk. The gradle build script might alter // the application Id, so we need to look at what was actually built. - return new AndroidApk.fromApk(gradleAppOut); + return new AndroidApk.fromApk(getGradleAppOut()); } // The .apk hasn't been built yet, so we work with what we have. The run // command will grab a new AndroidApk after building, to get the updated // IDs. manifestPath = gradleManifestPath; - apkPath = gradleAppOut; + apkPath = getGradleAppOut(); } else { manifestPath = fs.path.join('android', 'AndroidManifest.xml'); apkPath = fs.path.join(getAndroidBuildDirectory(), 'app.apk');
diff --git a/packages/flutter_tools/lib/src/commands/install.dart b/packages/flutter_tools/lib/src/commands/install.dart index 30e71d4..063585e 100644 --- a/packages/flutter_tools/lib/src/commands/install.dart +++ b/packages/flutter_tools/lib/src/commands/install.dart
@@ -37,12 +37,12 @@ printStatus('Installing $package to $device...'); - if (!installApp(device, package)) + if (!await installApp(device, package)) throwToolExit('Install failed'); } } -bool installApp(Device device, ApplicationPackage package, { bool uninstall: true }) { +Future<bool> installApp(Device device, ApplicationPackage package, { bool uninstall: true }) async { if (package == null) return false;
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 7489153..9a76b7e 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -150,7 +150,7 @@ bool isLatestBuildInstalled(ApplicationPackage app); /// Install an app package on the current device - bool installApp(ApplicationPackage app); + Future<bool> installApp(ApplicationPackage app); /// Uninstall an app package from the current device bool uninstallApp(ApplicationPackage app);
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index 3984567..0c4ce20 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
@@ -49,7 +49,7 @@ bool isLatestBuildInstalled(ApplicationPackage app) => false; @override - bool installApp(ApplicationPackage app) => false; + Future<bool> installApp(ApplicationPackage app) => new Future<bool>.value(false); @override bool uninstallApp(ApplicationPackage app) => false;
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index f9cd43b..fb6bc3d 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -155,7 +155,7 @@ bool isLatestBuildInstalled(ApplicationPackage app) => false; @override - bool installApp(ApplicationPackage app) { + Future<bool> installApp(ApplicationPackage app) async { final IOSApp iosApp = app; final Directory bundle = fs.directory(iosApp.deviceBundlePath); if (!bundle.existsSync()) { @@ -197,8 +197,7 @@ bool applicationNeedsRebuild: false, }) async { if (!prebuiltApplication) { - // TODO(chinmaygarde): Use checked, mainPath, route. - // TODO(devoncarew): Handle startPaused, debugPort. + // TODO(chinmaygarde): Use mainPath, route. printTrace('Building ${app.name} for $id'); // Step 1: Build the precompiled/DBC application if necessary. @@ -210,7 +209,7 @@ return new LaunchResult.failed(); } } else { - if (!installApp(app)) + if (!await installApp(app)) return new LaunchResult.failed(); }
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index fbd99dd..6fd46b8 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -343,7 +343,7 @@ bool isLatestBuildInstalled(ApplicationPackage app) => false; @override - bool installApp(ApplicationPackage app) { + Future<bool> installApp(ApplicationPackage app) async { try { final IOSApp iosApp = app; SimControl.instance.install(id, iosApp.simulatorBundlePath); @@ -435,7 +435,7 @@ return new LaunchResult.failed(); } } else { - if (!installApp(app)) + if (!await installApp(app)) return new LaunchResult.failed(); }
diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index 4db138c..d114a7f 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart
@@ -53,6 +53,14 @@ } } + final String modeName = getModeName(debuggingOptions.buildMode); + if (mainPath == null) { + assert(prebuiltMode); + printStatus('Launching ${package.displayName} on ${device.name} in $modeName mode...'); + } else { + printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...'); + } + package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary); if (package == null) { @@ -72,14 +80,6 @@ await startEchoingDeviceLog(package); - final String modeName = getModeName(debuggingOptions.buildMode); - if (mainPath == null) { - assert(prebuiltMode); - printStatus('Launching ${package.displayName} on ${device.name} in $modeName mode...'); - } else { - printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...'); - } - _result = await device.startApp( package, debuggingOptions.buildMode,
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index be25e64..823ff7e 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -174,6 +174,9 @@ return 1; } + final String modeName = getModeName(debuggingOptions.buildMode); + printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...'); + package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary); if (package == null) { @@ -195,9 +198,6 @@ await startEchoingDeviceLog(package); - final String modeName = getModeName(debuggingOptions.buildMode); - printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...'); - // Start the application. final Future<LaunchResult> futureResult = device.startApp( package,