Version 2.3.0-dev.0.2

* Cherry-pick d8a0d68bd66b388e4c5f6dc38f4fd940a4cb88bc to dev
* Cherry-pick 1ecedb23416943b13fd3f48a5d398f2cfa6dbee4 to dev
* Cherry-pick 2c304d997f08e9ba1d8d1af665522b31d695f19a to dev
* Cherry-pick 1f1592edce7122ff657d9538d58d9cce0cae46e6 to dev
* Cherry-pick cf4444b803a376bb1ad6442e1f09434a4d58167b to dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e6ff08..20cf64b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 2.3.0-dev.0.2
+
+* Cherry-pick d8a0d68bd66b388e4c5f6dc38f4fd940a4cb88bc to dev
+* Cherry-pick 1ecedb23416943b13fd3f48a5d398f2cfa6dbee4 to dev
+* Cherry-pick 2c304d997f08e9ba1d8d1af665522b31d695f19a to dev
+* Cherry-pick 1f1592edce7122ff657d9538d58d9cce0cae46e6 to dev
+* Cherry-pick cf4444b803a376bb1ad6442e1f09434a4d58167b to dev
+
 ## 2.3.0-dev.0.1
 
 * Cherry-pick 43eebea5a3715d7c3904cd85a35db5cffaae687e to dev
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index df6f051..29da5e8 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -71,6 +71,7 @@
     String manifestFile = newFile(filePath, content: '''
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
     <uses-feature android:name="android.software.home_screen" />
 </manifest>
 ''').path;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 6d2713d..0e565ab 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -364,9 +364,13 @@
   HintCode.UNUSED_LABEL,
   HintCode.UNUSED_LOCAL_VARIABLE,
   HintCode.UNUSED_SHOWN_NAME,
-  ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
-  ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE,
   ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE,
+  ManifestWarningCode.NON_RESIZABLE_ACTIVITY,
+  ManifestWarningCode.NO_TOUCHSCREEN_FEATURE,
+  ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE,
+  ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY,
+  ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE,
+  ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
   ParserErrorCode.ABSTRACT_CLASS_MEMBER,
   ParserErrorCode.ABSTRACT_ENUM,
   ParserErrorCode.ABSTRACT_STATIC_METHOD,
diff --git a/pkg/analyzer/lib/src/manifest/manifest_validator.dart b/pkg/analyzer/lib/src/manifest/manifest_validator.dart
index c83e616..3f2c5aa 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_validator.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_validator.dart
@@ -42,6 +42,7 @@
           manifest?.getElementsByTagName(USES_PERMISSION_TAG) ?? [];
       var activities = _findActivityElements(manifest);
 
+      _validateTouchScreenFeature(features, manifest, reporter);
       _validateFeatures(features, reporter);
       _validatePermissions(permissions, features, reporter);
       _validateActivities(activities, reporter);
@@ -50,6 +51,29 @@
   }
 
   /*
+   * Validate the presence/absence of the touchscreen feature tag.
+   */
+  _validateTouchScreenFeature(
+      List<Element> features, Element manifest, ErrorReporter reporter) {
+    var feature = features.firstWhere(
+        (element) =>
+            element.attributes[ANDROID_NAME] == HARDWARE_FEATURE_TOUCHSCREEN,
+        orElse: () => null);
+    if (feature != null) {
+      if (!feature.attributes.containsKey(ANDROID_REQUIRED)) {
+        _reportErrorForNode(reporter, feature, ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
+      } else if (feature.attributes[ANDROID_REQUIRED] == 'true') {
+        _reportErrorForNode(reporter, feature, ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE);
+      }
+    } else {
+      _reportErrorForNode(
+          reporter, manifest, null, ManifestWarningCode.NO_TOUCHSCREEN_FEATURE);
+    }
+  }
+
+  /*
    * Validate the `uses-feature` tags.
    */
   _validateFeatures(List<Element> features, ErrorReporter reporter) {
@@ -61,9 +85,9 @@
       if (!element.attributes.containsKey(ANDROID_REQUIRED)) {
         _reportErrorForNode(reporter, element, ANDROID_NAME,
             ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
-      } else if (element.attributes[ANDROID_REQUIRED] == true) {
+      } else if (element.attributes[ANDROID_REQUIRED] == 'true') {
         _reportErrorForNode(reporter, element, ANDROID_NAME,
-            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE);
       }
     });
   }
