// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

// Auto-generated initialization code.

final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
    ProtectedJniExtensions.initGeneratedLibrary("android_utils");

/// from: androidx.emoji2.text.EmojiCompat$CodepointSequenceMatchResult
class EmojiCompat_CodepointSequenceMatchResult extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_CodepointSequenceMatchResult> $type =
      type;

  EmojiCompat_CodepointSequenceMatchResult.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_CodepointSequenceMatchResultType();
}

final class $EmojiCompat_CodepointSequenceMatchResultType
    extends jni.JObjType<EmojiCompat_CodepointSequenceMatchResult> {
  const $EmojiCompat_CodepointSequenceMatchResultType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/EmojiCompat$CodepointSequenceMatchResult;";

  @override
  EmojiCompat_CodepointSequenceMatchResult fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_CodepointSequenceMatchResult.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_CodepointSequenceMatchResultType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType ==
            ($EmojiCompat_CodepointSequenceMatchResultType) &&
        other is $EmojiCompat_CodepointSequenceMatchResultType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$Config
///
/// Configuration class for EmojiCompat. Changes to the values will be ignored after
/// \#init(Config) is called.
///@see \#init(EmojiCompat.Config)
class EmojiCompat_Config extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_Config> $type = type;

  EmojiCompat_Config.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_ConfigType();
  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: protected void <init>(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader metadataLoader)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Default constructor.
  ///@param metadataLoader MetadataRepoLoader instance, cannot be {@code null}
  factory EmojiCompat_Config(
    EmojiCompat_MetadataRepoLoader metadataLoader,
  ) {
    return EmojiCompat_Config.fromRef(
        _new0(metadataLoader.reference.pointer).object);
  }

  static final _registerInitCallback = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__registerInitCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Registers an initialization callback.
  ///@param initCallback the initialization callback to register, cannot be {@code null}
  ///@return EmojiCompat.Config instance
  EmojiCompat_Config registerInitCallback(
    EmojiCompat_InitCallback initCallback,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(
        _registerInitCallback(reference.pointer, initCallback.reference.pointer)
            .object);
  }

  static final _unregisterInitCallback = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__unregisterInitCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Unregisters a callback that was added before.
  ///@param initCallback the initialization callback to be removed, cannot be {@code null}
  ///@return EmojiCompat.Config instance
  EmojiCompat_Config unregisterInitCallback(
    EmojiCompat_InitCallback initCallback,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(_unregisterInitCallback(
            reference.pointer, initCallback.reference.pointer)
        .object);
  }

  static final _setReplaceAll = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Uint8)>>("EmojiCompat_Config__setReplaceAll")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean replaceAll)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Determines whether EmojiCompat should replace all the emojis it finds with the
  /// EmojiSpans. By default EmojiCompat tries its best to understand if the system already
  /// can render an emoji and do not replace those emojis.
  ///@param replaceAll replace all emojis found with EmojiSpans
  ///@return EmojiCompat.Config instance
  EmojiCompat_Config setReplaceAll(
    bool replaceAll,
  ) {
    return const $EmojiCompat_ConfigType()
        .fromRef(_setReplaceAll(reference.pointer, replaceAll ? 1 : 0).object);
  }

  static final _setUseEmojiAsDefaultStyle = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Uint8)>>("EmojiCompat_Config__setUseEmojiAsDefaultStyle")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean useEmojiAsDefaultStyle)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Determines whether EmojiCompat should use the emoji presentation style for emojis
  /// that have text style as default. By default, the text style would be used, unless these
  /// are followed by the U+FE0F variation selector.
  /// Details about emoji presentation and text presentation styles can be found here:
  /// http://unicode.org/reports/tr51/\#Presentation_Style
  /// If useEmojiAsDefaultStyle is true, the emoji presentation style will be used for all
  /// emojis, including potentially unexpected ones (such as digits or other keycap emojis). If
  /// this is not the expected behaviour, method
  /// \#setUseEmojiAsDefaultStyle(boolean, List) can be used to specify the
  /// exception emojis that should be still presented as text style.
  ///@param useEmojiAsDefaultStyle whether to use the emoji style presentation for all emojis
  ///                               that would be presented as text style by default
  EmojiCompat_Config setUseEmojiAsDefaultStyle(
    bool useEmojiAsDefaultStyle,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(_setUseEmojiAsDefaultStyle(
            reference.pointer, useEmojiAsDefaultStyle ? 1 : 0)
        .object);
  }

  static final _setUseEmojiAsDefaultStyle1 = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Uint8,
                      ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__setUseEmojiAsDefaultStyle1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean useEmojiAsDefaultStyle, java.util.List<java.lang.Integer> emojiAsDefaultStyleExceptions)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// @see \#setUseEmojiAsDefaultStyle(boolean)
  ///@param emojiAsDefaultStyleExceptions Contains the exception emojis which will be still
  ///                                      presented as text style even if the
  ///                                      useEmojiAsDefaultStyle flag is set to {@code true}.
  ///                                      This list will be ignored if useEmojiAsDefaultStyle
  ///                                      is {@code false}. Note that emojis with default
  ///                                      emoji style presentation will remain emoji style
  ///                                      regardless the value of useEmojiAsDefaultStyle or
  ///                                      whether they are included in the exceptions list or
  ///                                      not. When no exception is wanted, the method
  ///                                      \#setUseEmojiAsDefaultStyle(boolean) should
  ///                                      be used instead.
  EmojiCompat_Config setUseEmojiAsDefaultStyle1(
    bool useEmojiAsDefaultStyle,
    jni.JList<jni.JInteger> emojiAsDefaultStyleExceptions,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(_setUseEmojiAsDefaultStyle1(
            reference.pointer,
            useEmojiAsDefaultStyle ? 1 : 0,
            emojiAsDefaultStyleExceptions.reference.pointer)
        .object);
  }

  static final _setEmojiSpanIndicatorEnabled = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
          "EmojiCompat_Config__setEmojiSpanIndicatorEnabled")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean emojiSpanIndicatorEnabled)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Determines whether a background will be drawn for the emojis that are found and
  /// replaced by EmojiCompat. Should be used only for debugging purposes. The indicator color
  /// can be set using \#setEmojiSpanIndicatorColor(int).
  ///@param emojiSpanIndicatorEnabled when {@code true} a background is drawn for each emoji
  ///                                  that is replaced
  EmojiCompat_Config setEmojiSpanIndicatorEnabled(
    bool emojiSpanIndicatorEnabled,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(
        _setEmojiSpanIndicatorEnabled(
                reference.pointer, emojiSpanIndicatorEnabled ? 1 : 0)
            .object);
  }

  static final _setEmojiSpanIndicatorColor = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat_Config__setEmojiSpanIndicatorColor")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(int color)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Sets the color used as emoji span indicator. The default value is
  /// Color\#GREEN Color.GREEN.
  ///@see \#setEmojiSpanIndicatorEnabled(boolean)
  EmojiCompat_Config setEmojiSpanIndicatorColor(
    int color,
  ) {
    return const $EmojiCompat_ConfigType()
        .fromRef(_setEmojiSpanIndicatorColor(reference.pointer, color).object);
  }

  static final _setMetadataLoadStrategy = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat_Config__setMetadataLoadStrategy")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int strategy)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Determines the strategy to start loading the metadata. By default EmojiCompat
  /// will start loading the metadata during EmojiCompat\#init(Config). When set to
  /// EmojiCompat\#LOAD_STRATEGY_MANUAL, you should call EmojiCompat\#load() to
  /// initiate metadata loading.
  /// <p/>
  /// Default implementations of EmojiCompat.MetadataRepoLoader start a thread
  /// during their EmojiCompat.MetadataRepoLoader\#load functions. Just instantiating
  /// and starting a thread might take time especially in older devices. Since
  /// EmojiCompat\#init(Config) has to be called before any EmojiCompat widgets are
  /// inflated, this results in time spent either on your Application.onCreate or Activity
  /// .onCreate. If you'd like to gain more control on when to start loading the metadata
  /// and be able to call EmojiCompat\#init(Config) with absolute minimum time cost you
  /// can use EmojiCompat\#LOAD_STRATEGY_MANUAL.
  /// <p/>
  /// When set to EmojiCompat\#LOAD_STRATEGY_MANUAL, EmojiCompat will wait
  /// for \#load() to be called by the developer in order to start loading metadata,
  /// therefore you should call EmojiCompat\#load() to initiate metadata loading.
  /// \#load() can be called from any thread.
  /// <pre>
  /// EmojiCompat.Config config = new FontRequestEmojiCompatConfig(context, fontRequest)
  ///         .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
  ///
  /// // EmojiCompat will not start loading metadata and MetadataRepoLoader\#load(...)
  /// // will not be called
  /// EmojiCompat.init(config);
  ///
  /// // At any time (i.e. idle time or executorService is ready)
  /// // call EmojiCompat\#load() to start loading metadata.
  /// executorService.execute(() -> EmojiCompat.get().load());
  /// </pre>
  ///@param strategy one of EmojiCompat\#LOAD_STRATEGY_DEFAULT,
  ///                  EmojiCompat\#LOAD_STRATEGY_MANUAL
  EmojiCompat_Config setMetadataLoadStrategy(
    int strategy,
  ) {
    return const $EmojiCompat_ConfigType()
        .fromRef(_setMetadataLoadStrategy(reference.pointer, strategy).object);
  }

  static final _setSpanFactory = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat_Config__setSpanFactory")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory factory)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Set the span factory used to actually draw emoji replacements.
  ///@param factory custum span factory that can draw the emoji replacements
  ///@return this
  EmojiCompat_Config setSpanFactory(
    EmojiCompat_SpanFactory factory0,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(
        _setSpanFactory(reference.pointer, factory0.reference.pointer).object);
  }

  static final _setGlyphChecker = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__setGlyphChecker")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker glyphChecker)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// The interface that is used by EmojiCompat in order to check if a given emoji can be
  /// rendered by the system.
  ///@param glyphChecker GlyphChecker instance to be used.
  EmojiCompat_Config setGlyphChecker(
    EmojiCompat_GlyphChecker glyphChecker,
  ) {
    return const $EmojiCompat_ConfigType().fromRef(
        _setGlyphChecker(reference.pointer, glyphChecker.reference.pointer)
            .object);
  }

  static final _getMetadataRepoLoader = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_Config__getMetadataRepoLoader")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns the MetadataRepoLoader.
  EmojiCompat_MetadataRepoLoader getMetadataRepoLoader() {
    return const $EmojiCompat_MetadataRepoLoaderType()
        .fromRef(_getMetadataRepoLoader(reference.pointer).object);
  }
}

final class $EmojiCompat_ConfigType extends jni.JObjType<EmojiCompat_Config> {
  const $EmojiCompat_ConfigType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$Config;";

  @override
  EmojiCompat_Config fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_Config.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_ConfigType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_ConfigType) &&
        other is $EmojiCompat_ConfigType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$DefaultSpanFactory
///
/// @hide
class EmojiCompat_DefaultSpanFactory extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_DefaultSpanFactory> $type = type;

  EmojiCompat_DefaultSpanFactory.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_DefaultSpanFactoryType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "EmojiCompat_DefaultSpanFactory__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory EmojiCompat_DefaultSpanFactory() {
    return EmojiCompat_DefaultSpanFactory.fromRef(_new0().object);
  }

  static final _createSpan = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_DefaultSpanFactory__createSpan")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer rasterizer)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns a TypefaceEmojiSpan.
  ///@param rasterizer TypefaceEmojiRasterizer instance, which can draw the emoji onto a
  ///                   Canvas.
  ///@return TypefaceEmojiSpan
  jni.JObject createSpan(
    jni.JObject rasterizer,
  ) {
    return const jni.JObjectType().fromRef(
        _createSpan(reference.pointer, rasterizer.reference.pointer).object);
  }
}

final class $EmojiCompat_DefaultSpanFactoryType
    extends jni.JObjType<EmojiCompat_DefaultSpanFactory> {
  const $EmojiCompat_DefaultSpanFactoryType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/EmojiCompat$DefaultSpanFactory;";

  @override
  EmojiCompat_DefaultSpanFactory fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_DefaultSpanFactory.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_DefaultSpanFactoryType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_DefaultSpanFactoryType) &&
        other is $EmojiCompat_DefaultSpanFactoryType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$GlyphChecker
///
/// Interface to check if a given emoji exists on the system.
class EmojiCompat_GlyphChecker extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_GlyphChecker> $type = type;

  EmojiCompat_GlyphChecker.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_GlyphCheckerType();
  static final _hasGlyph = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32,
                  ffi.Int32)>>("EmojiCompat_GlyphChecker__hasGlyph")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();

  /// from: public abstract boolean hasGlyph(java.lang.CharSequence charSequence, int start, int end, int sdkAdded)
  ///
  /// Return {@code true} if the emoji that is in {@code charSequence} between
  /// {@code start}(inclusive) and {@code end}(exclusive) can be rendered on the system
  /// using the default Typeface.
  ///
  /// This function is called after an emoji is identified in the given {@code charSequence}
  /// and EmojiCompat wants to know if that emoji can be rendered on the system. The result
  /// of this call will be cached and the same emoji sequence won't be asked for the same
  /// EmojiCompat instance.
  ///
  /// When the function returns {@code true}, it will mean that the system can render the
  /// emoji. In that case if Config\#setReplaceAll is set to {@code false}, then no
  /// EmojiSpan will be added in the final emoji processing result.
  ///
  /// When the function returns {@code false}, it will mean that the system cannot render
  /// the given emoji, therefore an EmojiSpan will be added to the final emoji
  /// processing result.
  ///
  /// The default implementation of this class uses
  /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) function to check
  /// if the emoji can be rendered on the system. This is required even if EmojiCompat
  /// knows about the SDK Version that the emoji was added on AOSP. Just the {@code sdkAdded}
  /// information is not enough to reliably decide if emoji can be rendered since this
  /// information may not be consistent across all the OEMs and all the Android versions.
  ///
  /// With this interface you can apply your own heuristics to check if the emoji can be
  /// rendered on the system. For example, if you'd like to rely on the {@code sdkAdded}
  /// information, and some predefined OEMs, it is possible to write the following code
  /// snippet.
  ///
  /// {@sample frameworks/support/samples/SupportEmojiDemos/src/main/java/com/example/android/support/text/emoji/sample/GlyphCheckerSample.java glyphchecker}
  ///@param charSequence the CharSequence that is being processed
  ///@param start the inclusive starting offset for the emoji in the {@code charSequence}
  ///@param end the exclusive end offset for the emoji in the {@code charSequence}
  ///@param sdkAdded the API version that the emoji was added in AOSP
  ///@return true if the given sequence can be rendered as a single glyph, otherwise false.
  bool hasGlyph(
    jni.JObject charSequence,
    int start,
    int end,
    int sdkAdded,
  ) {
    return _hasGlyph(reference.pointer, charSequence.reference.pointer, start,
            end, sdkAdded)
        .boolean;
  }
}

final class $EmojiCompat_GlyphCheckerType
    extends jni.JObjType<EmojiCompat_GlyphChecker> {
  const $EmojiCompat_GlyphCheckerType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$GlyphChecker;";

  @override
  EmojiCompat_GlyphChecker fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_GlyphChecker.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_GlyphCheckerType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_GlyphCheckerType) &&
        other is $EmojiCompat_GlyphCheckerType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$InitCallback
///
/// Listener class for the initialization of the EmojiCompat.
class EmojiCompat_InitCallback extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_InitCallback> $type = type;

  EmojiCompat_InitCallback.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_InitCallbackType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "EmojiCompat_InitCallback__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory EmojiCompat_InitCallback() {
    return EmojiCompat_InitCallback.fromRef(_new0().object);
  }

  static final _onInitialized = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_InitCallback__onInitialized")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void onInitialized()
  ///
  /// Called when EmojiCompat is initialized and the emoji data is loaded. When used on devices
  /// running API 18 or below, this function is always called.
  void onInitialized() {
    return _onInitialized(reference.pointer).check();
  }

  static final _onFailed = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat_InitCallback__onFailed")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void onFailed(java.lang.Throwable throwable)
  ///
  /// Called when an unrecoverable error occurs during EmojiCompat initialization. When used on
  /// devices running API 18 or below, this function is never called.
  void onFailed(
    jni.JObject throwable,
  ) {
    return _onFailed(reference.pointer, throwable.reference.pointer).check();
  }
}

final class $EmojiCompat_InitCallbackType
    extends jni.JObjType<EmojiCompat_InitCallback> {
  const $EmojiCompat_InitCallbackType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$InitCallback;";

  @override
  EmojiCompat_InitCallback fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_InitCallback.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_InitCallbackType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_InitCallbackType) &&
        other is $EmojiCompat_InitCallbackType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$LoadStrategy
class EmojiCompat_LoadStrategy extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_LoadStrategy> $type = type;

  EmojiCompat_LoadStrategy.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_LoadStrategyType();
}

final class $EmojiCompat_LoadStrategyType
    extends jni.JObjType<EmojiCompat_LoadStrategy> {
  const $EmojiCompat_LoadStrategyType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$LoadStrategy;";

  @override
  EmojiCompat_LoadStrategy fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_LoadStrategy.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_LoadStrategyType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_LoadStrategyType) &&
        other is $EmojiCompat_LoadStrategyType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$MetadataRepoLoader
///
/// Interface to load emoji metadata.
class EmojiCompat_MetadataRepoLoader extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_MetadataRepoLoader> $type = type;

  EmojiCompat_MetadataRepoLoader.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_MetadataRepoLoaderType();
  static final _load = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_MetadataRepoLoader__load")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback loaderCallback)
  ///
  /// Start loading the metadata. When the loading operation is finished MetadataRepoLoaderCallback\#onLoaded(MetadataRepo) or
  /// MetadataRepoLoaderCallback\#onFailed(Throwable) should be called. When used on
  /// devices running API 18 or below, this function is never called.
  ///@param loaderCallback callback to signal the loading state
  void load(
    EmojiCompat_MetadataRepoLoaderCallback loaderCallback,
  ) {
    return _load(reference.pointer, loaderCallback.reference.pointer).check();
  }
}

final class $EmojiCompat_MetadataRepoLoaderType
    extends jni.JObjType<EmojiCompat_MetadataRepoLoader> {
  const $EmojiCompat_MetadataRepoLoaderType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;";

  @override
  EmojiCompat_MetadataRepoLoader fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_MetadataRepoLoader.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_MetadataRepoLoaderType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_MetadataRepoLoaderType) &&
        other is $EmojiCompat_MetadataRepoLoaderType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$MetadataRepoLoaderCallback
///
/// Callback to inform EmojiCompat about the state of the metadata load. Passed to
/// MetadataRepoLoader during MetadataRepoLoader\#load(MetadataRepoLoaderCallback) call.
class EmojiCompat_MetadataRepoLoaderCallback extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_MetadataRepoLoaderCallback> $type = type;

  EmojiCompat_MetadataRepoLoaderCallback.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_MetadataRepoLoaderCallbackType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "EmojiCompat_MetadataRepoLoaderCallback__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory EmojiCompat_MetadataRepoLoaderCallback() {
    return EmojiCompat_MetadataRepoLoaderCallback.fromRef(_new0().object);
  }

  static final _onLoaded = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_MetadataRepoLoaderCallback__onLoaded")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void onLoaded(androidx.emoji2.text.MetadataRepo metadataRepo)
  ///
  /// Called by MetadataRepoLoader when metadata is loaded successfully.
  ///@param metadataRepo MetadataRepo instance, cannot be {@code null}
  void onLoaded(
    jni.JObject metadataRepo,
  ) {
    return _onLoaded(reference.pointer, metadataRepo.reference.pointer).check();
  }

  static final _onFailed = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_MetadataRepoLoaderCallback__onFailed")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void onFailed(java.lang.Throwable throwable)
  ///
  /// Called by MetadataRepoLoader if an error occurs while loading the metadata.
  ///@param throwable the exception that caused the failure, {@code nullable}
  void onFailed(
    jni.JObject throwable,
  ) {
    return _onFailed(reference.pointer, throwable.reference.pointer).check();
  }
}

final class $EmojiCompat_MetadataRepoLoaderCallbackType
    extends jni.JObjType<EmojiCompat_MetadataRepoLoaderCallback> {
  const $EmojiCompat_MetadataRepoLoaderCallbackType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;";

  @override
  EmojiCompat_MetadataRepoLoaderCallback fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_MetadataRepoLoaderCallback.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_MetadataRepoLoaderCallbackType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_MetadataRepoLoaderCallbackType) &&
        other is $EmojiCompat_MetadataRepoLoaderCallbackType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$ReplaceStrategy
class EmojiCompat_ReplaceStrategy extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_ReplaceStrategy> $type = type;

  EmojiCompat_ReplaceStrategy.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_ReplaceStrategyType();
}

final class $EmojiCompat_ReplaceStrategyType
    extends jni.JObjType<EmojiCompat_ReplaceStrategy> {
  const $EmojiCompat_ReplaceStrategyType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$ReplaceStrategy;";

  @override
  EmojiCompat_ReplaceStrategy fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_ReplaceStrategy.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_ReplaceStrategyType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_ReplaceStrategyType) &&
        other is $EmojiCompat_ReplaceStrategyType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat$SpanFactory
///
/// Factory class that creates the EmojiSpans.
///
/// By default it creates TypefaceEmojiSpan.
///
/// Apps should use this only if they want to control the drawing of EmojiSpans for non-standard
/// emoji display (for example, resizing or repositioning emoji).
class EmojiCompat_SpanFactory extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat_SpanFactory> $type = type;

  EmojiCompat_SpanFactory.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompat_SpanFactoryType();
  static final _createSpan = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat_SpanFactory__createSpan")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer rasterizer)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Create EmojiSpan instance.
  ///@param rasterizer TypefaceEmojiRasterizer instance, which can draw the emoji onto a
  ///                   Canvas.
  ///@return EmojiSpan instance that can use TypefaceEmojiRasterizer to draw emoji.
  jni.JObject createSpan(
    jni.JObject rasterizer,
  ) {
    return const jni.JObjectType().fromRef(
        _createSpan(reference.pointer, rasterizer.reference.pointer).object);
  }
}

final class $EmojiCompat_SpanFactoryType
    extends jni.JObjType<EmojiCompat_SpanFactory> {
  const $EmojiCompat_SpanFactoryType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat$SpanFactory;";

  @override
  EmojiCompat_SpanFactory fromRef(jni.JObjectPtr ref) =>
      EmojiCompat_SpanFactory.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompat_SpanFactoryType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompat_SpanFactoryType) &&
        other is $EmojiCompat_SpanFactoryType;
  }
}

/// from: androidx.emoji2.text.EmojiCompat
///
/// Main class to keep Android devices up to date with the newest emojis by adding EmojiSpans
/// to a given CharSequence.
/// <p/>
/// By default, EmojiCompat is initialized by EmojiCompatInitializer, which performs
/// deferred font loading to avoid potential app startup delays. The default behavior is to load
/// the font shortly after the first Activity resumes. EmojiCompatInitializer will configure
/// EmojiCompat to use the system emoji font provider via DefaultEmojiCompatConfig and
/// always creates a new background thread for font loading.
/// <p/>
/// EmojiCompat will only allow one instance to be initialized and any calls to
/// \#init(Config) after the first one will have no effect. As a result, configuration options
/// may not be provided when using EmojiCompatInitializer. To provide a custom configuration,
/// disable EmojiCompatInitializer in the manifest with:
///
/// <pre>
///     &lt;provider
///         android:name="androidx.startup.InitializationProvider"
///         android:authorities="${applicationId}.androidx-startup"
///         android:exported="false"
///         tools:node="merge"&gt;
///         &lt;meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer"
///                   tools:node="remove" /&gt;
///     &lt;/provider&gt;
/// </pre>
///
/// When not using EmojiCompatInitializer, EmojiCompat must to be initialized manually using
/// \#init(EmojiCompat.Config). It is recommended to make the initialization as early as
/// possible in your app, such as from Application\#onCreate().
/// <p/>
/// \#init(Config) is fast and may be called from the main thread on the path to
/// displaying the first activity. However, loading the emoji font takes significant resources on a
/// background thread, so it is suggested to use \#LOAD_STRATEGY_MANUAL in all manual
/// configurations to defer font loading until after the first screen displays. Font loading may
/// be started by calling \#load()}. See the implementation EmojiCompatInitializer
/// for ideas when building a manual configuration.
/// <p/>
/// After initialization the \#get() function can be used to get the configured instance and
/// the \#process(CharSequence) function can be used to update a CharSequence with emoji
/// EmojiSpans.
/// <p/>
/// <pre><code>CharSequence processedSequence = EmojiCompat.get().process("some string")</pre>
/// <p/>
/// During loading information about emojis is not available. Before the
/// EmojiCompat instance has finished loading, calls to functions such as EmojiCompat\#process(CharSequence) will throw an exception. It is safe to call process when
/// \#getLoadState() returns \#LOAD_STATE_SUCCEEDED. To register a callback when
/// loading completes use InitCallback.
/// <p/>
class EmojiCompat extends jni.JObject {
  @override
  late final jni.JObjType<EmojiCompat> $type = type;

  EmojiCompat.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $EmojiCompatType();
  static final _get_EDITOR_INFO_METAVERSION_KEY =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_EmojiCompat__EDITOR_INFO_METAVERSION_KEY")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String EDITOR_INFO_METAVERSION_KEY
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Key in EditorInfo\#extras that represents the emoji metadata version used by the
  /// widget. The existence of the value means that the widget is using EmojiCompat.
  /// <p/>
  /// If exists, the value for the key is an {@code int} and can be used to query EmojiCompat to
  /// see whether the widget has the ability to display a certain emoji using
  /// \#hasEmojiGlyph(CharSequence, int).
  static jni.JString get EDITOR_INFO_METAVERSION_KEY => const jni.JStringType()
      .fromRef(_get_EDITOR_INFO_METAVERSION_KEY().object);

  static final _get_EDITOR_INFO_REPLACE_ALL_KEY =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String EDITOR_INFO_REPLACE_ALL_KEY
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Key in EditorInfo\#extras that represents EmojiCompat.Config\#setReplaceAll(boolean) configuration parameter. The key is added only if
  /// EmojiCompat is used by the widget. If exists, the value is a boolean.
  static jni.JString get EDITOR_INFO_REPLACE_ALL_KEY => const jni.JStringType()
      .fromRef(_get_EDITOR_INFO_REPLACE_ALL_KEY().object);

  /// from: static public final int LOAD_STATE_DEFAULT
  ///
  /// EmojiCompat instance is constructed, however the initialization did not start yet.
  ///@see \#getLoadState()
  static const LOAD_STATE_DEFAULT = 3;

  /// from: static public final int LOAD_STATE_LOADING
  ///
  /// EmojiCompat is initializing.
  ///@see \#getLoadState()
  static const LOAD_STATE_LOADING = 0;

  /// from: static public final int LOAD_STATE_SUCCEEDED
  ///
  /// EmojiCompat successfully initialized.
  ///@see \#getLoadState()
  static const LOAD_STATE_SUCCEEDED = 1;

  /// from: static public final int LOAD_STATE_FAILED
  ///
  /// An unrecoverable error occurred during initialization of EmojiCompat. Calls to functions
  /// such as \#process(CharSequence) will fail.
  ///@see \#getLoadState()
  static const LOAD_STATE_FAILED = 2;

  /// from: static public final int REPLACE_STRATEGY_DEFAULT
  ///
  /// Replace strategy that uses the value given in EmojiCompat.Config.
  ///@see \#process(CharSequence, int, int, int, int)
  static const REPLACE_STRATEGY_DEFAULT = 0;

  /// from: static public final int REPLACE_STRATEGY_ALL
  ///
  /// Replace strategy to add EmojiSpans for all emoji that were found.
  ///@see \#process(CharSequence, int, int, int, int)
  static const REPLACE_STRATEGY_ALL = 1;

  /// from: static public final int REPLACE_STRATEGY_NON_EXISTENT
  ///
  /// Replace strategy to add EmojiSpans only for emoji that do not exist in the system.
  static const REPLACE_STRATEGY_NON_EXISTENT = 2;

  /// from: static public final int LOAD_STRATEGY_DEFAULT
  ///
  /// EmojiCompat will start loading metadata when \#init(Config) is called.
  ///@see Config\#setMetadataLoadStrategy(int)
  static const LOAD_STRATEGY_DEFAULT = 0;

  /// from: static public final int LOAD_STRATEGY_MANUAL
  ///
  /// EmojiCompat will wait for \#load() to be called by developer in order to
  /// start loading metadata.
  ///@see Config\#setMetadataLoadStrategy(int)
  static const LOAD_STRATEGY_MANUAL = 1;

  /// from: static public final int EMOJI_UNSUPPORTED
  ///
  /// Result of \#getEmojiMatch(CharSequence, int) that means no part of this codepoint
  /// sequence will ever generate an EmojiSpan at the requested metadata level.
  ///
  /// This return value implies:
  /// - EmojiCompat will always defer to system emoji font
  /// - System emoji font may or may not support this emoji
  /// - This application MAY render this emoji
  ///
  /// This can be used by keyboards to learn that EmojiCompat does not support this codepoint
  /// sequence at this metadata version. The system emoji font is not checked by this method,
  /// and this result will be returned even if the system emoji font supports the emoji. This may
  /// happen if the application is using an older version of the emoji compat font than the
  /// system emoji font.
  ///
  /// Keyboards may optionally determine that the system emoji font will support the emoji, for
  /// example by building a internal lookup table or calling
  /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) to query the system
  /// emoji font. Keyboards may use a lookup table to optimize this check, however they should be
  /// aware that OEMs may add or remove emoji from the system emoji font.
  ///
  /// Keyboards may finally decide:
  /// - If the system emoji font DOES NOT support the emoji, then the emoji IS NOT supported by
  /// this application.
  /// - If the system emoji font DOES support the emoji, then the emoji IS supported by this
  /// application.
  /// - If system emoji font is support is UNKNOWN, then assume the emoji IS NOT supported by
  /// this application.
  static const EMOJI_UNSUPPORTED = 0;

  /// from: static public final int EMOJI_SUPPORTED
  ///
  /// Result of \#getEmojiMatch(CharSequence, int) that means this codepoint can be drawn
  /// by an EmojiSpan at this metadata level.
  ///
  /// No further checks are required by keyboards for this result. The emoji is always supported
  /// by this application.
  ///
  /// This return value implies:
  /// - EmojiCompat can draw this emoji
  /// - System emoji font may or may not support this emoji
  /// - This application WILL render this emoji
  ///
  /// This result implies that EmojiCompat can successfully display this emoji. The system emoji
  /// font is not checked by this method, and this result may be returned even if the platform
  /// also supports the emoji sequence.
  ///
  /// If the application passes EmojiCompat\#REPLACE_STRATEGY_ALL of true, then an
  /// EmojiSpan will always be generated for this emoji.
  ///
  /// If the application passes EmojiCompat\#REPLACE_STRATEGY_ALL of false, then an
  /// EmojiSpan will only be generated if
  /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String)
  /// returns false for this emoji.
  static const EMOJI_SUPPORTED = 1;

  /// from: static public final int EMOJI_FALLBACK
  ///
  /// Result of \#getEmojiMatch(CharSequence, int) that means the full codepoint sequence
  /// is not known to emojicompat, but at least one subsequence is an emoji that is known at
  /// this metadata level.
  ///
  /// Keyboards may decide that this emoji is not supported by the application when this result is
  /// returned, with no further processing.
  ///
  /// This return value implies:
  /// - EmojiCompat will decompose this ZWJ sequence into multiple glyphs when replaceAll=true
  /// - EmojiCompat MAY defer to platform when replaceAll=false
  /// - System emoji font may or may not support this emoji
  /// - This application MAY render this emoji
  ///
  /// This return value is only ever returned for ZWJ sequences. To understand this result
  /// consider when it may be returned for the multi-skin-tone handshake introduced in emoji 14.
  ///
  /// <pre>
  ///     U+1FAF1 // unknown @ requested metadata level
  ///     U+1F3FB // metadata level 1
  ///     U+200D  // not displayed (ZWJ)
  ///     U+1FAF2 // unknown @ requested metadata level
  ///     U+1F3FD // metadata level 1
  /// </pre>
  ///
  /// In this codepoint sequence, U+1F3FB and U+1F3FD are known from metadata level 1. When an
  /// application is using a metadata level that doesn't understand this ZWJ and provides
  /// EmojiCompat\#REPLACE_STRATEGY_ALL true, the color emoji are matched and replaced
  /// with EmojiSpan. The system emoji font, even if it supports this ZWJ sequence, is
  /// never queried and the added EmojiSpans force fallback rendering for the ZWJ sequence.
  ///
  /// The glyph will only display correctly for this application if ALL of the following
  /// requirements are met:
  /// - EmojiCompat\#REPLACE_STRATEGY_ALL is false
  /// - androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) returns true for each
  /// emoji subsequence known at this metadata level
  /// - androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) returns true for the
  /// full sequence
  ///
  /// Given this return value for the multi-skin-tone handshake above, if
  /// EmojiCompat\#REPLACE_STRATEGY_ALL is false then the emoji will display if the
  /// entire emoji sequence is matched by
  /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) because U+1F3FB and
  /// U+1F3FD are both in the system emoji font.
  ///
  /// Keyboards that wish to determine if the glyph will display correctly by the application in
  /// response to this return value should consider building an internal lookup for new ZWJ
  /// sequences instead of repeatedly calling
  /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) for each emoji
  /// subsequence.
  static const EMOJI_FALLBACK = 2;
  static final _init = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__init")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.EmojiCompat init(android.content.Context context)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Initialize the singleton instance with the default system-provided configuration.
  ///
  /// This is the recommended configuration for most applications. For more details see
  /// DefaultEmojiCompatConfig.
  ///
  ///
  /// This call will use DefaultEmojiCompatConfig to lookup the default emoji font
  /// provider installed on the system and use that, if present. If there is no default font
  /// provider onthe system, this call will have no effect.
  ///
  ///
  /// Note: EmojiCompat may only be initialized once, and will return the same instance
  /// afterwords.
  ///
  ///@return Default EmojiCompat for this device, or null if there is no provider on the system.
  static EmojiCompat init(
    jni.JObject context,
  ) {
    return const $EmojiCompatType()
        .fromRef(_init(context.reference.pointer).object);
  }

  static final _init1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__init1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.EmojiCompat init(android.content.Context context, androidx.emoji2.text.DefaultEmojiCompatConfig.DefaultEmojiCompatConfigFactory defaultFactory)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// @hide
  static EmojiCompat init1(
    jni.JObject context,
    DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory defaultFactory,
  ) {
    return const $EmojiCompatType().fromRef(
        _init1(context.reference.pointer, defaultFactory.reference.pointer)
            .object);
  }

  static final _init2 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__init2")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config config)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Initialize the singleton instance with a configuration. When used on devices running API 18
  /// or below, the singleton instance is immediately moved into \#LOAD_STATE_SUCCEEDED
  /// state without loading any metadata. When called for the first time, the library will create
  /// the singleton instance and any call after that will not create a new instance and return
  /// immediately.
  ///@see EmojiCompat.Config
  static EmojiCompat init2(
    EmojiCompat_Config config,
  ) {
    return const $EmojiCompatType()
        .fromRef(_init2(config.reference.pointer).object);
  }

  static final _isConfigured =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "EmojiCompat__isConfigured")
          .asFunction<jni.JniResult Function()>();

  /// from: static public boolean isConfigured()
  ///
  /// Return true if EmojiCompat has been configured by a successful call to
  /// EmojiCompat\#init.
  ///
  /// You can use this to check if EmojiCompat\#get() will return a valid EmojiCompat
  /// instance.
  ///
  /// This function does not check the \#getLoadState() and will return true even if the
  /// font is still loading, or has failed to load.
  ///@return true if EmojiCompat has been successfully initialized.
  static bool isConfigured() {
    return _isConfigured().boolean;
  }

  static final _reset = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__reset")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.EmojiCompat reset(androidx.emoji2.text.EmojiCompat.Config config)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Used by the tests to reset EmojiCompat with a new configuration. Every time it is called a
  /// new instance is created with the new configuration.
  ///@hide
  static EmojiCompat reset(
    EmojiCompat_Config config,
  ) {
    return const $EmojiCompatType()
        .fromRef(_reset(config.reference.pointer).object);
  }

  static final _reset1 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__reset1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.EmojiCompat reset(androidx.emoji2.text.EmojiCompat emojiCompat)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Used by the tests to reset EmojiCompat with a new singleton instance.
  ///@hide
  static EmojiCompat reset1(
    EmojiCompat emojiCompat,
  ) {
    return const $EmojiCompatType()
        .fromRef(_reset1(emojiCompat.reference.pointer).object);
  }

  static final _skipDefaultConfigurationLookup =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint8)>>(
              "EmojiCompat__skipDefaultConfigurationLookup")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public void skipDefaultConfigurationLookup(boolean shouldSkip)
  ///
  /// Reset default configuration lookup flag, for tests.
  ///@hide
  static void skipDefaultConfigurationLookup(
    bool shouldSkip,
  ) {
    return _skipDefaultConfigurationLookup(shouldSkip ? 1 : 0).check();
  }

  static final _get0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "EmojiCompat__get0")
      .asFunction<jni.JniResult Function()>();

  /// from: static public androidx.emoji2.text.EmojiCompat get()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Return singleton EmojiCompat instance. Should be called after
  /// \#init(EmojiCompat.Config) is called to initialize the singleton instance.
  ///@return EmojiCompat instance
  ///@throws IllegalStateException if called before \#init(EmojiCompat.Config)
  static EmojiCompat get0() {
    return const $EmojiCompatType().fromRef(_get0().object);
  }

  static final _load = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__load")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void load()
  ///
  /// When Config\#setMetadataLoadStrategy(int) is set to \#LOAD_STRATEGY_MANUAL,
  /// this function starts loading the metadata. Calling the function when
  /// Config\#setMetadataLoadStrategy(int) is {@code not} set to
  /// \#LOAD_STRATEGY_MANUAL will throw an exception. The load will {@code not} start if:
  /// <ul>
  ///     <li>the metadata is already loaded successfully and \#getLoadState() is
  ///     \#LOAD_STATE_SUCCEEDED.
  ///     </li>
  ///      <li>a previous load attempt is not finished yet and \#getLoadState() is
  ///     \#LOAD_STATE_LOADING.</li>
  /// </ul>
  ///@throws IllegalStateException when Config\#setMetadataLoadStrategy(int) is not set
  /// to \#LOAD_STRATEGY_MANUAL
  void load() {
    return _load(reference.pointer).check();
  }

  static final _registerInitCallback = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__registerInitCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
  ///
  /// Registers an initialization callback. If the initialization is already completed by the time
  /// the listener is added, the callback functions are called immediately. Callbacks are called on
  /// the main looper.
  /// <p/>
  /// When used on devices running API 18 or below, InitCallback\#onInitialized() is called
  /// without loading any metadata. In such cases InitCallback\#onFailed(Throwable) is never
  /// called.
  ///@param initCallback the initialization callback to register, cannot be {@code null}
  ///@see \#unregisterInitCallback(InitCallback)
  void registerInitCallback(
    EmojiCompat_InitCallback initCallback,
  ) {
    return _registerInitCallback(
            reference.pointer, initCallback.reference.pointer)
        .check();
  }

  static final _unregisterInitCallback = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__unregisterInitCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
  ///
  /// Unregisters a callback that was added before.
  ///@param initCallback the callback to be removed, cannot be {@code null}
  void unregisterInitCallback(
    EmojiCompat_InitCallback initCallback,
  ) {
    return _unregisterInitCallback(
            reference.pointer, initCallback.reference.pointer)
        .check();
  }

  static final _getLoadState = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__getLoadState")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public int getLoadState()
  ///
  /// Returns loading state of the EmojiCompat instance. When used on devices running API 18 or
  /// below always returns \#LOAD_STATE_SUCCEEDED.
  ///@return one of \#LOAD_STATE_DEFAULT, \#LOAD_STATE_LOADING,
  /// \#LOAD_STATE_SUCCEEDED, \#LOAD_STATE_FAILED
  int getLoadState() {
    return _getLoadState(reference.pointer).integer;
  }

  static final _isEmojiSpanIndicatorEnabled = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__isEmojiSpanIndicatorEnabled")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public boolean isEmojiSpanIndicatorEnabled()
  ///
  /// @return whether a background should be drawn for the emoji for debugging
  ///@hide
  bool isEmojiSpanIndicatorEnabled() {
    return _isEmojiSpanIndicatorEnabled(reference.pointer).boolean;
  }

  static final _getEmojiSpanIndicatorColor = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__getEmojiSpanIndicatorColor")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public int getEmojiSpanIndicatorColor()
  ///
  /// @return color of background drawn if EmojiCompat\#isEmojiSpanIndicatorEnabled is true
  ///@hide
  int getEmojiSpanIndicatorColor() {
    return _getEmojiSpanIndicatorColor(reference.pointer).integer;
  }

  static final _getEmojiStart = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat__getEmojiStart")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public int getEmojiStart(java.lang.CharSequence charSequence, int offset)
  ///
  /// Together with \#getEmojiEnd(CharSequence, int), if the character at {@code offset} is
  /// part of an emoji, returns the index range of that emoji, start index inclusively/end index
  /// exclusively so that {@code charSequence.subSequence(start, end)} will return that emoji.
  /// E.g., getEmojiStart/End("AB\ud83d\ude00", 1) will return (-1,-1) since 'B' is not part an emoji;
  ///       getEmojiStart/End("AB\ud83d\ude00", 3) will return [2,4), note that "\ud83d\ude00" contains 2 Chars.
  /// Returns -1 otherwise.
  ///@param charSequence the whole sequence
  ///@param offset index of the emoji to look up
  ///@return the start index inclusively/end index exclusively
  int getEmojiStart(
    jni.JObject charSequence,
    int offset,
  ) {
    return _getEmojiStart(
            reference.pointer, charSequence.reference.pointer, offset)
        .integer;
  }

  static final _getEmojiEnd = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat__getEmojiEnd")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public int getEmojiEnd(java.lang.CharSequence charSequence, int offset)
  ///
  /// see \#getEmojiStart(CharSequence, int).
  int getEmojiEnd(
    jni.JObject charSequence,
    int offset,
  ) {
    return _getEmojiEnd(
            reference.pointer, charSequence.reference.pointer, offset)
        .integer;
  }

  static final _handleOnKeyDown = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__handleOnKeyDown")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();

  /// from: static public boolean handleOnKeyDown(android.text.Editable editable, int keyCode, android.view.KeyEvent event)
  ///
  /// Handles onKeyDown commands from a KeyListener and if {@code keyCode} is one of
  /// KeyEvent\#KEYCODE_DEL or KeyEvent\#KEYCODE_FORWARD_DEL it tries to delete an
  /// EmojiSpan from an Editable. Returns {@code true} if an EmojiSpan is
  /// deleted with the characters it covers.
  /// <p/>
  /// If there is a selection where selection start is not equal to selection end, does not
  /// delete.
  /// <p/>
  /// When used on devices running API 18 or below, always returns {@code false}.
  ///@param editable Editable instance passed to KeyListener\#onKeyDown(android.view.View,
  ///                 Editable, int, KeyEvent)
  ///@param keyCode keyCode passed to KeyListener\#onKeyDown(android.view.View, Editable,
  ///                int, KeyEvent)
  ///@param event KeyEvent passed to KeyListener\#onKeyDown(android.view.View, Editable,
  ///              int, KeyEvent)
  ///@return {@code true} if an EmojiSpan is deleted
  static bool handleOnKeyDown(
    jni.JObject editable,
    int keyCode,
    jni.JObject event,
  ) {
    return _handleOnKeyDown(
            editable.reference.pointer, keyCode, event.reference.pointer)
        .boolean;
  }

  static final _handleDeleteSurroundingText = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32,
                  ffi.Uint8)>>("EmojiCompat__handleDeleteSurroundingText")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();

  /// from: static public boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection inputConnection, android.text.Editable editable, int beforeLength, int afterLength, boolean inCodePoints)
  ///
  /// Handles deleteSurroundingText commands from InputConnection and tries to delete an
  /// EmojiSpan from an Editable. Returns {@code true} if an EmojiSpan is
  /// deleted.
  /// <p/>
  /// If there is a selection where selection start is not equal to selection end, does not
  /// delete.
  /// <p/>
  /// When used on devices running API 18 or below, always returns {@code false}.
  ///@param inputConnection InputConnection instance
  ///@param editable TextView.Editable instance
  ///@param beforeLength the number of characters before the cursor to be deleted
  ///@param afterLength the number of characters after the cursor to be deleted
  ///@param inCodePoints {@code true} if length parameters are in codepoints
  ///@return {@code true} if an EmojiSpan is deleted
  static bool handleDeleteSurroundingText(
    jni.JObject inputConnection,
    jni.JObject editable,
    int beforeLength,
    int afterLength,
    bool inCodePoints,
  ) {
    return _handleDeleteSurroundingText(
            inputConnection.reference.pointer,
            editable.reference.pointer,
            beforeLength,
            afterLength,
            inCodePoints ? 1 : 0)
        .boolean;
  }

  static final _hasEmojiGlyph = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__hasEmojiGlyph")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean hasEmojiGlyph(java.lang.CharSequence sequence)
  ///
  /// Returns {@code true} if EmojiCompat is capable of rendering an emoji. When used on devices
  /// running API 18 or below, always returns {@code false}.
  ///@deprecated use getEmojiMatch which returns more accurate lookup information.
  ///@param sequence CharSequence representing the emoji
  ///@return {@code true} if EmojiCompat can render given emoji, cannot be {@code null}
  ///@throws IllegalStateException if not initialized yet
  bool hasEmojiGlyph(
    jni.JObject sequence,
  ) {
    return _hasEmojiGlyph(reference.pointer, sequence.reference.pointer)
        .boolean;
  }

  static final _hasEmojiGlyph1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat__hasEmojiGlyph1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public boolean hasEmojiGlyph(java.lang.CharSequence sequence, int metadataVersion)
  ///
  /// Returns {@code true} if EmojiCompat is capable of rendering an emoji at the given metadata
  /// version. When used on devices running API 18 or below, always returns {@code false}.
  ///@deprecated use getEmojiMatch which returns more accurate lookup information.
  ///@param sequence CharSequence representing the emoji
  ///@param metadataVersion the metadata version to check against, should be greater than or
  ///                        equal to {@code 0},
  ///@return {@code true} if EmojiCompat can render given emoji, cannot be {@code null}
  ///@throws IllegalStateException if not initialized yet
  bool hasEmojiGlyph1(
    jni.JObject sequence,
    int metadataVersion,
  ) {
    return _hasEmojiGlyph1(
            reference.pointer, sequence.reference.pointer, metadataVersion)
        .boolean;
  }

  static final _getEmojiMatch = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("EmojiCompat__getEmojiMatch")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public int getEmojiMatch(java.lang.CharSequence sequence, int metadataVersion)
  ///
  /// Attempts to lookup the entire sequence at the specified metadata version and returns what
  /// the runtime match behavior would be.
  ///
  /// To be used by keyboards to show or hide emoji in response to specific metadata support.
  ///@see \#EMOJI_SUPPORTED
  ///@see \#EMOJI_UNSUPPORTED
  ///@see \#EMOJI_FALLBACK
  ///@param sequence CharSequence representing an emoji
  ///@param metadataVersion the metada version to check against, should be greater than or
  ///                        equal to {@code 0},
  ///@return A match result, or decomposes if replaceAll would cause partial subsequence matches.
  int getEmojiMatch(
    jni.JObject sequence,
    int metadataVersion,
  ) {
    return _getEmojiMatch(
            reference.pointer, sequence.reference.pointer, metadataVersion)
        .integer;
  }

  static final _process = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__process")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found. When
  /// used on devices running API 18 or below, returns the given {@code charSequence} without
  /// processing it.
  ///@param charSequence CharSequence to add the EmojiSpans
  ///@throws IllegalStateException if not initialized yet
  ///@see \#process(CharSequence, int, int)
  jni.JObject process(
    jni.JObject charSequence,
  ) {
    return const jni.JObjectType().fromRef(
        _process(reference.pointer, charSequence.reference.pointer).object);
  }

  static final _process1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32)>>("EmojiCompat__process1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
  ///
  /// <ul>
  /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
  /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
  /// returned.</li>
  /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
  /// a new android.text.Spannable instance is returned. </li>
  /// <li>If the given input is a Spannable, the same instance is returned. </li>
  /// </ul>
  /// When used on devices running API 18 or below, returns the given {@code charSequence} without
  /// processing it.
  ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
  ///@param start start index in the charSequence to look for emojis, should be greater than or
  ///              equal to {@code 0}, also less than or equal to {@code charSequence.length()}
  ///@param end end index in the charSequence to look for emojis, should be greater than or equal
  ///              to {@code start} parameter, also less than or equal to
  ///              {@code charSequence.length()}
  ///@throws IllegalStateException if not initialized yet
  ///@throws IllegalArgumentException in the following cases:
  ///                                  {@code start < 0}, {@code end < 0}, {@code end < start},
  ///                                  {@code start > charSequence.length()},
  ///                                  {@code end > charSequence.length()}
  jni.JObject process1(
    jni.JObject charSequence,
    int start,
    int end,
  ) {
    return const jni.JObjectType().fromRef(
        _process1(reference.pointer, charSequence.reference.pointer, start, end)
            .object);
  }

  static final _process2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32,
                  ffi.Int32)>>("EmojiCompat__process2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();

  /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end, int maxEmojiCount)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
  ///
  /// <ul>
  /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
  /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
  /// returned.</li>
  /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
  /// a new android.text.Spannable instance is returned. </li>
  /// <li>If the given input is a Spannable, the same instance is returned. </li>
  /// </ul>
  /// When used on devices running API 18 or below, returns the given {@code charSequence} without
  /// processing it.
  ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
  ///@param start start index in the charSequence to look for emojis, should be greater than or
  ///              equal to {@code 0}, also less than or equal to {@code charSequence.length()}
  ///@param end end index in the charSequence to look for emojis, should be greater than or
  ///            equal to {@code start} parameter, also less than or equal to
  ///            {@code charSequence.length()}
  ///@param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater
  ///                      than or equal to {@code 0}
  ///@throws IllegalStateException if not initialized yet
  ///@throws IllegalArgumentException in the following cases:
  ///                                  {@code start < 0}, {@code end < 0}, {@code end < start},
  ///                                  {@code start > charSequence.length()},
  ///                                  {@code end > charSequence.length()}
  ///                                  {@code maxEmojiCount < 0}
  jni.JObject process2(
    jni.JObject charSequence,
    int start,
    int end,
    int maxEmojiCount,
  ) {
    return const jni.JObjectType().fromRef(_process2(reference.pointer,
            charSequence.reference.pointer, start, end, maxEmojiCount)
        .object);
  }

  static final _process3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32,
                  ffi.Int32,
                  ffi.Int32)>>("EmojiCompat__process3")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              int, int, int, int)>();

  /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end, int maxEmojiCount, int replaceStrategy)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
  ///
  /// <ul>
  /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
  /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
  /// returned.</li>
  /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
  /// a new android.text.Spannable instance is returned. </li>
  /// <li>If the given input is a Spannable, the same instance is returned. </li>
  /// </ul>
  /// When used on devices running API 18 or below, returns the given {@code charSequence} without
  /// processing it.
  ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
  ///@param start start index in the charSequence to look for emojis, should be greater than or
  ///              equal to {@code 0}, also less than or equal to {@code charSequence.length()}
  ///@param end end index in the charSequence to look for emojis, should be greater than or
  ///            equal to {@code start} parameter, also less than or equal to
  ///            {@code charSequence.length()}
  ///@param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater
  ///                      than or equal to {@code 0}
  ///@param replaceStrategy whether to replace all emoji with EmojiSpans, should be one of
  ///                        \#REPLACE_STRATEGY_DEFAULT,
  ///                        \#REPLACE_STRATEGY_NON_EXISTENT,
  ///                        \#REPLACE_STRATEGY_ALL
  ///@throws IllegalStateException if not initialized yet
  ///@throws IllegalArgumentException in the following cases:
  ///                                  {@code start < 0}, {@code end < 0}, {@code end < start},
  ///                                  {@code start > charSequence.length()},
  ///                                  {@code end > charSequence.length()}
  ///                                  {@code maxEmojiCount < 0}
  jni.JObject process3(
    jni.JObject charSequence,
    int start,
    int end,
    int maxEmojiCount,
    int replaceStrategy,
  ) {
    return const jni.JObjectType().fromRef(_process3(
            reference.pointer,
            charSequence.reference.pointer,
            start,
            end,
            maxEmojiCount,
            replaceStrategy)
        .object);
  }

  static final _getAssetSignature = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "EmojiCompat__getAssetSignature")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String getAssetSignature()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns signature for the currently loaded emoji assets. The signature is a SHA that is
  /// constructed using emoji assets. Can be used to detect if currently loaded asset is different
  /// then previous executions. When used on devices running API 18 or below, returns empty string.
  ///@throws IllegalStateException if not initialized yet
  jni.JString getAssetSignature() {
    return const jni.JStringType()
        .fromRef(_getAssetSignature(reference.pointer).object);
  }

  static final _updateEditorInfo = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("EmojiCompat__updateEditorInfo")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void updateEditorInfo(android.view.inputmethod.EditorInfo outAttrs)
  ///
  /// Updates the EditorInfo attributes in order to communicate information to Keyboards. When
  /// used on devices running API 18 or below, does not update EditorInfo attributes.
  ///
  /// This is called from EditText integrations that use EmojiEditTextHelper. Custom
  /// widgets that allow IME not subclassing EditText should call this method when creating an
  /// input connection.
  ///
  /// When EmojiCompat is not in \#LOAD_STATE_SUCCEEDED, this method has no effect.
  ///
  /// Calling this method on API levels below API 19 will have no effect, as EmojiCompat may
  /// never be configured. However, it is always safe to call, even on older API levels.
  ///@param outAttrs EditorInfo instance passed to
  ///                 android.widget.TextView\#onCreateInputConnection(EditorInfo)
  ///@see \#EDITOR_INFO_METAVERSION_KEY
  ///@see \#EDITOR_INFO_REPLACE_ALL_KEY
  void updateEditorInfo(
    jni.JObject outAttrs,
  ) {
    return _updateEditorInfo(reference.pointer, outAttrs.reference.pointer)
        .check();
  }
}

final class $EmojiCompatType extends jni.JObjType<EmojiCompat> {
  const $EmojiCompatType();

  @override
  String get signature => r"Landroidx/emoji2/text/EmojiCompat;";

  @override
  EmojiCompat fromRef(jni.JObjectPtr ref) => EmojiCompat.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($EmojiCompatType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($EmojiCompatType) && other is $EmojiCompatType;
  }
}

/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory
///
/// Actual factory for generating default emoji configs, does service locator lookup internally.
///@see DefaultEmojiCompatConfig\#create
///@hide
class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory
    extends jni.JObject {
  @override
  late final jni
      .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory>
      $type = type;

  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type =
      $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType();
  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(androidx.emoji2.text.DefaultEmojiCompatConfig.DefaultEmojiCompatConfigHelper helper)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// @hide
  factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory(
    DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper helper,
  ) {
    return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(
        _new0(helper.reference.pointer).object);
  }

  static final _create = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public androidx.emoji2.text.EmojiCompat.Config create(android.content.Context context)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// @see DefaultEmojiCompatConfig\#create
  ///@hide
  EmojiCompat_Config create(
    jni.JObject context,
  ) {
    return const $EmojiCompat_ConfigType()
        .fromRef(_create(reference.pointer, context.reference.pointer).object);
  }
}

final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType
    extends jni
    .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory> {
  const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;";

  @override
  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory fromRef(
          jni.JObjectPtr ref) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode =>
      ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType ==
            ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType) &&
        other is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType;
  }
}

/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper
///
/// Helper to lookup signatures in package manager.
///@hide
class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper
    extends jni.JObject {
  @override
  late final jni
      .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper> $type =
      type;

  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type =
      $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper() {
    return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(
        _new0().object);
  }

  static final _getSigningSignatures = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public android.content.pm.Signature[] getSigningSignatures(android.content.pm.PackageManager packageManager, java.lang.String providerPackage)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Get the signing signatures for a package in package manager.
  jni.JArray<jni.JObject> getSigningSignatures(
    jni.JObject packageManager,
    jni.JString providerPackage,
  ) {
    return const jni.JArrayType(jni.JObjectType()).fromRef(
        _getSigningSignatures(
                reference.pointer,
                packageManager.reference.pointer,
                providerPackage.reference.pointer)
            .object);
  }

  static final _queryIntentContentProviders = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Int32)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, int)>();

  /// from: public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.pm.PackageManager packageManager, android.content.Intent intent, int flags)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Get the content provider by intent.
  jni.JList<jni.JObject> queryIntentContentProviders(
    jni.JObject packageManager,
    jni.JObject intent,
    int flags,
  ) {
    return const jni.JListType(jni.JObjectType()).fromRef(
        _queryIntentContentProviders(
                reference.pointer,
                packageManager.reference.pointer,
                intent.reference.pointer,
                flags)
            .object);
  }

  static final _getProviderInfo = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public android.content.pm.ProviderInfo getProviderInfo(android.content.pm.ResolveInfo resolveInfo)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Get a ProviderInfo, if present, from a ResolveInfo
  ///@param resolveInfo the subject
  ///@return resolveInfo.providerInfo above API 19
  jni.JObject getProviderInfo(
    jni.JObject resolveInfo,
  ) {
    return const jni.JObjectType().fromRef(
        _getProviderInfo(reference.pointer, resolveInfo.reference.pointer)
            .object);
  }
}

final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType
    extends jni
    .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper> {
  const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;";

  @override
  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper fromRef(
          jni.JObjectPtr ref) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode =>
      ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType ==
            ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType) &&
        other is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType;
  }
}

/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19
///
/// Actually do lookups > API 19
///@hide
class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19
    extends DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper {
  @override
  late final jni
      .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19>
      $type = type;

  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type =
      $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19() {
    return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19
        .fromRef(_new0().object);
  }

  static final _queryIntentContentProviders = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Int32)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, int)>();

  /// from: public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.pm.PackageManager packageManager, android.content.Intent intent, int flags)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JList<jni.JObject> queryIntentContentProviders(
    jni.JObject packageManager,
    jni.JObject intent,
    int flags,
  ) {
    return const jni.JListType(jni.JObjectType()).fromRef(
        _queryIntentContentProviders(
                reference.pointer,
                packageManager.reference.pointer,
                intent.reference.pointer,
                flags)
            .object);
  }

  static final _getProviderInfo = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public android.content.pm.ProviderInfo getProviderInfo(android.content.pm.ResolveInfo resolveInfo)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject getProviderInfo(
    jni.JObject resolveInfo,
  ) {
    return const jni.JObjectType().fromRef(
        _getProviderInfo(reference.pointer, resolveInfo.reference.pointer)
            .object);
  }
}

final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type
    extends jni
    .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19> {
  const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;";

  @override
  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 fromRef(
          jni.JObjectPtr ref) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19.fromRef(
          ref);

  @override
  jni.JObjType get superType =>
      const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();

  @override
  final superCount = 2;

  @override
  int get hashCode =>
      ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type)
          .hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType ==
            ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type) &&
        other
            is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type;
  }
}

/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28
///
/// Helper to lookup signatures in package manager > API 28
///@hide
class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28
    extends DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 {
  @override
  late final jni
      .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28>
      $type = type;

  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type =
      $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28() {
    return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28
        .fromRef(_new0().object);
  }

  static final _getSigningSignatures1 = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public android.content.pm.Signature[] getSigningSignatures(android.content.pm.PackageManager packageManager, java.lang.String providerPackage)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JArray<jni.JObject> getSigningSignatures1(
    jni.JObject packageManager,
    jni.JString providerPackage,
  ) {
    return const jni.JArrayType(jni.JObjectType()).fromRef(
        _getSigningSignatures1(
                reference.pointer,
                packageManager.reference.pointer,
                providerPackage.reference.pointer)
            .object);
  }
}

final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type
    extends jni
    .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28> {
  const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type();

  @override
  String get signature =>
      r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28;";

  @override
  DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 fromRef(
          jni.JObjectPtr ref) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28.fromRef(
          ref);

  @override
  jni.JObjType get superType =>
      const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();

  @override
  final superCount = 3;

  @override
  int get hashCode =>
      ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type)
          .hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType ==
            ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type) &&
        other
            is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type;
  }
}

/// from: androidx.emoji2.text.DefaultEmojiCompatConfig
///
/// The default config will use downloadable fonts to fetch the emoji compat font file.
///
/// It will automatically fetch the emoji compat font from a {@code ContentProvider} that is
/// installed on the devices system image, if present.
///
///
/// You should use this if you want the default emoji font from a system installed
/// downloadable fonts provider. This is the recommended behavior for all applications unless
/// they install a custom emoji font.
///
///
/// You may need to specialize the configuration beyond this default config in some
/// situations:
///
/// <ul>
///  <li>If you are trying to install a custom emoji font through downloadable fonts use
///  FontRequestEmojiCompatConfig instead of this method.</li>
///  <li>If you're trying to bundle an emoji font with your APK use {@code
///  BundledEmojiCompatConfig} in the {@code emoji2-bundled} artifact.</li>
///  <li>If you are building an APK that will be installed on devices that won't have a
///  downloadable fonts provider, use {@code BundledEmojiCompatConfig}.</li>
/// </ul>
///
/// The downloadable font provider used by {@code DefaultEmojiCompatConfig} always satisfies
/// the following contract:
///
/// <ol>
///  <li>It <i>MUST</i> provide an intent filter for {@code androidx.content.action.LOAD_EMOJI_FONT}.
///  </li>
///  <li>It <i>MUST</i> respond to the query {@code emojicompat-emoji-font} with a valid emoji compat
///  font file including metadata.</li>
///  <li>It <i>MUST</i> provide fonts via the same contract as downloadable fonts.</li>
///  <li>It <i>MUST</i> be installed in the system image.</li>
/// </ol>
class DefaultEmojiCompatConfig extends jni.JObject {
  @override
  late final jni.JObjType<DefaultEmojiCompatConfig> $type = type;

  DefaultEmojiCompatConfig.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $DefaultEmojiCompatConfigType();
  static final _create = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "DefaultEmojiCompatConfig__create")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public androidx.emoji2.text.FontRequestEmojiCompatConfig create(android.content.Context context)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Get the default emoji compat config for this device.
  ///
  /// You may further configure the returned config before passing it to EmojiCompat\#init.
  ///
  /// Each call to this method will return a new EmojiCompat.Config, so changes to the returned
  /// object will not modify future return values.
  ///@param context context for lookup
  ///@return A valid config for downloading the emoji compat font, or null if no font provider
  /// could be found.
  static jni.JObject create(
    jni.JObject context,
  ) {
    return const jni.JObjectType()
        .fromRef(_create(context.reference.pointer).object);
  }
}

final class $DefaultEmojiCompatConfigType
    extends jni.JObjType<DefaultEmojiCompatConfig> {
  const $DefaultEmojiCompatConfigType();

  @override
  String get signature => r"Landroidx/emoji2/text/DefaultEmojiCompatConfig;";

  @override
  DefaultEmojiCompatConfig fromRef(jni.JObjectPtr ref) =>
      DefaultEmojiCompatConfig.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($DefaultEmojiCompatConfigType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($DefaultEmojiCompatConfigType) &&
        other is $DefaultEmojiCompatConfigType;
  }
}

/// from: android.os.Build$Partition
class Build_Partition extends jni.JObject {
  @override
  late final jni.JObjType<Build_Partition> $type = type;

  Build_Partition.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $Build_PartitionType();
  static final _get_PARTITION_NAME_SYSTEM =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_Partition__PARTITION_NAME_SYSTEM")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String PARTITION_NAME_SYSTEM
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get PARTITION_NAME_SYSTEM =>
      const jni.JStringType().fromRef(_get_PARTITION_NAME_SYSTEM().object);

  static final _getName = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Build_Partition__getName")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String getName()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString getName() {
    return const jni.JStringType().fromRef(_getName(reference.pointer).object);
  }

  static final _getFingerprint = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Build_Partition__getFingerprint")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String getFingerprint()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString getFingerprint() {
    return const jni.JStringType()
        .fromRef(_getFingerprint(reference.pointer).object);
  }

  static final _getBuildTimeMillis = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Build_Partition__getBuildTimeMillis")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public long getBuildTimeMillis()
  int getBuildTimeMillis() {
    return _getBuildTimeMillis(reference.pointer).long;
  }

  static final _equals1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Build_Partition__equals1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean equals(java.lang.Object object)
  bool equals1(
    jni.JObject object,
  ) {
    return _equals1(reference.pointer, object.reference.pointer).boolean;
  }

  static final _hashCode1 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Build_Partition__hashCode1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public int hashCode()
  int hashCode1() {
    return _hashCode1(reference.pointer).integer;
  }
}

final class $Build_PartitionType extends jni.JObjType<Build_Partition> {
  const $Build_PartitionType();

  @override
  String get signature => r"Landroid/os/Build$Partition;";

  @override
  Build_Partition fromRef(jni.JObjectPtr ref) => Build_Partition.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Build_PartitionType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Build_PartitionType) &&
        other is $Build_PartitionType;
  }
}

/// from: android.os.Build$VERSION
class Build_VERSION extends jni.JObject {
  @override
  late final jni.JObjType<Build_VERSION> $type = type;

  Build_VERSION.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $Build_VERSIONType();
  static final _get_BASE_OS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__BASE_OS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String BASE_OS
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get BASE_OS =>
      const jni.JStringType().fromRef(_get_BASE_OS().object);

