Commit f29dd4f9 authored by Devon Carew's avatar Devon Carew Committed by GitHub

improve progress display when running apps; speed up startup (#9475)

* improve progress display when running apps; speed up startup

* review comments
parent 35803c22
...@@ -222,7 +222,7 @@ class AndroidDevice extends Device { ...@@ -222,7 +222,7 @@ class AndroidDevice extends Device {
} }
@override @override
bool installApp(ApplicationPackage app) { Future<bool> installApp(ApplicationPackage app) async {
final AndroidApk apk = app; final AndroidApk apk = app;
if (!fs.isFileSync(apk.apkPath)) { if (!fs.isFileSync(apk.apkPath)) {
printError('"${apk.apkPath}" does not exist.'); printError('"${apk.apkPath}" does not exist.');
...@@ -233,16 +233,18 @@ class AndroidDevice extends Device { ...@@ -233,16 +233,18 @@ class AndroidDevice extends Device {
return false; return false;
final Status status = logger.startProgress('Installing ${apk.apkPath}...', expectSlowOperation: true); 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(); status.stop();
final RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true); 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) { if (failure != null) {
printError('Package install error: $failure'); printError('Package install error: $failure');
return false; 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; return true;
} }
...@@ -262,7 +264,7 @@ class AndroidDevice extends Device { ...@@ -262,7 +264,7 @@ class AndroidDevice extends Device {
return true; return true;
} }
bool _installLatestApp(ApplicationPackage package) { Future<bool> _installLatestApp(ApplicationPackage package) async {
final bool wasInstalled = isAppInstalled(package); final bool wasInstalled = isAppInstalled(package);
if (wasInstalled) { if (wasInstalled) {
if (isLatestBuildInstalled(package)) { if (isLatestBuildInstalled(package)) {
...@@ -271,7 +273,7 @@ class AndroidDevice extends Device { ...@@ -271,7 +273,7 @@ class AndroidDevice extends Device {
} }
} }
printTrace('Installing APK.'); printTrace('Installing APK.');
if (!installApp(package)) { if (!await installApp(package)) {
printTrace('Warning: Failed to install APK.'); printTrace('Warning: Failed to install APK.');
if (wasInstalled) { if (wasInstalled) {
printStatus('Uninstalling old version...'); printStatus('Uninstalling old version...');
...@@ -279,7 +281,7 @@ class AndroidDevice extends Device { ...@@ -279,7 +281,7 @@ class AndroidDevice extends Device {
printError('Error: Uninstalling old version failed.'); printError('Error: Uninstalling old version failed.');
return false; return false;
} }
if (!installApp(package)) { if (!await installApp(package)) {
printError('Error: Failed to install APK again.'); printError('Error: Failed to install APK again.');
return false; return false;
} }
...@@ -325,7 +327,7 @@ class AndroidDevice extends Device { ...@@ -325,7 +327,7 @@ class AndroidDevice extends Device {
printTrace("Stopping app '${package.name}' on $name."); printTrace("Stopping app '${package.name}' on $name.");
await stopApp(package); await stopApp(package);
if (!_installLatestApp(package)) if (!await _installLatestApp(package))
return new LaunchResult.failed(); return new LaunchResult.failed();
final bool traceStartup = platformArgs['trace-startup'] ?? false; final bool traceStartup = platformArgs['trace-startup'] ?? false;
......
...@@ -23,6 +23,8 @@ const String gradleManifestPath = 'android/app/src/main/AndroidManifest.xml'; ...@@ -23,6 +23,8 @@ const String gradleManifestPath = 'android/app/src/main/AndroidManifest.xml';
const String gradleAppOutV1 = 'android/app/build/outputs/apk/app-debug.apk'; const String gradleAppOutV1 = 'android/app/build/outputs/apk/app-debug.apk';
const String gradleAppOutDirV1 = 'android/app/build/outputs/apk'; const String gradleAppOutDirV1 = 'android/app/build/outputs/apk';
String _cachedGradleAppOutDirV2;
enum FlutterPluginVersion { enum FlutterPluginVersion {
none, none,
v1, v1,
...@@ -54,7 +56,7 @@ FlutterPluginVersion get flutterPluginVersion { ...@@ -54,7 +56,7 @@ FlutterPluginVersion get flutterPluginVersion {
return FlutterPluginVersion.none; return FlutterPluginVersion.none;
} }
String get gradleAppOut { String getGradleAppOut() {
switch (flutterPluginVersion) { switch (flutterPluginVersion) {
case FlutterPluginVersion.none: case FlutterPluginVersion.none:
// Fall through. Pretend we're v1, and just go with it. // Fall through. Pretend we're v1, and just go with it.
...@@ -63,12 +65,18 @@ String get gradleAppOut { ...@@ -63,12 +65,18 @@ String get gradleAppOut {
case FlutterPluginVersion.managed: case FlutterPluginVersion.managed:
// Fall through. The managed plugin matches plugin v2 for now. // Fall through. The managed plugin matches plugin v2 for now.
case FlutterPluginVersion.v2: case FlutterPluginVersion.v2:
return '$gradleAppOutDirV2/app.apk'; return '${getGradleAppOutDirV2()}/app.apk';
} }
return null; 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(); final String gradle = ensureGradle();
ensureLocalProperties(); ensureLocalProperties();
try { try {
...@@ -224,7 +232,7 @@ Future<Null> buildGradleProjectV2(String gradle, String buildModeName, String ta ...@@ -224,7 +232,7 @@ Future<Null> buildGradleProjectV2(String gradle, String buildModeName, String ta
if (exitcode != 0) if (exitcode != 0)
throwToolExit('Gradle build failed: $exitcode', exitCode: exitcode); throwToolExit('Gradle build failed: $exitcode', exitCode: exitcode);
final String buildDirectory = gradleAppOutDirV2; final String buildDirectory = getGradleAppOutDirV2();
final String apkFilename = 'app-$buildModeName.apk'; final String apkFilename = 'app-$buildModeName.apk';
final File apkFile = fs.file('$buildDirectory/$apkFilename'); final File apkFile = fs.file('$buildDirectory/$apkFilename');
// Copy the APK to app.apk, so `flutter run`, `flutter install`, etc. can find it. // Copy the APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
......
...@@ -83,16 +83,16 @@ class AndroidApk extends ApplicationPackage { ...@@ -83,16 +83,16 @@ class AndroidApk extends ApplicationPackage {
String apkPath; String apkPath;
if (isProjectUsingGradle()) { if (isProjectUsingGradle()) {
if (fs.file(gradleAppOut).existsSync()) { if (fs.file(getGradleAppOut()).existsSync()) {
// Grab information from the .apk. The gradle build script might alter // Grab information from the .apk. The gradle build script might alter
// the application Id, so we need to look at what was actually built. // 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 // 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 // command will grab a new AndroidApk after building, to get the updated
// IDs. // IDs.
manifestPath = gradleManifestPath; manifestPath = gradleManifestPath;
apkPath = gradleAppOut; apkPath = getGradleAppOut();
} else { } else {
manifestPath = fs.path.join('android', 'AndroidManifest.xml'); manifestPath = fs.path.join('android', 'AndroidManifest.xml');
apkPath = fs.path.join(getAndroidBuildDirectory(), 'app.apk'); apkPath = fs.path.join(getAndroidBuildDirectory(), 'app.apk');
......
...@@ -37,12 +37,12 @@ class InstallCommand extends FlutterCommand { ...@@ -37,12 +37,12 @@ class InstallCommand extends FlutterCommand {
printStatus('Installing $package to $device...'); printStatus('Installing $package to $device...');
if (!installApp(device, package)) if (!await installApp(device, package))
throwToolExit('Install failed'); 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) if (package == null)
return false; return false;
......
...@@ -150,7 +150,7 @@ abstract class Device { ...@@ -150,7 +150,7 @@ abstract class Device {
bool isLatestBuildInstalled(ApplicationPackage app); bool isLatestBuildInstalled(ApplicationPackage app);
/// Install an app package on the current device /// 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 /// Uninstall an app package from the current device
bool uninstallApp(ApplicationPackage app); bool uninstallApp(ApplicationPackage app);
......
...@@ -49,7 +49,7 @@ class FuchsiaDevice extends Device { ...@@ -49,7 +49,7 @@ class FuchsiaDevice extends Device {
bool isLatestBuildInstalled(ApplicationPackage app) => false; bool isLatestBuildInstalled(ApplicationPackage app) => false;
@override @override
bool installApp(ApplicationPackage app) => false; Future<bool> installApp(ApplicationPackage app) => new Future<bool>.value(false);
@override @override
bool uninstallApp(ApplicationPackage app) => false; bool uninstallApp(ApplicationPackage app) => false;
......
...@@ -155,7 +155,7 @@ class IOSDevice extends Device { ...@@ -155,7 +155,7 @@ class IOSDevice extends Device {
bool isLatestBuildInstalled(ApplicationPackage app) => false; bool isLatestBuildInstalled(ApplicationPackage app) => false;
@override @override
bool installApp(ApplicationPackage app) { Future<bool> installApp(ApplicationPackage app) async {
final IOSApp iosApp = app; final IOSApp iosApp = app;
final Directory bundle = fs.directory(iosApp.deviceBundlePath); final Directory bundle = fs.directory(iosApp.deviceBundlePath);
if (!bundle.existsSync()) { if (!bundle.existsSync()) {
...@@ -197,8 +197,7 @@ class IOSDevice extends Device { ...@@ -197,8 +197,7 @@ class IOSDevice extends Device {
bool applicationNeedsRebuild: false, bool applicationNeedsRebuild: false,
}) async { }) async {
if (!prebuiltApplication) { if (!prebuiltApplication) {
// TODO(chinmaygarde): Use checked, mainPath, route. // TODO(chinmaygarde): Use mainPath, route.
// TODO(devoncarew): Handle startPaused, debugPort.
printTrace('Building ${app.name} for $id'); printTrace('Building ${app.name} for $id');
// Step 1: Build the precompiled/DBC application if necessary. // Step 1: Build the precompiled/DBC application if necessary.
...@@ -210,7 +209,7 @@ class IOSDevice extends Device { ...@@ -210,7 +209,7 @@ class IOSDevice extends Device {
return new LaunchResult.failed(); return new LaunchResult.failed();
} }
} else { } else {
if (!installApp(app)) if (!await installApp(app))
return new LaunchResult.failed(); return new LaunchResult.failed();
} }
......
...@@ -343,7 +343,7 @@ class IOSSimulator extends Device { ...@@ -343,7 +343,7 @@ class IOSSimulator extends Device {
bool isLatestBuildInstalled(ApplicationPackage app) => false; bool isLatestBuildInstalled(ApplicationPackage app) => false;
@override @override
bool installApp(ApplicationPackage app) { Future<bool> installApp(ApplicationPackage app) async {
try { try {
final IOSApp iosApp = app; final IOSApp iosApp = app;
SimControl.instance.install(id, iosApp.simulatorBundlePath); SimControl.instance.install(id, iosApp.simulatorBundlePath);
...@@ -435,7 +435,7 @@ class IOSSimulator extends Device { ...@@ -435,7 +435,7 @@ class IOSSimulator extends Device {
return new LaunchResult.failed(); return new LaunchResult.failed();
} }
} else { } else {
if (!installApp(app)) if (!await installApp(app))
return new LaunchResult.failed(); return new LaunchResult.failed();
} }
......
...@@ -53,6 +53,14 @@ class ColdRunner extends ResidentRunner { ...@@ -53,6 +53,14 @@ class ColdRunner extends ResidentRunner {
} }
} }
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); package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary);
if (package == null) { if (package == null) {
...@@ -72,14 +80,6 @@ class ColdRunner extends ResidentRunner { ...@@ -72,14 +80,6 @@ class ColdRunner extends ResidentRunner {
await startEchoingDeviceLog(package); 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( _result = await device.startApp(
package, package,
debuggingOptions.buildMode, debuggingOptions.buildMode,
......
...@@ -174,6 +174,9 @@ class HotRunner extends ResidentRunner { ...@@ -174,6 +174,9 @@ class HotRunner extends ResidentRunner {
return 1; return 1;
} }
final String modeName = getModeName(debuggingOptions.buildMode);
printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...');
package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary); package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary);
if (package == null) { if (package == null) {
...@@ -195,9 +198,6 @@ class HotRunner extends ResidentRunner { ...@@ -195,9 +198,6 @@ class HotRunner extends ResidentRunner {
await startEchoingDeviceLog(package); await startEchoingDeviceLog(package);
final String modeName = getModeName(debuggingOptions.buildMode);
printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...');
// Start the application. // Start the application.
final Future<LaunchResult> futureResult = device.startApp( final Future<LaunchResult> futureResult = device.startApp(
package, package,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment