[flutter_tool] Allow analytics without a terminal attached (#36208)

diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index 9b612e2..ebdc745 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -33,9 +33,6 @@
 
     return platform.environment['BOT'] == 'true'
 
-        // Non-interactive terminals are assumed to be bots.
-        || !io.stdout.hasTerminal
-
         // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
         || platform.environment['TRAVIS'] == 'true'
         || platform.environment['CONTINUOUS_INTEGRATION'] == 'true'
@@ -48,7 +45,8 @@
         || platform.environment.containsKey('CIRRUS_CI')
 
         // https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
-        || (platform.environment.containsKey('AWS_REGION') && platform.environment.containsKey('CODEBUILD_INITIATOR'))
+        || (platform.environment.containsKey('AWS_REGION') &&
+            platform.environment.containsKey('CODEBUILD_INITIATOR'))
 
         // https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-belowJenkinsSetEnvironmentVariables
         || platform.environment.containsKey('JENKINS_URL')
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index dc48eab..d39d4d1 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -13,6 +13,7 @@
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
+import '../base/io.dart' as io;
 import '../base/terminal.dart';
 import '../base/time.dart';
 import '../base/user_messages.dart';
@@ -424,6 +425,7 @@
           break;
       }
     }
+    additionalUsageValues[kCommandHasTerminal] = io.stdout.hasTerminal ? 'true' : 'false';
     flutterUsage.sendCommand(commandPath, parameters: additionalUsageValues);
 
     // Send timing.
diff --git a/packages/flutter_tools/lib/src/usage.dart b/packages/flutter_tools/lib/src/usage.dart
index 6ad484b..f68e4a1 100644
--- a/packages/flutter_tools/lib/src/usage.dart
+++ b/packages/flutter_tools/lib/src/usage.dart
@@ -49,12 +49,13 @@
 const String kCommandBuildBundleIsModule = 'cd25';
 
 const String kCommandResult = 'cd26';
+const String kCommandHasTerminal = 'cd31';
 
 const String reloadExceptionTargetPlatform = 'cd27';
 const String reloadExceptionSdkName = 'cd28';
 const String reloadExceptionEmulator = 'cd29';
 const String reloadExceptionFullRestart = 'cd30';
-// Next ID: cd31
+// Next ID: cd32
 
 Usage get flutterUsage => Usage.instance;
 
diff --git a/packages/flutter_tools/test/general.shard/base/utils_test.dart b/packages/flutter_tools/test/general.shard/base/utils_test.dart
index 097d72f..9046c5e 100644
--- a/packages/flutter_tools/test/general.shard/base/utils_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/utils_test.dart
@@ -42,11 +42,11 @@
         Platform: () => fakePlatform,
       });
 
-      testUsingContext('returns true for non-interactive terminals', () async {
+      testUsingContext('returns false with and without a terminal attached', () async {
         mockStdio.stdout.hasTerminal = true;
         expect(botDetector.isRunningOnBot, isFalse);
         mockStdio.stdout.hasTerminal = false;
-        expect(botDetector.isRunningOnBot, isTrue);
+        expect(botDetector.isRunningOnBot, isFalse);
       }, overrides: <Type, Generator>{
         Stdio: () => mockStdio,
         Platform: () => fakePlatform,
diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
index 86ee99d..e3502c4 100644
--- a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
@@ -62,11 +62,8 @@
 
       expect(
         verify(usage.sendCommand(captureAny,
-                parameters: captureAnyNamed('parameters'))).captured,
-        <dynamic>[
-          'dummy',
-          const <String, String>{'cd26': 'success'}
-        ],
+                parameters: captureAnyNamed('parameters'))).captured[1]['cd26'],
+        equals('success'),
       );
     },
     overrides: <Type, Generator>{
@@ -87,11 +84,8 @@
 
       expect(
         verify(usage.sendCommand(captureAny,
-                parameters: captureAnyNamed('parameters'))).captured,
-        <dynamic>[
-          'dummy',
-          const <String, String>{'cd26': 'warning'}
-        ],
+                parameters: captureAnyNamed('parameters'))).captured[1]['cd26'],
+        equals('warning'),
       );
     },
     overrides: <Type, Generator>{
@@ -114,11 +108,8 @@
       } on ToolExit {
         expect(
           verify(usage.sendCommand(captureAny,
-                  parameters: captureAnyNamed('parameters'))).captured,
-          <dynamic>[
-            'dummy',
-            const <String, String>{'cd26': 'fail'}
-          ],
+                  parameters: captureAnyNamed('parameters'))).captured[1]['cd26'],
+          equals('fail'),
         );
       }
     },
@@ -144,11 +135,8 @@
       } on ToolExit {
         expect(
           verify(usage.sendCommand(captureAny,
-                  parameters: captureAnyNamed('parameters'))).captured,
-          <dynamic>[
-            'dummy',
-            const <String, String>{'cd26': 'fail'}
-          ],
+                  parameters: captureAnyNamed('parameters'))).captured[1]['cd26'],
+          equals('fail'),
         );
       }
     },