  static final _get_CODENAME =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__CODENAME")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String CODENAME
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get CODENAME =>
      const jni.JStringType().fromRef(_get_CODENAME().object);

  static final _get_INCREMENTAL =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__INCREMENTAL")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String INCREMENTAL
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get INCREMENTAL =>
      const jni.JStringType().fromRef(_get_INCREMENTAL().object);

  static final _get_MEDIA_PERFORMANCE_CLASS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__MEDIA_PERFORMANCE_CLASS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final int MEDIA_PERFORMANCE_CLASS
  static int get MEDIA_PERFORMANCE_CLASS =>
      _get_MEDIA_PERFORMANCE_CLASS().integer;

  static final _get_PREVIEW_SDK_INT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__PREVIEW_SDK_INT")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final int PREVIEW_SDK_INT
  static int get PREVIEW_SDK_INT => _get_PREVIEW_SDK_INT().integer;

  static final _get_RELEASE =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__RELEASE")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String RELEASE
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get RELEASE =>
      const jni.JStringType().fromRef(_get_RELEASE().object);

  static final _get_RELEASE_OR_CODENAME =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__RELEASE_OR_CODENAME")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String RELEASE_OR_CODENAME
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get RELEASE_OR_CODENAME =>
      const jni.JStringType().fromRef(_get_RELEASE_OR_CODENAME().object);

  static final _get_RELEASE_OR_PREVIEW_DISPLAY =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String RELEASE_OR_PREVIEW_DISPLAY
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get RELEASE_OR_PREVIEW_DISPLAY =>
      const jni.JStringType().fromRef(_get_RELEASE_OR_PREVIEW_DISPLAY().object);

  static final _get_SDK =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__SDK")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SDK
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SDK =>
      const jni.JStringType().fromRef(_get_SDK().object);

  static final _get_SDK_INT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__SDK_INT")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final int SDK_INT
  static int get SDK_INT => _get_SDK_INT().integer;

  static final _get_SECURITY_PATCH =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build_VERSION__SECURITY_PATCH")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SECURITY_PATCH
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SECURITY_PATCH =>
      const jni.JStringType().fromRef(_get_SECURITY_PATCH().object);

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "Build_VERSION__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Build_VERSION() {
    return Build_VERSION.fromRef(_new0().object);
  }
}

final class $Build_VERSIONType extends jni.JObjType<Build_VERSION> {
  const $Build_VERSIONType();

  @override
  String get signature => r"Landroid/os/Build$VERSION;";

  @override
  Build_VERSION fromRef(jni.JObjectPtr ref) => Build_VERSION.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Build_VERSIONType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Build_VERSIONType) &&
        other is $Build_VERSIONType;
  }
}

/// from: android.os.Build$VERSION_CODES
class Build_VERSION_CODES extends jni.JObject {
  @override
  late final jni.JObjType<Build_VERSION_CODES> $type = type;

  Build_VERSION_CODES.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $Build_VERSION_CODESType();

  /// from: static public final int BASE
  static const BASE = 1;

  /// from: static public final int BASE_1_1
  static const BASE_1_1 = 2;

  /// from: static public final int CUPCAKE
  static const CUPCAKE = 3;

  /// from: static public final int CUR_DEVELOPMENT
  static const CUR_DEVELOPMENT = 10000;

  /// from: static public final int DONUT
  static const DONUT = 4;

  /// from: static public final int ECLAIR
  static const ECLAIR = 5;

  /// from: static public final int ECLAIR_0_1
  static const ECLAIR_0_1 = 6;

  /// from: static public final int ECLAIR_MR1
  static const ECLAIR_MR1 = 7;

  /// from: static public final int FROYO
  static const FROYO = 8;

  /// from: static public final int GINGERBREAD
  static const GINGERBREAD = 9;

  /// from: static public final int GINGERBREAD_MR1
  static const GINGERBREAD_MR1 = 10;

  /// from: static public final int HONEYCOMB
  static const HONEYCOMB = 11;

  /// from: static public final int HONEYCOMB_MR1
  static const HONEYCOMB_MR1 = 12;

  /// from: static public final int HONEYCOMB_MR2
  static const HONEYCOMB_MR2 = 13;

  /// from: static public final int ICE_CREAM_SANDWICH
  static const ICE_CREAM_SANDWICH = 14;

  /// from: static public final int ICE_CREAM_SANDWICH_MR1
  static const ICE_CREAM_SANDWICH_MR1 = 15;

  /// from: static public final int JELLY_BEAN
  static const JELLY_BEAN = 16;

  /// from: static public final int JELLY_BEAN_MR1
  static const JELLY_BEAN_MR1 = 17;

  /// from: static public final int JELLY_BEAN_MR2
  static const JELLY_BEAN_MR2 = 18;

  /// from: static public final int KITKAT
  static const KITKAT = 19;

  /// from: static public final int KITKAT_WATCH
  static const KITKAT_WATCH = 20;

  /// from: static public final int LOLLIPOP
  static const LOLLIPOP = 21;

  /// from: static public final int LOLLIPOP_MR1
  static const LOLLIPOP_MR1 = 22;

  /// from: static public final int M
  static const M = 23;

  /// from: static public final int N
  static const N = 24;

  /// from: static public final int N_MR1
  static const N_MR1 = 25;

  /// from: static public final int O
  static const O = 26;

  /// from: static public final int O_MR1
  static const O_MR1 = 27;

  /// from: static public final int P
  static const P = 28;

  /// from: static public final int Q
  static const Q = 29;

  /// from: static public final int R
  static const R = 30;

  /// from: static public final int S
  static const S = 31;

  /// from: static public final int S_V2
  static const S_V2 = 32;

  /// from: static public final int TIRAMISU
  static const TIRAMISU = 33;
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "Build_VERSION_CODES__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Build_VERSION_CODES() {
    return Build_VERSION_CODES.fromRef(_new0().object);
  }
}

final class $Build_VERSION_CODESType extends jni.JObjType<Build_VERSION_CODES> {
  const $Build_VERSION_CODESType();

  @override
  String get signature => r"Landroid/os/Build$VERSION_CODES;";

  @override
  Build_VERSION_CODES fromRef(jni.JObjectPtr ref) =>
      Build_VERSION_CODES.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Build_VERSION_CODESType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Build_VERSION_CODESType) &&
        other is $Build_VERSION_CODESType;
  }
}

/// from: android.os.Build
class Build extends jni.JObject {
  @override
  late final jni.JObjType<Build> $type = type;

  Build.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $BuildType();
  static final _get_BOARD =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__BOARD")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String BOARD
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get BOARD =>
      const jni.JStringType().fromRef(_get_BOARD().object);

  static final _get_BOOTLOADER =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__BOOTLOADER")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String BOOTLOADER
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get BOOTLOADER =>
      const jni.JStringType().fromRef(_get_BOOTLOADER().object);

  static final _get_BRAND =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__BRAND")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String BRAND
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get BRAND =>
      const jni.JStringType().fromRef(_get_BRAND().object);

  static final _get_CPU_ABI =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__CPU_ABI")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String CPU_ABI
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get CPU_ABI =>
      const jni.JStringType().fromRef(_get_CPU_ABI().object);

  static final _get_CPU_ABI2 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__CPU_ABI2")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String CPU_ABI2
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get CPU_ABI2 =>
      const jni.JStringType().fromRef(_get_CPU_ABI2().object);

  static final _get_DEVICE =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__DEVICE")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String DEVICE
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get DEVICE =>
      const jni.JStringType().fromRef(_get_DEVICE().object);

  static final _get_DISPLAY =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__DISPLAY")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String DISPLAY
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get DISPLAY =>
      const jni.JStringType().fromRef(_get_DISPLAY().object);

  static final _get_FINGERPRINT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__FINGERPRINT")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String FINGERPRINT
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get FINGERPRINT =>
      const jni.JStringType().fromRef(_get_FINGERPRINT().object);

  static final _get_HARDWARE =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__HARDWARE")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String HARDWARE
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get HARDWARE =>
      const jni.JStringType().fromRef(_get_HARDWARE().object);

  static final _get_HOST =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__HOST")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String HOST
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get HOST =>
      const jni.JStringType().fromRef(_get_HOST().object);

  static final _get_ID =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__ID")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String ID
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get ID =>
      const jni.JStringType().fromRef(_get_ID().object);

  static final _get_MANUFACTURER =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__MANUFACTURER")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String MANUFACTURER
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get MANUFACTURER =>
      const jni.JStringType().fromRef(_get_MANUFACTURER().object);

  static final _get_MODEL =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__MODEL")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String MODEL
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get MODEL =>
      const jni.JStringType().fromRef(_get_MODEL().object);

  static final _get_ODM_SKU =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__ODM_SKU")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String ODM_SKU
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get ODM_SKU =>
      const jni.JStringType().fromRef(_get_ODM_SKU().object);

  static final _get_PRODUCT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__PRODUCT")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String PRODUCT
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get PRODUCT =>
      const jni.JStringType().fromRef(_get_PRODUCT().object);

  static final _get_RADIO =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__RADIO")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String RADIO
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get RADIO =>
      const jni.JStringType().fromRef(_get_RADIO().object);

  static final _get_SERIAL =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SERIAL")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SERIAL
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SERIAL =>
      const jni.JStringType().fromRef(_get_SERIAL().object);

  static final _get_SKU =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__SKU")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SKU
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SKU =>
      const jni.JStringType().fromRef(_get_SKU().object);

  static final _get_SOC_MANUFACTURER =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SOC_MANUFACTURER")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SOC_MANUFACTURER
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SOC_MANUFACTURER =>
      const jni.JStringType().fromRef(_get_SOC_MANUFACTURER().object);

  static final _get_SOC_MODEL =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SOC_MODEL")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SOC_MODEL
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SOC_MODEL =>
      const jni.JStringType().fromRef(_get_SOC_MODEL().object);

  static final _get_SUPPORTED_32_BIT_ABIS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SUPPORTED_32_BIT_ABIS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String[] SUPPORTED_32_BIT_ABIS
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.JString> get SUPPORTED_32_BIT_ABIS =>
      const jni.JArrayType(jni.JStringType())
          .fromRef(_get_SUPPORTED_32_BIT_ABIS().object);

  static final _get_SUPPORTED_64_BIT_ABIS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SUPPORTED_64_BIT_ABIS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String[] SUPPORTED_64_BIT_ABIS
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.JString> get SUPPORTED_64_BIT_ABIS =>
      const jni.JArrayType(jni.JStringType())
          .fromRef(_get_SUPPORTED_64_BIT_ABIS().object);

  static final _get_SUPPORTED_ABIS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__SUPPORTED_ABIS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String[] SUPPORTED_ABIS
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.JString> get SUPPORTED_ABIS =>
      const jni.JArrayType(jni.JStringType())
          .fromRef(_get_SUPPORTED_ABIS().object);

  static final _get_TAGS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TAGS")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String TAGS
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get TAGS =>
      const jni.JStringType().fromRef(_get_TAGS().object);

  static final _get_TIME =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TIME")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final long TIME
  static int get TIME => _get_TIME().long;

