Kotlin: Exceptions moved from helpers to core bindings

Needed because they will be used by the bindings and we can't
have a circular relationship bindings <-> helper.

Test: ./gradlew connectedAndroidTest
Bug: b/458144497
Change-Id: Ifdd9e7d18c4ff9011e815d71b42cc20971d8ac07
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/271694
Commit-Queue: Jim Blackler <jimblackler@google.com>
Reviewed-by: Mridul Goyal <mridulgoyal@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 91c1ab4..7ca2e72 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -1777,6 +1777,12 @@
                                          'function_pointer': function_pointer
                                      }
                                  ]))
+
+            renders.append(
+                FileRender('art/api_kotlin_exceptions.kt',
+                           'java/' + kt_file_path + '/Exceptions.kt',
+                           [RENDER_PARAMS_BASE, params_kotlin]))
+
             renders.append(
                 FileRender('art/api_kotlin_functions.kt',
                            'java/' + kt_file_path + '/Functions.kt',
diff --git a/generator/templates/art/api_kotlin_exceptions.kt b/generator/templates/art/api_kotlin_exceptions.kt
new file mode 100644
index 0000000..83166aae
--- /dev/null
+++ b/generator/templates/art/api_kotlin_exceptions.kt
@@ -0,0 +1,66 @@
+//* Copyright 2025 The Dawn & Tint Authors
+//*
+//* Redistribution and use in source and binary forms, with or without
+//* modification, are permitted provided that the following conditions are met:
+//*
+//* 1. Redistributions of source code must retain the above copyright notice, this
+//*    list of conditions and the following disclaimer.
+//*
+//* 2. Redistributions in binary form must reproduce the above copyright notice,
+//*    this list of conditions and the following disclaimer in the documentation
+//*    and/or other materials provided with the distribution.
+//*
+//* 3. Neither the name of the copyright holder nor the names of its
+//*    contributors may be used to endorse or promote products derived from
+//*    this software without specific prior written permission.
+//*
+//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+package {{ kotlin_package }}
+{% set ns = namespace() %}
+{% for enum in by_category["enum"] %}
+    {% if enum.name.get() == "error type" %}{% set ns.error = enum %}{% endif %}
+    {% if enum.name.get() == "device lost reason" %}{% set ns.device_lost_reason = enum %}{% endif %}
+{% endfor %}
+{% for obj in by_category["object"] if obj.name.get() == "device" %}
+    {% set ns.device = obj %}
+{% endfor %}
+
+/**
+ * Exception for errors originating from the Dawn WebGPU library that do not fit
+ * into more specific WebGPU error categories.
+ *
+ * @param message A detailed message explaining the error.
+ */
+public class DawnException(message: String) : Exception(message)
+
+/**
+ * Exception thrown when a [GPUDevice] is lost and can no longer be used.
+ *
+ * @property device The [GPUDevice] that was lost.
+ * @property reason The reason code indicating why the device was lost.
+ * @param message A human-readable message describing the device loss.
+ */
+public class DeviceLostException(
+  public val device: {{kotlin_name(ns.device)}},
+  @{{kotlin_name(ns.device_lost_reason)}} public val reason: Int,
+  message: String
+) : Exception(message)
+
+{% for value in ns.error.values %}
+    /**
+     * Exception for {{value.name.CamelCase()}} type errors.
+     *
+     * @property device The device that encountered the condition.
+     */
+    public class {{value.name.CamelCase()}}Exception(public val device: {{kotlin_name(ns.device)}}, message: String) : Exception(message);
+
+{% endfor %}
diff --git a/generator/templates/art/methods.cpp b/generator/templates/art/methods.cpp
index dacae68..443b969 100644
--- a/generator/templates/art/methods.cpp
+++ b/generator/templates/art/methods.cpp
@@ -160,7 +160,7 @@
         }
         {% if method.returns and method.returns.type.name.canonical_case() == 'status' %}
             if (result != WGPUStatus_Success) {
-                jclass exClass = env->FindClass("androidx/webgpu/helper/DawnException");
+                jclass exClass = env->FindClass("androidx/webgpu/DawnException");
                 std::string message = "Dawn method failed with status: " + std::to_string(result);
                 env->ThrowNew(exClass, message.c_str());
                 return{{ ' 0' if _kotlin_return }};
diff --git a/tools/android/BUILD.gn b/tools/android/BUILD.gn
index f0d4d87..1072b83 100644
--- a/tools/android/BUILD.gn
+++ b/tools/android/BUILD.gn
@@ -99,6 +99,7 @@
     "java/androidx/webgpu/DeviceLostReason.kt",
     "java/androidx/webgpu/ErrorFilter.kt",
     "java/androidx/webgpu/ErrorType.kt",
+    "java/androidx/webgpu/Exceptions.kt",
     "java/androidx/webgpu/Extent3D.kt",
     "java/androidx/webgpu/FeatureLevel.kt",
     "java/androidx/webgpu/FeatureName.kt",
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/BufferTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/BufferTest.kt
index 38b6450..e184a65 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/BufferTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/BufferTest.kt
@@ -2,10 +2,10 @@
 
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.DawnException
-import androidx.webgpu.helper.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createWebGpu
+import androidx.webgpu.DawnException
+import androidx.webgpu.ValidationException
 import java.nio.ByteBuffer
 import java.nio.ByteOrder
 import kotlinx.coroutines.runBlocking
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/CommandEncoderTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/CommandEncoderTest.kt
index 6ead622..f3a2d3e 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/CommandEncoderTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/CommandEncoderTest.kt
@@ -1,7 +1,7 @@
 package androidx.webgpu
 
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.ValidationException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createWebGpu
 import java.nio.ByteBuffer
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/DeviceTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/DeviceTest.kt
index e5fa158..39b52b0 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/DeviceTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/DeviceTest.kt
@@ -2,10 +2,10 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createWebGpu
 import junit.framework.TestCase.assertEquals
+import androidx.webgpu.ValidationException
 import kotlinx.coroutines.runBlocking
 import org.junit.After
 import org.junit.Test
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/ErrorTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/ErrorTest.kt
index c445e1a..0f34321 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/ErrorTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/ErrorTest.kt
@@ -2,7 +2,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.ValidationException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.helper.createWebGpu
 import kotlinx.coroutines.runBlocking
 import org.junit.Assert.assertThrows
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/RenderBundleEncoderTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/RenderBundleEncoderTest.kt
index c6b43af..4e97364 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/RenderBundleEncoderTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/RenderBundleEncoderTest.kt
@@ -2,7 +2,7 @@
 
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.ValidationException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createWebGpu
 import java.nio.ByteBuffer
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/SurfaceTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/SurfaceTest.kt
index f1a3697..950b4e9 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/SurfaceTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/SurfaceTest.kt
@@ -4,7 +4,7 @@
 import android.view.Surface
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.ValidationException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createWebGpu
 import kotlinx.coroutines.runBlocking
diff --git a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/TextureTest.kt b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/TextureTest.kt
index ed82d6d..86cf2ad 100644
--- a/tools/android/webgpu/src/androidTest/java/androidx/webgpu/TextureTest.kt
+++ b/tools/android/webgpu/src/androidTest/java/androidx/webgpu/TextureTest.kt
@@ -1,8 +1,8 @@
 package androidx.webgpu
 
 import androidx.test.filters.SmallTest
-import androidx.webgpu.helper.DawnException
-import androidx.webgpu.helper.ValidationException
+import androidx.webgpu.DawnException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.helper.WebGpu
 import androidx.webgpu.helper.createBitmap
 import androidx.webgpu.helper.createWebGpu
diff --git a/tools/android/webgpu/src/main/java/androidx/webgpu/helper/DawnException.kt b/tools/android/webgpu/src/main/java/androidx/webgpu/helper/DawnException.kt
deleted file mode 100644
index 4a8b14e..0000000
--- a/tools/android/webgpu/src/main/java/androidx/webgpu/helper/DawnException.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package androidx.webgpu.helper
-
-public class DawnException(message:String): Exception(message)
diff --git a/tools/android/webgpu/src/main/java/androidx/webgpu/helper/WebGpu.kt b/tools/android/webgpu/src/main/java/androidx/webgpu/helper/WebGpu.kt
index c4fe942..410eec6 100644
--- a/tools/android/webgpu/src/main/java/androidx/webgpu/helper/WebGpu.kt
+++ b/tools/android/webgpu/src/main/java/androidx/webgpu/helper/WebGpu.kt
@@ -10,10 +10,13 @@
 import androidx.webgpu.GPUDevice
 import androidx.webgpu.DeviceDescriptor
 import androidx.webgpu.DeviceLostCallback
+import androidx.webgpu.DeviceLostException
 import androidx.webgpu.DeviceLostReason
 import androidx.webgpu.ErrorType
 import androidx.webgpu.GPUInstance
 import androidx.webgpu.InstanceDescriptor
+import androidx.webgpu.InternalException
+import androidx.webgpu.OutOfMemoryException
 import androidx.webgpu.RequestAdapterOptions
 import androidx.webgpu.RequestAdapterStatus
 import androidx.webgpu.GPUSurface
@@ -21,22 +24,12 @@
 import androidx.webgpu.SurfaceDescriptor
 import androidx.webgpu.SurfaceSourceAndroidNativeWindow
 import androidx.webgpu.UncapturedErrorCallback
+import androidx.webgpu.UnknownException
+import androidx.webgpu.ValidationException
 import androidx.webgpu.createInstance
 import androidx.webgpu.helper.Util.windowFromSurface
 import java.util.concurrent.Executor
 
-public class DeviceLostException(
-    public val device: GPUDevice, @DeviceLostReason public val reason: Int, message: String
-) : Exception(message)
-
-public class ValidationException(public val device: GPUDevice, message: String) : Exception(message)
-
-public class OutOfMemoryException(public val device: GPUDevice, message: String) : Exception(message)
-
-public class InternalException(public val device: GPUDevice, message: String) : Exception(message)
-
-public class UnknownException(public val device: GPUDevice, message: String) : Exception(message)
-
 private const val POLLING_DELAY_MS = 100L
 
 public abstract class WebGpu : AutoCloseable {