[flutter_releases] Flutter 1.22.2 framework cherrypicks (#68135)

* [flutter_tools] support Android Studio 4.1 on Windows (#67992)

Android Studio 4.1 moved the location of the .home file on Windows which is used to located the install directory. This functionality is important because it is how we locate and discover the Android SDK functionality, as well as the appropriate JRE.

fixes #67986

* [gestures] make stylus pointer types use touch pan/drag slop (#67885)

* Update engine cherrypicks

* pin customer_testing and add back windows to cirrus

Co-authored-by: Jonah Williams <jonahwilliams@google.com>
diff --git a/.cirrus.yml b/.cirrus.yml
index 73ed9ae..e2206e0 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -231,6 +231,7 @@
       script:
         - rm -rf bin/cache/pkg/tests
         - git clone https://github.com/flutter/tests.git bin/cache/pkg/tests
+        - (cd bin/cache/pkg/tests; git checkout f1c35d57db5f0c1dd31ae3e0f73a18891343cd60)
         - dart --enable-asserts dev/customer_testing/run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
 
     # firebase_test_lab_tests are linux-only
@@ -347,6 +348,20 @@
         CPU: 4
         MEMORY: 6G
 
+    - name: customer_testing-windows
+      environment:
+        # As of December 2019, the customer_testing-windows shard got faster with more CPUs up to 4
+        # CPUs (which requires >=4G RAM), and needed at least 2G of RAM to not run out of memory.
+        CPU: 4
+        MEMORY: 4G
+      script:
+        - CMD /S /C "IF EXIST "bin\cache\pkg\tests\" RMDIR /S /Q bin\cache\pkg\tests"
+        - git clone https://github.com/flutter/tests.git bin\cache\pkg\tests
+        - cd bin\cache\pkg\tests
+        - git checkout f1c35d57db5f0c1dd31ae3e0f73a18891343cd60
+        - cd ..\..\..\..
+        - dart --enable-asserts dev\customer_testing\run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
+
 # MACOS SHARDS
 # Mac doesn't use caches because they apparently take longer to populate and save
 # than just fetching the data in the first place.
@@ -473,6 +488,7 @@
         - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
         - rm -rf bin/cache/pkg/tests
         - git clone https://github.com/flutter/tests.git bin/cache/pkg/tests
+        - (cd bin/cache/pkg/tests; git checkout f1c35d57db5f0c1dd31ae3e0f73a18891343cd60)
         - dart --enable-asserts dev/customer_testing/run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
 
     - name: deploy_gallery-macos # linux- and macos- only
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index ee5d620..596deba 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-75bef9f6c8ac2ed4e1e04cdfcd88b177d9f1850d
+b8752bbfff0419c8bf616b602bc59fd28f6a3d1b
diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart
index f96d4a5..1709a15 100644
--- a/packages/flutter/lib/src/gestures/events.dart
+++ b/packages/flutter/lib/src/gestures/events.dart
@@ -2228,9 +2228,9 @@
 double computeHitSlop(PointerDeviceKind kind) {
   switch (kind) {
     case PointerDeviceKind.mouse:
+      return kPrecisePointerHitSlop;
     case PointerDeviceKind.stylus:
     case PointerDeviceKind.invertedStylus:
-      return kPrecisePointerHitSlop;
     case PointerDeviceKind.unknown:
     case PointerDeviceKind.touch:
       return kTouchSlop;
@@ -2241,9 +2241,9 @@
 double computePanSlop(PointerDeviceKind kind) {
   switch (kind) {
     case PointerDeviceKind.mouse:
+      return kPrecisePointerPanSlop;
     case PointerDeviceKind.stylus:
     case PointerDeviceKind.invertedStylus:
-      return kPrecisePointerPanSlop;
     case PointerDeviceKind.unknown:
     case PointerDeviceKind.touch:
       return kPanSlop;
@@ -2254,9 +2254,9 @@
 double computeScaleSlop(PointerDeviceKind kind) {
   switch (kind) {
     case PointerDeviceKind.mouse:
+      return kPrecisePointerScaleSlop;
     case PointerDeviceKind.stylus:
     case PointerDeviceKind.invertedStylus:
-      return kPrecisePointerScaleSlop;
     case PointerDeviceKind.unknown:
     case PointerDeviceKind.touch:
       return kScaleSlop;
diff --git a/packages/flutter/test/gestures/events_test.dart b/packages/flutter/test/gestures/events_test.dart
index 9064371..26bf386 100644
--- a/packages/flutter/test/gestures/events_test.dart
+++ b/packages/flutter/test/gestures/events_test.dart
@@ -40,20 +40,20 @@
 
   test('computed hit slop values are based on pointer device kind', () {
     expect(computeHitSlop(PointerDeviceKind.mouse), kPrecisePointerHitSlop);
-    expect(computeHitSlop(PointerDeviceKind.stylus), kPrecisePointerHitSlop);
-    expect(computeHitSlop(PointerDeviceKind.invertedStylus), kPrecisePointerHitSlop);
+    expect(computeHitSlop(PointerDeviceKind.stylus), kTouchSlop);
+    expect(computeHitSlop(PointerDeviceKind.invertedStylus), kTouchSlop);
     expect(computeHitSlop(PointerDeviceKind.touch), kTouchSlop);
     expect(computeHitSlop(PointerDeviceKind.unknown), kTouchSlop);
 
     expect(computePanSlop(PointerDeviceKind.mouse), kPrecisePointerPanSlop);
-    expect(computePanSlop(PointerDeviceKind.stylus), kPrecisePointerPanSlop);
-    expect(computePanSlop(PointerDeviceKind.invertedStylus), kPrecisePointerPanSlop);
+    expect(computePanSlop(PointerDeviceKind.stylus), kPanSlop);
+    expect(computePanSlop(PointerDeviceKind.invertedStylus), kPanSlop);
     expect(computePanSlop(PointerDeviceKind.touch), kPanSlop);
     expect(computePanSlop(PointerDeviceKind.unknown), kPanSlop);
 
     expect(computeScaleSlop(PointerDeviceKind.mouse), kPrecisePointerScaleSlop);
-    expect(computeScaleSlop(PointerDeviceKind.stylus), kPrecisePointerScaleSlop);
-    expect(computeScaleSlop(PointerDeviceKind.invertedStylus), kPrecisePointerScaleSlop);
+    expect(computeScaleSlop(PointerDeviceKind.stylus), kScaleSlop);
+    expect(computeScaleSlop(PointerDeviceKind.invertedStylus), kScaleSlop);
     expect(computeScaleSlop(PointerDeviceKind.touch), kScaleSlop);
     expect(computeScaleSlop(PointerDeviceKind.unknown), kScaleSlop);
   });
diff --git a/packages/flutter_tools/lib/src/android/android_studio.dart b/packages/flutter_tools/lib/src/android/android_studio.dart
index eb07945..a7f6540 100644
--- a/packages/flutter_tools/lib/src/android/android_studio.dart
+++ b/packages/flutter_tools/lib/src/android/android_studio.dart
@@ -260,6 +260,29 @@
         }
       }
     }
+    // 4.1 has a different location for AndroidStudio installs on Windows.
+    if (globals.platform.isWindows) {
+      final File homeDot = globals.fs.file(globals.fs.path.join(
+        globals.platform.environment['LOCALAPPDATA'],
+        'Google',
+        'AndroidStudio4.1',
+        '.home',
+      ));
+      if (homeDot.existsSync()) {
+        final String installPath = homeDot.readAsStringSync();
+        if (globals.fs.isDirectorySync(installPath)) {
+          final AndroidStudio studio = AndroidStudio(
+            installPath,
+            version: Version(4, 1, 0),
+            studioAppName: 'Android Studio 4.1',
+          );
+          if (studio != null && !_hasStudioAt(studio.directory, newerThan: studio.version)) {
+            studios.removeWhere((AndroidStudio other) => other.directory == studio.directory);
+            studios.add(studio);
+          }
+        }
+      }
+    }
 
     final String configuredStudioDir = globals.config.getValue('android-studio-dir') as String;
     if (configuredStudioDir != null && !_hasStudioAt(configuredStudioDir)) {
diff --git a/packages/flutter_tools/test/general.shard/android/android_studio_test.dart b/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
index 0041995..d4bd7a2 100644
--- a/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
@@ -6,6 +6,7 @@
 import 'package:flutter_tools/src/android/android_studio.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/platform.dart';
+import 'package:flutter_tools/src/base/version.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:flutter_tools/src/ios/plist_parser.dart';
 import 'package:mockito/mockito.dart';
@@ -33,6 +34,13 @@
   environment: <String, String>{'HOME': homeLinux},
 );
 
+final Platform windowsPlatform = FakePlatform(
+  operatingSystem: 'windows',
+  environment: <String, String>{
+    'LOCALAPPDATA': 'C:\\Users\\Dash\\AppData\\Local',
+  }
+);
+
 class MockPlistUtils extends Mock implements PlistParser {}
 
 Platform macPlatform() {
@@ -177,4 +185,28 @@
       PlistParser: () => plistUtils,
     });
   });
+
+  FileSystem windowsFileSystem;
+
+  setUp(() {
+    windowsFileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
+  });
+
+  testUsingContext('Can discover Android Studio 4.1 location on Windows', () {
+    windowsFileSystem.file('C:\\Users\\Dash\\AppData\\Local\\Google\\AndroidStudio4.1\\.home')
+      ..createSync(recursive: true)
+      ..writeAsStringSync('C:\\Program Files\\AndroidStudio');
+    windowsFileSystem
+      .directory('C:\\Program Files\\AndroidStudio')
+      .createSync(recursive: true);
+
+    final AndroidStudio studio = AndroidStudio.allInstalled().single;
+
+    expect(studio.version, Version(4, 1, 0));
+    expect(studio.studioAppName, 'Android Studio 4.1');
+  }, overrides: <Type, Generator>{
+    Platform: () => windowsPlatform,
+    FileSystem: () => windowsFileSystem,
+    ProcessManager: () => FakeProcessManager.any(),
+  });
 }