Repository: flutter
Issue: Methods marked with @UiThread must be executed on the main thread. Current thread: WallpaperService
Labels: c: crash,e: device-specific,platform-android,engine,P2,c: fatal crash,team-android,triaged-android

I'm trying to run `FlutterEngine` in Android `WallpaperService`, every thing works so far except some VIVO phone crashed and throw the `java.lang.RuntimeException` with message in title. 

## Steps to Reproduce
1. When `WallpaperService#onCreateEngine` getting called, and `WallpaperService.Engine#onCreate` getting called.
2. Some VIVO phone seem start the `WallpaperService` in a thread named "WallpaperService".

**Expected results:** 
Pass the `@UiThread` checking in Android Service

**Actual results:** 
Crash when calling `FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:36)`

<details>
<summary>LiveWallpaperFltService.kt</summary>

```kotlin
package com.LondonX.live_wallpaper_flt.service

import android.content.res.Configuration
import android.service.wallpaper.WallpaperService
import android.text.format.DateFormat
import android.view.SurfaceHolder
import android.view.ViewConfiguration
import com.LondonX.live_wallpaper_flt.entity.Config
import com.google.gson.Gson
import io.flutter.FlutterInjector
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterJNI
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.renderer.FlutterRenderer
import io.flutter.embedding.engine.systemchannels.SettingsChannel
import kotlinx.coroutines.*
import java.io.File

private const val TAG = "[live_wallpaper_flt]"

class LiveWallpaperFltService : WallpaperService() {

    override fun onCreateEngine(): Engine {
        return object : Engine() {
            private val config by lazy {
                val json = File(filesDir, "live_wallpaper_config.json").readText()
                Gson().fromJson(json, Config::class.java)
                    ?: throw Exception("${TAG}invalid config file, make sure you called LiveWallpaperFlt.instance.applyConfig first.")
            }
            private lateinit var flutterEngine: FlutterEngine

            private val scope = CoroutineScope(Dispatchers.Main)
            private var refreshJob: Job? = null

            private var width: Int? = null
            private var height: Int? = null
            private var isDark = false

            override fun onCreate(surfaceHolder: SurfaceHolder?) {
                super.onCreate(surfaceHolder)
                flutterEngine = FlutterEngine(this@LiveWallpaperFltService)
                flutterEngine.dartExecutor.executeDartEntrypoint(
                    DartExecutor.DartEntrypoint(
                        FlutterInjector.instance().flutterLoader().findAppBundlePath(),
                        config.entryFunction,
                    ),
                    listOf("is_started_from_wallpaper_service"),
                )
                isDark = isInDarkMode()
                applyPlatformDarkMode()
            }

            private fun engineScope(f: suspend FlutterEngine.() -> Unit) {
                scope.launch {
                    f.invoke(flutterEngine)
                }
            }

            private fun FlutterEngine.isAttached(): Boolean {
                surfaceHolder?.surface ?: return false
                val flutterJNI = FlutterRenderer::class.java.getDeclaredField("flutterJNI")
                    .apply { isAccessible = true }.get(renderer) as? FlutterJNI
                return flutterJNI?.isAttached == true
            }

            override fun onVisibilityChanged(visible: Boolean) {
                super.onVisibilityChanged(visible)
                if (visible) {
                    refreshJob = scope.launch {
                        while (true) {
                            delay(24)
                            if (flutterEngine.isAttached()) {
                                applyViewportMetrics()
                                if (isDark != isInDarkMode()) {
                                    isDark = isInDarkMode()
                                    applyPlatformDarkMode()
                                }
                            }
                        }
                    }
                    engineScope {
                        lifecycleChannel.appIsResumed()
                        if (flutterEngine.isAttached()) {
                            renderer.startRenderingToSurface(surfaceHolder.surface!!, true)
                        }
                    }
                } else {
                    refreshJob?.cancel()
                    engineScope {
                        lifecycleChannel.appIsPaused()
                        if (flutterEngine.isAttached()) {
                            renderer.stopRenderingToSurface()
                        }
                        lifecycleChannel.appIsInactive()
                    }
                }
            }

            override fun onDestroy() {
                refreshJob?.cancel()
                engineScope {
                    lifecycleChannel.appIsDetached()
                    destroy()
                }
                super.onDestroy()
            }

            override fun onSurfaceChanged(
                holder: SurfaceHolder?, format: Int, width: Int, height: Int
            ) {
                super.onSurfaceChanged(holder, format, width, height)
                this.width = width
                this.height = height
                if (!flutterEngine.renderer.isDisplayingFlutterUi) return
                applyViewportMetrics()
            }

            private fun applyViewportMetrics() {
                val width = this.width ?: resources.displayMetrics.widthPixels
                val height = this.height ?: resources.displayMetrics.heightPixels
                val viewportMetrics = FlutterRenderer.ViewportMetrics()
                viewportMetrics.devicePixelRatio = resources.displayMetrics.density
                viewportMetrics.height = height
                viewportMetrics.width = width
                viewportMetrics.physicalTouchSlop =
                    ViewConfiguration.get(this@LiveWallpaperFltService).scaledTouchSlop
                engineScope {
                    if (flutterEngine.isAttached()) {
                        renderer.setViewportMetrics(viewportMetrics)
                        renderer.surfaceChanged(width, height)
                    }
                }
            }

            private fun isInDarkMode(): Boolean {
                return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
            }

            private fun applyPlatformDarkMode() {
                engineScope {
                    settingsChannel.startMessage()
                        .setTextScaleFactor(resources.configuration.fontScale)
                        .setUse24HourFormat(DateFormat.is24HourFormat(this@LiveWallpaperFltService))
                        .setPlatformBrightness(
                            if (isInDarkMode()) {
                                SettingsChannel.PlatformBrightness.dark
                            } else {
                                SettingsChannel.PlatformBrightness.light
                            }
                        ).send()
                }
            }
        }
    }
}
```