  static final _get_TYPE =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TYPE")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String TYPE
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get TYPE =>
      const jni.JStringType().fromRef(_get_TYPE().object);

  static final _get_UNKNOWN =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Build__UNKNOWN")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String UNKNOWN
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get UNKNOWN =>
      const jni.JStringType().fromRef(_get_UNKNOWN().object);

  static final _get_USER =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__USER")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String USER
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get USER =>
      const jni.JStringType().fromRef(_get_USER().object);

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Build__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Build() {
    return Build.fromRef(_new0().object);
  }

  static final _getSerial =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Build__getSerial")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.lang.String getSerial()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString getSerial() {
    return const jni.JStringType().fromRef(_getSerial().object);
  }

  static final _getFingerprintedPartitions =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Build__getFingerprintedPartitions")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.util.List getFingerprintedPartitions()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JList<Build_Partition> getFingerprintedPartitions() {
    return const jni.JListType($Build_PartitionType())
        .fromRef(_getFingerprintedPartitions().object);
  }

  static final _getRadioVersion =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Build__getRadioVersion")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.lang.String getRadioVersion()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString getRadioVersion() {
    return const jni.JStringType().fromRef(_getRadioVersion().object);
  }
}

final class $BuildType extends jni.JObjType<Build> {
  const $BuildType();

  @override
  String get signature => r"Landroid/os/Build;";

  @override
  Build fromRef(jni.JObjectPtr ref) => Build.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($BuildType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($BuildType) && other is $BuildType;
  }
}

/// from: java.util.HashMap
class HashMap<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObject {
  @override
  late final jni.JObjType<HashMap<$K, $V>> $type = type(K, V);

  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  HashMap.fromRef(
    this.K,
    this.V,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static $HashMapType<$K, $V>
      type<$K extends jni.JObject, $V extends jni.JObject>(
    jni.JObjType<$K> K,
    jni.JObjType<$V> V,
  ) {
    return $HashMapType(
      K,
      V,
    );
  }

  static final _new0 = jniLookup<
              ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Float)>>(
          "HashMap__new0")
      .asFunction<jni.JniResult Function(int, double)>();

  /// from: public void <init>(int i, float f)
  /// The returned object must be released after use, by calling the [release] method.
  factory HashMap(
    int i,
    double f, {
    required jni.JObjType<$K> K,
    required jni.JObjType<$V> V,
  }) {
    return HashMap.fromRef(K, V, _new0(i, f).object);
  }

  static final _new1 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "HashMap__new1")
          .asFunction<jni.JniResult Function(int)>();

  /// from: public void <init>(int i)
  /// The returned object must be released after use, by calling the [release] method.
  factory HashMap.new1(
    int i, {
    required jni.JObjType<$K> K,
    required jni.JObjType<$V> V,
  }) {
    return HashMap.fromRef(K, V, _new1(i).object);
  }

  static final _new2 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("HashMap__new2")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory HashMap.new2({
    required jni.JObjType<$K> K,
    required jni.JObjType<$V> V,
  }) {
    return HashMap.fromRef(K, V, _new2().object);
  }

  static final _new3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__new3")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(java.util.Map map)
  /// The returned object must be released after use, by calling the [release] method.
  factory HashMap.new3(
    jni.JMap<$K, $V> map, {
    jni.JObjType<$K>? K,
    jni.JObjType<$V>? V,
  }) {
    K ??= jni.lowestCommonSuperType([
      (map.$type as jni.JMapType).K,
    ]) as jni.JObjType<$K>;
    V ??= jni.lowestCommonSuperType([
      (map.$type as jni.JMapType).V,
    ]) as jni.JObjType<$V>;
    return HashMap.fromRef(K, V, _new3(map.reference.pointer).object);
  }

  static final _size = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__size")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public int size()
  int size() {
    return _size(reference.pointer).integer;
  }

  static final _isEmpty = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "HashMap__isEmpty")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public boolean isEmpty()
  bool isEmpty() {
    return _isEmpty(reference.pointer).boolean;
  }

  static final _get0 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__get0")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public V get(java.lang.Object object)
  /// The returned object must be released after use, by calling the [release] method.
  $V get0(
    jni.JObject object,
  ) {
    return V.fromRef(_get0(reference.pointer, object.reference.pointer).object);
  }

  static final _containsKey = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__containsKey")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean containsKey(java.lang.Object object)
  bool containsKey(
    jni.JObject object,
  ) {
    return _containsKey(reference.pointer, object.reference.pointer).boolean;
  }

  static final _put = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__put")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V put(K object, V object1)
  /// The returned object must be released after use, by calling the [release] method.
  $V put(
    $K object,
    $V object1,
  ) {
    return V.fromRef(_put(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object);
  }

  static final _putAll = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__putAll")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void putAll(java.util.Map map)
  void putAll(
    jni.JMap<$K, $V> map,
  ) {
    return _putAll(reference.pointer, map.reference.pointer).check();
  }

  static final _remove = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__remove")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public V remove(java.lang.Object object)
  /// The returned object must be released after use, by calling the [release] method.
  $V remove(
    jni.JObject object,
  ) {
    return V
        .fromRef(_remove(reference.pointer, object.reference.pointer).object);
  }

  static final _clear = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__clear")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void clear()
  void clear() {
    return _clear(reference.pointer).check();
  }

  static final _containsValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__containsValue")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean containsValue(java.lang.Object object)
  bool containsValue(
    jni.JObject object,
  ) {
    return _containsValue(reference.pointer, object.reference.pointer).boolean;
  }

  static final _keySet = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__keySet")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Set keySet()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JSet<$K> keySet() {
    return jni.JSetType(K).fromRef(_keySet(reference.pointer).object);
  }

  static final _values = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__values")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Collection values()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject values() {
    return const jni.JObjectType().fromRef(_values(reference.pointer).object);
  }

  static final _entrySet = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "HashMap__entrySet")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Set entrySet()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JSet<jni.JObject> entrySet() {
    return const jni.JSetType(jni.JObjectType())
        .fromRef(_entrySet(reference.pointer).object);
  }

  static final _getOrDefault = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__getOrDefault")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V getOrDefault(java.lang.Object object, V object1)
  /// The returned object must be released after use, by calling the [release] method.
  $V getOrDefault(
    jni.JObject object,
    $V object1,
  ) {
    return V.fromRef(_getOrDefault(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object);
  }

  static final _putIfAbsent = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__putIfAbsent")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V putIfAbsent(K object, V object1)
  /// The returned object must be released after use, by calling the [release] method.
  $V putIfAbsent(
    $K object,
    $V object1,
  ) {
    return V.fromRef(_putIfAbsent(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object);
  }

  static final _remove1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__remove1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public boolean remove(java.lang.Object object, java.lang.Object object1)
  bool remove1(
    jni.JObject object,
    jni.JObject object1,
  ) {
    return _remove1(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .boolean;
  }

  static final _replace = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__replace")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean replace(K object, V object1, V object2)
  bool replace(
    $K object,
    $V object1,
    $V object2,
  ) {
    return _replace(reference.pointer, object.reference.pointer,
            object1.reference.pointer, object2.reference.pointer)
        .boolean;
  }

  static final _replace1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__replace1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V replace(K object, V object1)
  /// The returned object must be released after use, by calling the [release] method.
  $V replace1(
    $K object,
    $V object1,
  ) {
    return V.fromRef(_replace1(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object);
  }

  static final _computeIfAbsent = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__computeIfAbsent")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V computeIfAbsent(K object, java.util.function.Function function)
  /// The returned object must be released after use, by calling the [release] method.
  $V computeIfAbsent(
    $K object,
    jni.JObject function,
  ) {
    return V.fromRef(_computeIfAbsent(reference.pointer,
            object.reference.pointer, function.reference.pointer)
        .object);
  }

  static final _computeIfPresent = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__computeIfPresent")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V computeIfPresent(K object, java.util.function.BiFunction biFunction)
  /// The returned object must be released after use, by calling the [release] method.
  $V computeIfPresent(
    $K object,
    jni.JObject biFunction,
  ) {
    return V.fromRef(_computeIfPresent(reference.pointer,
            object.reference.pointer, biFunction.reference.pointer)
        .object);
  }

  static final _compute = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__compute")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V compute(K object, java.util.function.BiFunction biFunction)
  /// The returned object must be released after use, by calling the [release] method.
  $V compute(
    $K object,
    jni.JObject biFunction,
  ) {
    return V.fromRef(_compute(reference.pointer, object.reference.pointer,
            biFunction.reference.pointer)
        .object);
  }

  static final _merge = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__merge")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public V merge(K object, V object1, java.util.function.BiFunction biFunction)
  /// The returned object must be released after use, by calling the [release] method.
  $V merge(
    $K object,
    $V object1,
    jni.JObject biFunction,
  ) {
    return V.fromRef(_merge(reference.pointer, object.reference.pointer,
            object1.reference.pointer, biFunction.reference.pointer)
        .object);
  }

  static final _forEach = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__forEach")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void forEach(java.util.function.BiConsumer biConsumer)
  void forEach(
    jni.JObject biConsumer,
  ) {
    return _forEach(reference.pointer, biConsumer.reference.pointer).check();
  }

  static final _replaceAll = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("HashMap__replaceAll")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void replaceAll(java.util.function.BiFunction biFunction)
  void replaceAll(
    jni.JObject biFunction,
  ) {
    return _replaceAll(reference.pointer, biFunction.reference.pointer).check();
  }

  static final _clone = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__clone")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.Object clone()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject clone() {
    return const jni.JObjectType().fromRef(_clone(reference.pointer).object);
  }
}

final class $HashMapType<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObjType<HashMap<$K, $V>> {
  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  const $HashMapType(
    this.K,
    this.V,
  );

  @override
  String get signature => r"Ljava/util/HashMap;";

  @override
  HashMap<$K, $V> fromRef(jni.JObjectPtr ref) => HashMap.fromRef(K, V, ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($HashMapType, K, V);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($HashMapType<$K, $V>) &&
        other is $HashMapType<$K, $V> &&
        K == other.K &&
        V == other.V;
  }
}

/// from: com.example.in_app_java.AndroidUtils
class AndroidUtils extends jni.JObject {
  @override
  late final jni.JObjType<AndroidUtils> $type = type;

  AndroidUtils.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// The type which includes information such as the signature of this class.
  static const type = $AndroidUtilsType();
  static final _showToast = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("AndroidUtils__showToast")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: static public void showToast(android.app.Activity mainActivity, java.lang.CharSequence text, int duration)
  static void showToast(
    jni.JObject mainActivity,
    jni.JObject text,
    int duration,
  ) {
    return _showToast(
            mainActivity.reference.pointer, text.reference.pointer, duration)
        .check();
  }
}

final class $AndroidUtilsType extends jni.JObjType<AndroidUtils> {
  const $AndroidUtilsType();

  @override
  String get signature => r"Lcom/example/in_app_java/AndroidUtils;";

  @override
  AndroidUtils fromRef(jni.JObjectPtr ref) => AndroidUtils.fromRef(ref);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($AndroidUtilsType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($AndroidUtilsType) &&
        other is $AndroidUtilsType;
  }
}
