// 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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 fromReference(
          jni.JReference reference) =>
      EmojiCompat_CodepointSequenceMatchResult.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(
        _new0(metadataLoader.reference.pointer).reference);
  }

  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 _registerInitCallback(
            reference.pointer, initCallback.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _unregisterInitCallback(
            reference.pointer, initCallback.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setReplaceAll(reference.pointer, replaceAll ? 1 : 0)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setUseEmojiAsDefaultStyle(
            reference.pointer, useEmojiAsDefaultStyle ? 1 : 0)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setUseEmojiAsDefaultStyle1(
            reference.pointer,
            useEmojiAsDefaultStyle ? 1 : 0,
            emojiAsDefaultStyleExceptions.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setEmojiSpanIndicatorEnabled(
            reference.pointer, emojiSpanIndicatorEnabled ? 1 : 0)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setEmojiSpanIndicatorColor(reference.pointer, color)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setMetadataLoadStrategy(reference.pointer, strategy)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setSpanFactory(reference.pointer, factory0.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _setGlyphChecker(reference.pointer, glyphChecker.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }

  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 _getMetadataRepoLoader(reference.pointer)
        .object(const $EmojiCompat_MetadataRepoLoaderType());
  }
}

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 fromReference(jni.JReference reference) =>
      EmojiCompat_Config.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(_new0().reference);
  }

  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 _createSpan(reference.pointer, rasterizer.reference.pointer)
        .object(const jni.JObjectType());
  }
}

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 fromReference(jni.JReference reference) =>
      EmojiCompat_DefaultSpanFactory.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 fromReference(jni.JReference reference) =>
      EmojiCompat_GlyphChecker.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(_new0().reference);
  }

  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() {
    _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,
  ) {
    _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 fromReference(jni.JReference reference) =>
      EmojiCompat_InitCallback.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 fromReference(jni.JReference reference) =>
      EmojiCompat_LoadStrategy.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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,
  ) {
    _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 fromReference(jni.JReference reference) =>
      EmojiCompat_MetadataRepoLoader.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(
        _new0().reference);
  }

  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,
  ) {
    _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,
  ) {
    _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 fromReference(
          jni.JReference reference) =>
      EmojiCompat_MetadataRepoLoaderCallback.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 fromReference(jni.JReference reference) =>
      EmojiCompat_ReplaceStrategy.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 _createSpan(reference.pointer, rasterizer.reference.pointer)
        .object(const jni.JObjectType());
  }
}

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 fromReference(jni.JReference reference) =>
      EmojiCompat_SpanFactory.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 =>
      _get_EDITOR_INFO_METAVERSION_KEY().object(const jni.JStringType());

  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 =>
      _get_EDITOR_INFO_REPLACE_ALL_KEY().object(const jni.JStringType());

  /// 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 _init(context.reference.pointer).object(const $EmojiCompatType());
  }

  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 _init1(context.reference.pointer, defaultFactory.reference.pointer)
        .object(const $EmojiCompatType());
  }

  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 _init2(config.reference.pointer).object(const $EmojiCompatType());
  }

  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 _reset(config.reference.pointer).object(const $EmojiCompatType());
  }

  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 _reset1(emojiCompat.reference.pointer)
        .object(const $EmojiCompatType());
  }

  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,
  ) {
    _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 _get0().object(const $EmojiCompatType());
  }

  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() {
    _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,
  ) {
    _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,
  ) {
    _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 _process(reference.pointer, charSequence.reference.pointer)
        .object(const jni.JObjectType());
  }

  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 _process1(
            reference.pointer, charSequence.reference.pointer, start, end)
        .object(const jni.JObjectType());
  }

  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 _process2(reference.pointer, charSequence.reference.pointer, start,
            end, maxEmojiCount)
        .object(const jni.JObjectType());
  }

  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 _process3(reference.pointer, charSequence.reference.pointer, start,
            end, maxEmojiCount, replaceStrategy)
        .object(const jni.JObjectType());
  }

  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 _getAssetSignature(reference.pointer)
        .object(const jni.JStringType());
  }

  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,
  ) {
    _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 fromReference(jni.JReference reference) =>
      EmojiCompat.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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
        .fromReference(_new0(helper.reference.pointer).reference);
  }

  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 _create(reference.pointer, context.reference.pointer)
        .object(const $EmojiCompat_ConfigType());
  }
}

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 fromReference(
          jni.JReference reference) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromReference(
          reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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
        .fromReference(_new0().reference);
  }

  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 _getSigningSignatures(reference.pointer,
            packageManager.reference.pointer, providerPackage.reference.pointer)
        .object(const jni.JArrayType(jni.JObjectType()));
  }

  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 _queryIntentContentProviders(reference.pointer,
            packageManager.reference.pointer, intent.reference.pointer, flags)
        .object(const jni.JListType(jni.JObjectType()));
  }

  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 _getProviderInfo(reference.pointer, resolveInfo.reference.pointer)
        .object(const jni.JObjectType());
  }
}

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 fromReference(
          jni.JReference reference) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromReference(
          reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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
        .fromReference(_new0().reference);
  }

  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 _queryIntentContentProviders(reference.pointer,
            packageManager.reference.pointer, intent.reference.pointer, flags)
        .object(const jni.JListType(jni.JObjectType()));
  }

  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 _getProviderInfo(reference.pointer, resolveInfo.reference.pointer)
        .object(const jni.JObjectType());
  }
}

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 fromReference(
          jni.JReference reference) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19
          .fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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
        .fromReference(_new0().reference);
  }

  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 _getSigningSignatures1(reference.pointer,
            packageManager.reference.pointer, providerPackage.reference.pointer)
        .object(const jni.JArrayType(jni.JObjectType()));
  }
}

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 fromReference(
          jni.JReference reference) =>
      DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28
          .fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 _create(context.reference.pointer).object(const jni.JObjectType());
  }
}

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

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

  @override
  DefaultEmojiCompatConfig fromReference(jni.JReference reference) =>
      DefaultEmojiCompatConfig.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 =>
      _get_PARTITION_NAME_SYSTEM().object(const jni.JStringType());

  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 _getName(reference.pointer).object(const jni.JStringType());
  }

  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 _getFingerprint(reference.pointer).object(const jni.JStringType());
  }

  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 _equals = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Build_Partition__equals")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean equals(java.lang.Object object)
  bool equals(
    jni.JObject object,
  ) {
    return _equals(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 fromReference(jni.JReference reference) =>
      Build_Partition.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 =>
      _get_BASE_OS().object(const jni.JStringType());

  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 =>
      _get_CODENAME().object(const jni.JStringType());

  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 =>
      _get_INCREMENTAL().object(const jni.JStringType());

  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 =>
      _get_RELEASE().object(const jni.JStringType());

  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 =>
      _get_RELEASE_OR_CODENAME().object(const jni.JStringType());

  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 =>
      _get_RELEASE_OR_PREVIEW_DISPLAY().object(const jni.JStringType());

  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 => _get_SDK().object(const jni.JStringType());

  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 =>
      _get_SECURITY_PATCH().object(const jni.JStringType());

  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.fromReference(_new0().reference);
  }
}

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

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

  @override
  Build_VERSION fromReference(jni.JReference reference) =>
      Build_VERSION.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(_new0().reference);
  }
}

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 fromReference(jni.JReference reference) =>
      Build_VERSION_CODES.fromReference(reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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 => _get_BOARD().object(const jni.JStringType());

  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 =>
      _get_BOOTLOADER().object(const jni.JStringType());

  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 => _get_BRAND().object(const jni.JStringType());

  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 =>
      _get_CPU_ABI().object(const jni.JStringType());

  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 =>
      _get_CPU_ABI2().object(const jni.JStringType());

  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 =>
      _get_DEVICE().object(const jni.JStringType());

  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 =>
      _get_DISPLAY().object(const jni.JStringType());

  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 =>
      _get_FINGERPRINT().object(const jni.JStringType());

  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 =>
      _get_HARDWARE().object(const jni.JStringType());

  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 => _get_HOST().object(const jni.JStringType());

  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 => _get_ID().object(const jni.JStringType());

  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 =>
      _get_MANUFACTURER().object(const jni.JStringType());

  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 => _get_MODEL().object(const jni.JStringType());

  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 =>
      _get_ODM_SKU().object(const jni.JStringType());

  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 =>
      _get_PRODUCT().object(const jni.JStringType());

  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 => _get_RADIO().object(const jni.JStringType());

  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 =>
      _get_SERIAL().object(const jni.JStringType());

  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 => _get_SKU().object(const jni.JStringType());

  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 =>
      _get_SOC_MANUFACTURER().object(const jni.JStringType());

  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 =>
      _get_SOC_MODEL().object(const jni.JStringType());

  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 =>
      _get_SUPPORTED_32_BIT_ABIS()
          .object(const jni.JArrayType(jni.JStringType()));

  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 =>
      _get_SUPPORTED_64_BIT_ABIS()
          .object(const jni.JArrayType(jni.JStringType()));

  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 =>
      _get_SUPPORTED_ABIS().object(const jni.JArrayType(jni.JStringType()));

  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 => _get_TAGS().object(const jni.JStringType());

  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 => _get_TYPE().object(const jni.JStringType());

  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 =>
      _get_UNKNOWN().object(const jni.JStringType());

  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 => _get_USER().object(const jni.JStringType());

  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.fromReference(_new0().reference);
  }

  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 _getSerial().object(const jni.JStringType());
  }

  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 _getFingerprintedPartitions()
        .object(const jni.JListType($Build_PartitionType()));
  }

  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 _getRadioVersion().object(const jni.JStringType());
  }
}

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

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

  @override
  Build fromReference(jni.JReference reference) =>
      Build.fromReference(reference);

  @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.fromReference(
    this.K,
    this.V,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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.fromReference(K, V, _new0(i, f).reference);
  }

  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.fromReference(K, V, _new1(i).reference);
  }

  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.fromReference(K, V, _new2().reference);
  }

  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.fromReference(K, V, _new3(map.reference.pointer).reference);
  }

  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 _get0(reference.pointer, object.reference.pointer).object(V);
  }

  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 _put(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object(V);
  }

  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,
  ) {
    _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 _remove(reference.pointer, object.reference.pointer).object(V);
  }

  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() {
    _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 _keySet(reference.pointer).object(jni.JSetType(K));
  }

  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 _values(reference.pointer).object(const jni.JObjectType());
  }

  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 _entrySet(reference.pointer)
        .object(const jni.JSetType(jni.JObjectType()));
  }

  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 _getOrDefault(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object(V);
  }

  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 _putIfAbsent(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object(V);
  }

  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 _replace1(reference.pointer, object.reference.pointer,
            object1.reference.pointer)
        .object(V);
  }

  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 _computeIfAbsent(reference.pointer, object.reference.pointer,
            function.reference.pointer)
        .object(V);
  }

  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 _computeIfPresent(reference.pointer, object.reference.pointer,
            biFunction.reference.pointer)
        .object(V);
  }

  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 _compute(reference.pointer, object.reference.pointer,
            biFunction.reference.pointer)
        .object(V);
  }

  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 _merge(reference.pointer, object.reference.pointer,
            object1.reference.pointer, biFunction.reference.pointer)
        .object(V);
  }

  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,
  ) {
    _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,
  ) {
    _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 _clone(reference.pointer).object(const jni.JObjectType());
  }
}

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> fromReference(jni.JReference reference) =>
      HashMap.fromReference(K, V, reference);

  @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.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// 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,
  ) {
    _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 fromReference(jni.JReference reference) =>
      AndroidUtils.fromReference(reference);

  @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;
  }
}