</details>

Still crash even I tried using `engineScope` to wrap codes running on `CoroutineScope(Dispatchers.Main)`.

<details>
<summary>Logs</summary>

```
Fatal Exception: java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: WallpaperService
       at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:36)
       at io.flutter.embedding.engine.FlutterJNI.setPlatformMessageHandler(FlutterJNI.java)
       at io.flutter.embedding.engine.dart.DartExecutor.onAttachedToJNI(DartExecutor.java:11)
       at io.flutter.embedding.engine.FlutterEngine.<init>(FlutterEngine.java:58)
       at io.flutter.embedding.engine.FlutterEngine.<init>(FlutterEngine.java:8)
       at io.flutter.embedding.engine.FlutterEngine.<init>(FlutterEngine.java:11)
       at io.flutter.embedding.engine.FlutterEngine.<init>(FlutterEngine.java:6)
       at io.flutter.embedding.engine.FlutterEngine.<init>(FlutterEngine.java:1)
       at com.LondonX.live_wallpaper_flt.service.LiveWallpaperFltService$onCreateEngine$1.<init>(LiveWallpaperFltService.java:18)
       at com.LondonX.live_wallpaper_flt.service.LiveWallpaperFltService.onCreateEngine(LiveWallpaperFltService.java:2)
       at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:2192)
       at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:44)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:233)
       at android.os.Looper.loop(Looper.java:334)
       at android.os.HandlerThread.run(HandlerThread.java:67)
```
</details>

<details>
<summary>flutter analyze</summary>

```
flutter analyze
Analyzing wallpaper_gpt...                                              
No issues found! (ran in 7.0s)
```
</details>

<details>
<summary>flutter doctor -v</summary>

```
flutter doctor -v
[✓] Flutter (Channel stable, 3.7.7, on macOS 13.2.1 22D68 darwin-x64, locale zh-Hans-CN)
    • Flutter version 3.7.7 on channel stable at /usr/local/Caskroom/flutter/1.22.6/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2ad6cd72c0 (9 days ago), 2023-03-08 09:41:59 -0800
    • Engine revision 1837b5be5f
    • Dart version 2.19.4
    • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc2)
    • Android SDK at /Users/london/Library/Android/sdk/
    • Platform android-33, build-tools 33.0.0-rc2
    • ANDROID_HOME = /Users/london/Library/Android/sdk/
    • ANDROID_SDK_ROOT = /Users/london/Library/Android/sdk/
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] IntelliJ IDEA Community Edition (version 2022.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.76.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.60.0

[✓] Proxy Configuration
    • HTTP_PROXY is set
    • NO_PROXY is localhost,127.0.0.1,::1
    • NO_PROXY contains localhost
    • NO_PROXY contains 127.0.0.1
    • NO_PROXY contains ::1

[✓] Connected device (2 available)
    • London’s iPhone (mobile) • 00008101-001E39DE3A63001E • ios            • iOS 16.3.1 20D67
    • Chrome (web)             • chrome                    • web-javascript • Google Chrome 111.0.5563.64

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
```
</details>