@@ -140,7 +164,8 @@
   void _reportErrorForNode(
       ErrorReporter reporter, Node node, dynamic key, ErrorCode errorCode,
       [List<Object> arguments]) {
-    FileSpan span = node.attributeValueSpans[key];
+    FileSpan span =
+        key == null ? node.sourceSpan : node.attributeValueSpans[key];
     reporter.reportErrorForOffset(
         errorCode, span.start.offset, span.length, arguments);
   }
diff --git a/pkg/analyzer/lib/src/manifest/manifest_values.dart b/pkg/analyzer/lib/src/manifest/manifest_values.dart
index db96a93..f44a4ba 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_values.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_values.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*
-*  The arritbute values to check for compatibiltiy with Chrome OS.
+*  The attribute values to check for compatibility with Chrome OS.
 *
 */
 
@@ -30,6 +30,8 @@
 
 const String HARDWARE_FEATURE_CAMERA = 'android.hardware.camera';
 
+const String HARDWARE_FEATURE_TOUCHSCREEN = 'android.hardware.touchscreen';
+
 const String HARDWARE_FEATURE_CAMERA_AUTOFOCUS =
     'android.hardware.camera.autofocus';
 
@@ -53,7 +55,6 @@
   HARDWARE_FEATURE_TELEPHONY,
   'android.hardware.telephony.cdma',
   'android.hardware.telephony.gsm',
-  'android.hardware.touchscreen',
   'android.hardware.type.automotive',
   'android.hardware.type.television',
   'android.hardware.usb.accessory',
diff --git a/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart b/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
index 8cd566c..c7c1504 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
@@ -15,11 +15,37 @@
    * A code indicating that a specified hardware feature is not supported on Chrome OS.
    */
   static const ManifestWarningCode UNSUPPORTED_CHROME_OS_HARDWARE =
