[webview_flutter] Workaround old Android tablets select drop down crash (#2663)

diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index e24c832..efff00e 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,6 +1,7 @@
 ## 0.3.20+1
 
 * OCMock module import -> #import, unit tests compile generated as library.
+* Fix select drop down crash on old Android tablets (https://github.com/flutter/flutter/issues/54164).
 
 ## 0.3.20
 
diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
index 477eefc..0aa2f58 100644
--- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
+++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
@@ -7,10 +7,13 @@
 import static android.content.Context.INPUT_METHOD_SERVICE;
 
 import android.content.Context;
+import android.graphics.Rect;
+import android.os.Build;
 import android.util.Log;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.WebView;
+import android.widget.ListPopupWindow;
 
 /**
  * A WebView subclass that mirrors the same implementation hacks that the system WebView does in
@@ -186,4 +189,45 @@
           }
         });
   }
+
+  @Override
+  protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+    // This works around a crash when old (<67.0.3367.0) Chromium versions are used.
+
+    // Prior to Chromium 67.0.3367 the following sequence happens when a select drop down is shown
+    // on tablets:
+    //
+    //  - WebView is calling ListPopupWindow#show
+    //  - buildDropDown is invoked, which sets mDropDownList to a DropDownListView.
+    //  - showAsDropDown is invoked - resulting in mDropDownList being added to the window and is
+    //    also synchronously performing the following sequence:
+    //    - WebView's focus change listener is loosing focus (as mDropDownList got it)
+    //    - WebView is hiding all popups (as it lost focus)
+    //    - WebView's SelectPopupDropDown#hide is invoked.
+    //    - DropDownPopupWindow#dismiss is invoked setting mDropDownList to null.
+    //  - mDropDownList#setSelection is invoked and is throwing a NullPointerException (as we just set mDropDownList to null).
+    //
+    // To workaround this, we drop the problematic focus lost call.
+    // See more details on: https://github.com/flutter/flutter/issues/54164
+    //
+    // We don't do this after Android P as it shipped with a new enough WebView version, and it's
+    // better to not do this on all future Android versions in case DropDownListView's code changes.
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P
+        && isCalledFromListPopupWindowShow()
+        && !focused) {
+      return;
+    }
+    super.onFocusChanged(focused, direction, previouslyFocusedRect);
+  }
+
+  private boolean isCalledFromListPopupWindowShow() {
+    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+    for (int i = 0; i < stackTraceElements.length; i++) {
+      if (stackTraceElements[i].getClassName().equals(ListPopupWindow.class.getCanonicalName())
+          && stackTraceElements[i].getMethodName().equals("show")) {
+        return true;
+      }
+    }
+    return false;
+  }
 }