-      const ManifestWarningCode('UNSUPPORTED_CHROME_OS_HARDWARE',
-          "This hardware feature is not supported on Chrome OS.",
+      const ManifestWarningCode(
+          'UNSUPPORTED_CHROME_OS_HARDWARE',
+          "This feature is not supported on Chrome OS. Try adding " +
+              "`android:required=\"false\"` for this feature.",
           correction:
-              "Try adding `android:required=\"false\"` for this hardware " +
-                  "feature.");
+              "Try adding `android:required=\"false\"` for this " + "feature.");
+
+  /**
+   * A code indicating that a specified feature is not supported on Chrome OS.
+   */
+  static const ManifestWarningCode UNSUPPORTED_CHROME_OS_FEATURE =
+      const ManifestWarningCode(
+          'UNSUPPORTED_CHROME_OS_FEATURE',
+          "This feature is not supported on Chrome OS. Try changing " +
+              "`android:required to \"false\"` for this feature.",
+          correction: "Try changing to `android:required=\"false\"` for this " +
+              "feature.");
+
+  /**
+   * A code indicating that the touchscreen feature is not specified in the
+   * manifest.
+   */
+  static const ManifestWarningCode NO_TOUCHSCREEN_FEATURE = const ManifestWarningCode(
+      'NO_TOUCHSCREEN_FEATURE',
+      "Explicitly set \"android.hardware.touchscreen\" to not required for Chrome OS. " +
+          "Consider adding " +
+          "<uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />" +
+          " to the manifest.",
+      correction: "Consider adding " +
+          "<uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />" +
+          " to the manifest.");
 
   /**
    * A code indicating that a specified permission is not supported on Chrome OS.
diff --git a/pkg/analyzer/test/src/manifest/manifest_validator_test.dart b/pkg/analyzer/test/src/manifest/manifest_validator_test.dart
index 1388f40..80f825a 100644
--- a/pkg/analyzer/test/src/manifest/manifest_validator_test.dart
+++ b/pkg/analyzer/test/src/manifest/manifest_validator_test.dart
@@ -51,15 +51,43 @@
     assertErrors('''
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
     <uses-feature android:name="android.software.home_screen" />
 </manifest>
 ''', [ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE]);
   }
 
+  test_noTouchScreen_error() {
+    assertErrors('''
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android">
+</manifest>
+''', [ManifestWarningCode.NO_TOUCHSCREEN_FEATURE]);
+  }
+
+  test_touchScreenNotSupported_error() {
+    assertErrors('''
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" android:required="true"/>
+</manifest>
+''', [ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE]);
+  }
+
+  test_featureNotSupported_error() {
+    assertErrors('''
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" />
+</manifest>
+''', [ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE]);
+  }
+
   test_cameraPermissions_error() {
     assertErrors('''
 <manifest
      xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
     <uses-permission android:name="android.permission.CAMERA" />
 </manifest>
 ''', [ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE]);
@@ -69,6 +97,7 @@
     assertErrors('''
 <manifest
      xmlns:android="http://schemas.android.com/apk/res/android">
+  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
   <application android:label="@string/app_name">
     <activity android:name="testActivity"
       android:screenOrientation="landscape"
@@ -83,11 +112,12 @@
     assertErrors('''
 <manifest
      xmlns:android="http://schemas.android.com/apk/res/android">
-   <application android:label="@string/app_name">
-  <activity android:name="testActivity"
-    android:resizeableActivity="false"
-    android:exported="false">
-  </activity>
+  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
+  <application android:label="@string/app_name">
+    <activity android:name="testActivity"
+      android:resizeableActivity="false"
+      android:exported="false">
+    </activity>
   </application>
 </manifest>
 ''', [ManifestWarningCode.NON_RESIZABLE_ACTIVITY]);
@@ -97,6 +127,7 @@
     assertErrors('''
 <manifest
      xmlns:android="http://schemas.android.com/apk/res/android">
+  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
   <activity android:name="testActivity"
     android:resizeableActivity="true"
     android:exported="false">
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 385f323..054521d 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -825,10 +825,8 @@
 </manifest>
 ''');
       await drive(manifestPath, options: filePath);
-      expect(
-          bulletToDash(outSink),
-          contains(
-              "warning - This hardware feature is not supported on Chrome OS"));
+      expect(bulletToDash(outSink),
+          contains("warning - This feature is not supported on Chrome OS"));
       expect(exitCode, 0);
     });
   }
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 8591d9c..39f7c88f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -1430,6 +1430,15 @@
                   throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
                       ".new(...)` to create a Dart object");
               }''', [runtimeModule, runtimeModule])));
+    } else if (classElem == _jsArray) {
+      // Provide access to the Array constructor property, so it works like
+      // other native types (rather than calling the Dart Object "constructor"
+      // above, which throws).
+      //
+      // This will become obsolete when
+      // https://github.com/dart-lang/sdk/issues/31003 is addressed.
+      jsMethods.add(JS.Method(
+          propertyName('constructor'), js.fun(r'function() { return []; }')));
     } else if (classElem.isEnum) {
       // Generate Enum.toString()
       var fields = classElem.fields.where((f) => f.type == type).toList();
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 1c88754..b6c1925 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1586,6 +1586,15 @@
                   throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
                       ".new(...)` to create a Dart object");
               }''', [runtimeModule, runtimeModule])));
+    } else if (c == _jsArrayClass) {
+      // Provide access to the Array constructor property, so it works like
+      // other native types (rather than calling the Dart Object "constructor"
+      // above, which throws).
+      //
+      // This will become obsolete when
+      // https://github.com/dart-lang/sdk/issues/31003 is addressed.
+      jsMethods.add(JS.Method(
+          propertyName('constructor'), js.fun(r'function() { return []; }')));
     }
 
     Set<Member> redirectingFactories;
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d0916b9..2d09c17 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -511,7 +511,7 @@
   // Load embedder specific bits and return.
   if (!VmService::Setup(
           Options::vm_service_server_ip(), Options::vm_service_server_port(),
-          Options::vm_service_dev_mode(), !Options::vm_service_auth_enabled(),
+          Options::vm_service_dev_mode(), Options::vm_service_auth_disabled(),
           Options::trace_loading(), Options::deterministic())) {
     *error = strdup(VmService::GetErrorMessage());
     return NULL;
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 414f309..8513fe3 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -34,16 +34,12 @@
 
 // As STRING_OPTIONS_LIST but for boolean valued options. The default value is
 // always false, and the presence of the flag switches the value to true.
-// TODO(bkonyi): enable_service_auth_codes is a temporary flag and will be
-// removed once auth codes are enabled by default. disable_service_auth_codes is
-// a no-op for now.
 #define BOOL_OPTIONS_LIST(V)                                                   \
   V(version, version_option)                                                   \
   V(compile_all, compile_all)                                                  \
   V(disable_service_origin_check, vm_service_dev_mode)                         \
   V(disable_service_auth_codes, vm_service_auth_disabled)                      \
   V(deterministic, deterministic)                                              \
-  V(enable_service_auth_codes, vm_service_auth_enabled)                        \
   V(trace_loading, trace_loading)                                              \
   V(short_socket_read, short_socket_read)                                      \
   V(short_socket_write, short_socket_write)                                    \
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index f57bf4e..05c37a1 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -132,8 +132,8 @@
     if (pause_on_exit) {
       fullArgs.add('--pause-isolates-on-exit');
     }
-    if (useAuthToken) {
-      fullArgs.add('--enable-service-auth-codes');
+    if (!useAuthToken) {
+      fullArgs.add('--disable-service-auth-codes');
     }
     if (pause_on_unhandled_exceptions) {
       fullArgs.add('--pause-isolates-on-unhandled-exceptions');
diff --git a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
index 81fd124..42ad0c4 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -173,15 +173,18 @@
   V internalRemove(Object key) {
     var rest = _rest;
     if (rest == null) return null;
-    var bucket = _getBucket(rest, key);
+    var hash = internalComputeHashCode(key);
+    var bucket = _getTableBucket(rest, hash);
     int index = internalFindBucketIndex(bucket, key);
     if (index < 0) return null;
     // Use splice to remove the [cell] element at the index and
     // unlink the cell before returning its value.
     LinkedHashMapCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index);
     _unlinkCell(cell);
-    // TODO(kasperl): Consider getting rid of the bucket list when
-    // the length reaches zero.
+    // Remove empty bucket list to avoid memory leak.
+    if (JS('int', '#.length', bucket) == 0) {
+      _deleteTableEntry(rest, hash);
+    }
     return JS('', '#', cell.hashMapCellValue);
   }
 
diff --git a/tests/lib_2/js/array_test.dart b/tests/lib_2/js/array_test.dart
new file mode 100644
index 0000000..30bae97
--- /dev/null
+++ b/tests/lib_2/js/array_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@JS()
+library array_test;
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js;
+
+main() {
+  testArrayConstructor();
+}
+
+/// Test that we can access .constructor() on a JS Array instance, regardless
+/// of the reified generic type.
+///
+/// Regression test for https://github.com/dart-lang/sdk/issues/36372
+testArrayConstructor() {
+  var list = <int>[1, 2, 3];
+  testArray = list;
+
+  // Call the consturctor with `new`.
+  var array = js.callConstructor(js.getProperty(testArray, 'constructor'), []);
+  var list2 = array as List;
+  Expect.listEquals(list2, []);
+  Expect.notEquals(list, list2, '$list2 should be a new list');
+
+  // We could return a reified type here, but currently does not to match
+  // dart2js, and because the Array is being returned to JS.
+  Expect.isFalse(list2 is List<int>,
+      '$list2 should not have a reified generic type (it was allocated by JS)');
+
+  list2.addAll([1, 2, 3]);
+  Expect.listEquals(list, list2);
+}
+
+external Object get testArray;
+external set testArray(value);
diff --git a/tools/VERSION b/tools/VERSION
index a90ee68..236864e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -34,6 +34,6 @@
 MINOR 3
 PATCH 0
 PRERELEASE 0
-PRERELEASE_PATCH 1
+PRERELEASE_PATCH 2
 ABI_VERSION 4
 OLDEST_SUPPORTED_ABI_VERSION 1
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index c866ed2..53cf818 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -120,8 +120,8 @@
       negatable: true,
       help: 'Whether to only build summary files.')
   ..addOption('target',
-      allowed: const ['vm', 'dart2js', 'devcompiler'],
-      help: 'Build kernel for the vm, dart2js, or devcompiler')
+      allowed: const ['vm', 'dart2js', 'ddc'],
+      help: 'Build kernel for the vm, dart2js, or ddc')
   ..addOption('dart-sdk-summary')
   ..addMultiOption('input-summary')
   ..addMultiOption('input-linked')
@@ -179,7 +179,7 @@
   // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
   // compatible while we migrate existing clients of this tool.
   var targetName =
-      (parsedArgs['target'] as String) ?? (summaryOnly ? 'devcompiler' : 'vm');
+      (parsedArgs['target'] as String) ?? (summaryOnly ? 'ddc' : 'vm');
   var targetFlags = new TargetFlags();
   Target target;
   switch (targetName) {
@@ -196,13 +196,13 @@
             'error: --summary-only not supported for the dart2js target');
       }
       break;
-    case 'devcompiler':
+    case 'ddc':
       // TODO(jakemac):If `generateKernel` changes to return a summary
       // component, process the component instead.
       target = new DevCompilerSummaryTarget(sources, excludeNonSources);
       if (!summaryOnly) {
         out.writeln('error: --no-summary-only not supported for the '
-            'devcompiler target');
+            'ddc target');
       }
       break;
     default: