diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 0000000..7dbcf0f
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,31 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(./gradlew :shared:testAndroidHostTest*)",
+ "Bash(./gradlew :shared:compileAndroidHostTest*)",
+ "Bash(./gradlew :shared:iosSimulatorArm64Test*)",
+ "Bash(./gradlew :shared:compileKotlinIosSimulatorArm64*)",
+ "Bash(./gradlew :androidApp:assembleDebug*)",
+ "Bash(./gradlew :androidApp:testDebugUnitTest*)",
+ "Bash(./gradlew :core:flags:allTests*)",
+ "Bash(awk *)",
+ "Bash(curl -s *)",
+ "Bash(curl -sL *)",
+ "Bash(curl -sI *)",
+ "Bash(unzip -l *)",
+ "Bash(unzip -p *)",
+ "Bash(javap *)",
+ "Bash(xxd *)",
+ "Bash(adb devices*)",
+ "Bash(adb logcat *)",
+ "Bash(xcrun simctl list *)",
+ "mcp__claude-in-chrome__navigate",
+ "mcp__claude-in-chrome__find",
+ "mcp__claude-in-chrome__get_page_text",
+ "mcp__claude-in-chrome__read_page",
+ "mcp__claude-in-chrome__tabs_context_mcp",
+ "mcp__claude_ai_Notion__notion-fetch",
+ "mcp__claude_ai_Notion__notion-search"
+ ]
+ }
+}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..e13ba0f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,93 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+concurrency:
+ # A new push supersedes an in-flight run on the same ref; nobody needs the results of a commit
+ # that has already been replaced.
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ # Everything that needs only a JVM. Split from the iOS job because this is the fast feedback most
+ # commits need, and it must not wait on a macOS runner queue.
+ shared:
+ name: Shared + Android (JVM)
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: '17'
+
+ - uses: gradle/actions/setup-gradle@v4
+
+ - name: Flags module
+ run: ./gradlew :core:flags:allTests --stacktrace
+
+ # verify=true makes Roborazzi compare against the committed goldens and fail on a diff. Without it
+ # the snapshot tests run, pass, and check nothing — which is how a snapshot suite quietly becomes
+ # decoration.
+ - name: Shared unit + snapshot + architecture tests
+ run: ./gradlew :shared:testAndroidHostTest -Proborazzi.test.verify=true --stacktrace
+
+ - name: Compose interaction tests
+ run: ./gradlew :androidApp:testDebugUnitTest --stacktrace
+
+ # Proves the app actually assembles with the real ML Kit and llama.cpp dependencies wired in.
+ # A green test suite over a module that no longer links is not a green build.
+ - name: Assemble debug APK
+ run: ./gradlew :androidApp:assembleDebug --stacktrace
+
+ # The baseline profile is generated on a device, which CI has none of — but the committed profile must
+ # still be packaged, and a release assemble is what proves that wiring survives.
+ - name: Assemble release (packages the committed baseline profile)
+ run: ./gradlew :androidApp:assembleRelease --stacktrace
+
+ - name: Upload test reports
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-reports
+ path: |
+ **/build/reports/tests/
+ **/build/test-results/
+ # Roborazzi writes the actual-vs-expected diff here; without it a snapshot failure on CI
+ # is unreadable and the usual response is to re-record it blind.
+ **/build/outputs/roborazzi/
+
+ # A separate job on macOS: Kotlin/Native and the Swift Tier-A bridge cannot be built anywhere else,
+ # and this is the half that a JVM-only pipeline would silently never check.
+ ios:
+ name: iOS (Kotlin/Native + Swift)
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: '17'
+
+ - uses: gradle/actions/setup-gradle@v4
+
+ - name: Kotlin/Native tests
+ run: ./gradlew :shared:iosSimulatorArm64Test --stacktrace
+
+ # The Swift bridge only exists in the Xcode project, so a Gradle-only iOS job would not compile
+ # FoundationModelsBridge.swift at all — and that file is where the Tier-A error mapping lives.
+ - name: Build the iOS app
+ run: |
+ xcodebuild \
+ -project iosApp/iosApp.xcodeproj \
+ -scheme iosApp \
+ -configuration Debug \
+ -destination 'generic/platform=iOS Simulator' \
+ -derivedDataPath build/dd \
+ build \
+ CODE_SIGNING_ALLOWED=NO
diff --git a/.gitignore b/.gitignore
index 46b22c8..e8d2037 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,13 @@ node_modules/
# MemPalace per-project files (issue #185)
mempalace.yaml
entities.json
+
+# Personal write-up material — kept locally, deliberately out of the repo.
+# The three diagrams the README embeds are the exception and stay tracked.
+docs/linkedin-series.md
+docs/media/*
+!docs/media/01-before-after.png
+!docs/media/01-thesis-architecture.png
+!docs/media/05-latency-measured.png
+docs/study/
+docs/gaps.md
diff --git a/README.md b/README.md
index 785625f..b43fe92 100644
--- a/README.md
+++ b/README.md
@@ -1,57 +1,271 @@
-### Goals
-* Building Multiplatform app (mainly Android, iOS, with Web as minor focus) that showcase how
- well engineered e-commerce apps should be built.
-* It showcases the new revolutionary concept of Generative UI in Mobile apps with application
- in e-commerce apps.
-*
-### Non-Goals
-* building app the will be used by a real store (versatile features)
+# StoreFront
+**A proof-of-concept storefront whose UI is generated, not hard-coded — and every model runs on the
+device.**
+This is a demo built to answer one question with code rather than opinions: *what can you actually run
+on-device today?* Not a shippable store — the commerce is a backdrop for the generative-UI and on-device
+AI engineering.
-This is a Kotlin Multiplatform project targeting Android, iOS, Web, Desktop (JVM).
+Two things decide what you see. Your own behaviour on the phone (what you opened, how long you read), and
+plain language: you type *"compact grid, 3 columns, hide prices"* and the screen re-composes to match.
-* [/iosApp](./iosApp/iosApp) contains an iOS application. Even if you’re sharing your UI with Compose Multiplatform,
- you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
+No server. No upload. Kotlin Multiplatform + Compose Multiplatform, Android and iOS from one codebase.
-* [/shared](./shared/src) is for code that will be shared across your Compose Multiplatform applications.
- It contains several subfolders:
- - [commonMain](./shared/src/commonMain/kotlin) is for code that’s common for all targets.
- - Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name.
- For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app,
- the [iosMain](./shared/src/iosMain/kotlin) folder would be the right place for such calls.
- Similarly, if you want to edit the Desktop (JVM) specific part, the [jvmMain](./shared/src/jvmMain/kotlin)
- folder is the appropriate location.
+
+
+
-### Running the apps
+> One command, three dimensions, parsed on-device in 0 ms — no model call, no network. The override then
+> decays back to the inferred baseline on its own.
-Use the run configurations provided by the run widget in your IDE's toolbar. You can also use these commands and options:
+---
-- Android app: `./gradlew :androidApp:assembleDebug`
-- Desktop app:
- - Hot reload: `./gradlew :desktopApp:hotRun --auto`
- - Standard run: `./gradlew :desktopApp:run`
-- Web app:
- - Wasm target (faster, modern browsers): `./gradlew :webApp:wasmJsBrowserDevelopmentRun`
- - JS target (slower, supports older browsers): `./gradlew :webApp:jsBrowserDevelopmentRun`
-- iOS app: open the [/iosApp](./iosApp) directory in Xcode and run it from there.
+## Why this is harder than it looks
-### Running tests
+"Generated UI" turns every comfortable assumption into a question, and the answers are the project:
-Use the run button in your IDE's editor gutter, or run tests using Gradle tasks:
+- **How do you snapshot-test a layout that differs every run?** → a typed spec, a pure merge, an injected clock
+- **What renders before any signals exist?** → a deterministic cold-start baseline
+- **What happens when someone asks for something you can't do?** → a bounded vocabulary and a named refusal
+- **How does a screen reader cope with a screen that rearranges itself?** → stable item identity + a live region
+- **How do you ship an LLM you can't hotfix, on hardware you don't own?** → three tiers and a failure taxonomy
-- Android tests: `./gradlew :shared:testAndroidHostTest`
-- Desktop tests: `./gradlew :shared:jvmTest`
-- Web tests:
- - Wasm target: `./gradlew :shared:wasmJsTest`
- - JS target: `./gradlew :shared:jsTest`
-- iOS tests: `./gradlew :shared:iosSimulatorArm64Test`
+## Architecture
----
+
+
+
+
+Two contributors meet in exactly one place, and neither owns a dimension:
+
+```kotlin
+fun merge(baseline: UiSpec, overlay: PreferenceOverlay, nowMs: Long): UiSpec
+```
+
+A *live* explicit override wins per-dimension; otherwise the inferred value stands. **Decay is emergent** —
+no timer, no sweep, no expiry job. An override carries `appliedAtMs` + `ttlMs`, and the merge simply asks
+whether it is still live at `nowMs`. That one property makes the whole generative pipeline a pure function,
+and therefore snapshot-testable end to end.
+
+**Four input channels, one contract:** implicit signals · in-app chatbox · Android AppFunctions · iOS App
+Intents. The two OS channels share a single typed function surface in `commonMain`, so each platform adapter
+is genuinely thin — build once, N callers.
+
+### Shared vs platform code
+
+| Source set | Files |
+| --- | --- |
+| `commonMain` | 70 |
+| `androidMain` | 5 |
+| `iosMain` | 6 |
+
+~86% shared, including all UI, the state machine, the NL layer, ranking, download infrastructure and
+persistence. The 11 platform files each exist for a specific, nameable capability — not as "the Android
+version" of anything.
+
+**Notable:** this codebase contains exactly **one** `expect`/`actual` pair, and it is template leftover.
+Every real boundary is an interface in `commonMain`, implemented per platform, injected at startup —
+because `expect`/`actual` is compile-time, unfakeable in tests, and *cannot be implemented from Swift*.
+
+Swift also cannot implement a Kotlin `suspend` function at all. The bridge is therefore three layers: a
+shared suspend interface, a callback-shaped protocol Swift can satisfy, and a
+`suspendCancellableCoroutine` adapter that reunites them without leaking the shape upward.
+
+## On-device AI: three tiers
+
+| | Tier A: platform | Tier B: downloaded | Tier C: rule table |
+| --- | --- | --- | --- |
+| **Engine** | Gemini Nano (ML Kit) / Apple Foundation Models | Qwen3-0.6B Q4_K_M via llama.cpp | token rule table |
+| **Ships in the APK** | nothing | nothing (397 MB on consent) | ~350 lines |
+| **Latency** | 4.2–19.6 s *(measured)* | 6.5–11.1 s *(measured)* | instant |
+| **Background** | ❌ Android · ⚠️ iOS | ✅ | ✅ |
+
+All three are **$0 inference**. Cloud grounding was evaluated and rejected — paid, and it breaks the offline
+thesis. The rejection is recorded rather than silent.
+
+### The counter-intuitive decision: parser first
+
+The obvious design is model-first with a dumb fallback. This does the opposite, and not for latency.
+
+AICore enforces a per-app inference quota **and** a daily battery quota. Google publishes neither number.
+You cannot design against a number that does not exist, so the only defensible design is to not spend it.
+The rule table answers most real commands at zero cost; the model is reserved for paraphrase and
+contradiction — where it actually earns its seconds.
+
+The parser is not a keyword `contains()`. That version read *"don't hide prices"* as **hide prices**, and
+matched LIST inside "sty**list**". It is token + clause matching with clause-scoped negation.
+
+### Failure is a first-class type
+
+Both platforms' error sets collapse into five shared categories, each with its own retry policy:
+
+```kotlin
+sealed interface ModelFailure {
+ data object Unavailable // stop asking
+ data object NotReady // suppress, re-probe
+ data class Throttled(retryable: Boolean, retryAfterMs: Long?) // backoff, or a window
+ data class Rejected(reason: RejectionReason) // never retry this text
+ data object Cancelled // not a failure at all
+}
+```
+
+Only `retryable` differs by platform — and that difference is real behaviour, not a leaky abstraction:
+**Android hard-blocks background inference; iOS merely rate-limits it.**
+
+### Shipping 397 MB to a phone
+
+Tier B's weights are fetched after install, on explicit consent, and every one of these *will* happen: the
+connection drops, the disk fills, the user backgrounds the app, the file arrives corrupt. So bytes land in
+a `.part` file and a `Range` header asks only for what is missing; space is checked before the first byte,
+not after 400 MB; a metered connection is refused unless consent says otherwise; and the file is hashed
+then `atomicMove`d, so a crash can never leave a truncated file that looks installed — the only two states
+on disk are *partial* and *verified*.
+
+The interesting part is what a `.part` file **cannot** tell you. A 300 MB partial looks identical whether
+the user deliberately paused it or the OS killed the app mid-transfer, and those two want opposite
+behaviour. So the persisted record holds intent, not progress:
+
+```kotlin
+enum class DownloadIntent { ACTIVE, USER_PAUSED }
+```
+
+`ACTIVE` resumes — a dropped connection is nobody's decision. `USER_PAUSED` never does, because resuming
+what someone deliberately stopped is a bug. The automatic resume is announced rather than silent and can
+be refused, and refusing *writes* `USER_PAUSED` so the decline outlives the process rather than lasting
+until the next launch. Refusing keeps the bytes: "not now" must not discard 300 MB.
+
+Disk wins over the record on every question it can answer. A record naming an already-installed model is
+stale; one whose `.part` file is gone has nothing to resume. Both are cleared rather than allowed to drive
+a bogus offer, and a `.part` with no record at all reads as `USER_PAUSED` — no consent evidence exists, so
+offering is the only defensible read.
+
+## What measurement changed
+
+Every item here would have shipped broken on documentation alone.
+
+**`BUSY = 9` is documented as ambiguous** — *either* "out of quota, retry" *or* "background use not allowed".
+Two states, opposite responses, one code. Resolved with a fact the app already knows: its own foreground
+state.
+
+**Inference is foreground-only on Android** (`BACKGROUND_USE_BLOCKED = 30`). This killed a planned feature —
+an OS-assistant channel cannot be Nano-backed, because an assistant invokes you with no screen alive. That
+channel now uses typed setters and no model at all.
-Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html),
-[Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform/#compose-multiplatform),
-[Kotlin/Wasm](https://kotl.in/wasm/)…
+**My timeout was wrong by 6×.** Warm, prewarmed, session-reused inference measured 4.2–19.6 s against a
+3-second budget. Every request would have silently demoted a working engine.
+
+**A schema sentinel made the model echo.** Non-optional enums carrying an `"unchanged"` value caused Apple's
+model to restate current state in every field — so *"play some jazz"* returned a full layout patch. Fixed
+with optional fields, a required `isDisplayRequest` flag giving the model an exit, and a no-op filter.
+Qwen3-0.6B echoes identically, so it was never one vendor's quirk.
+
+**A native crash walks straight through error handling.** Grammar-constrained decoding segfaults inside
+`llama_grammar_accept_token` on two emulators and a physical device. A SIGSEGV cannot be caught from Kotlin,
+so the five-category taxonomy is powerless — the mitigation is *avoidance*, not handling.
+
+
+
+
+
+## Testing what cannot be run
+
+Most interesting behaviour here is unexecutable in CI: Nano ships on no emulator, Apple's model needs
+specific hardware, OS assistants cannot be invoked, and races are non-deterministic by nature.
+
+The strategy is to **move the part most likely to be wrong somewhere reachable.** The vendor call is
+unavoidable; *interpreting its result* is where bugs live — so that lives in shared code as a pure function.
+AICore's entire error table is unit-tested **with ML Kit not on the classpath**.
+
+The technique worth stealing: **prove the hazard deterministically, prove the fix under contention.** A
+lost-update test firing 5,000 concurrent dispatches was probabilistic on the JVM and *never* reproduced on
+Kotlin/Native. It now injects the competing write into the exact read→write gap — no threads, no luck,
+identical on every platform — while the CAS fix keeps a real concurrent storm, because that direction cannot
+flake.
+
+| Suite | Tests |
+| --- | --- |
+| `:shared` — JVM target | 332 |
+| `:shared` — Kotlin/Native (iOS) | 209 |
+| `:androidApp` — Compose interaction | 20 |
+| `:core:flags` | 6 |
+| On-device instrumented | 1 |
+
+`commonTest` runs on both shared targets, so the first two rows overlap rather than sum to distinct cases.
+Also: 10 Roborazzi snapshots (verified to actually gate, by corrupting one), and **7 architecture rules that
+read the source tree** — including the privacy thesis as an executable test.
+
+## Privacy and security
+
+The claim is that behavioural signals never leave the device. Both halves are enforced, not promised:
+
+**Nothing is uploaded** — an architecture test fails the build if anything outside the catalog API, the model
+downloader and the composition roots imports a network client.
+
+**Nothing is readable at rest** — the signal log is encrypted. Android uses SQLCipher with a passphrase
+wrapped by a hardware-backed Keystore key; iOS uses Data Protection, because SQLDelight's native driver has
+no SQLCipher build and the OS already provides the same guarantee against the same threat.
+
+The threat model is stated **before** the mechanism, including what is out of scope: an attacker already
+executing as the app. No client-side key helps there, and claiming otherwise would be theatre.
+
+Verified rather than asserted: the DB header is random bytes, `sqlite3` reports *"file is not a database"*,
+`strings` finds zero table or event names, and a product opened in one process reappeared in Recommended
+after a full restart — proving encrypted write → new-process decrypt → rank.
+
+## Ranking
+
+The implicit half is a pure function of a signal window and a clock, so it is fully testable:
+
+```kotlin
+fun score(records: List, nowMs: Long): Map
+```
+
+Opens decay exponentially (7-day half-life). Dwell is a **multiplier, not an addend** — every dwell follows
+an open, so summing both counts one visit twice and ranks *opened twice, bounced twice* above *opened once,
+read for a minute*. The longest single dwell counts rather than the sum, and it saturates at 30 s, so a
+detail screen left open in the background cannot dominate. Time-of-day is a continuous circular nudge —
+capped at 1.15×, because a weak signal must never overpower a strong one, and a bucketed version would put a
+cliff edge between 11:59 and 12:01.
+
+The result is a `ProductScore` with its reasoning attached, not a bare `Double` — *"why is this in
+Recommended"* is unanswerable without the breakdown.
+
+## Status
+
+**Complete:** the typed contract · four input channels · three engine tiers with fallback · decaying overlay
+· single-site validation · ranking over opens, dwell and time-of-day · encryption at rest · engine picker
+(3 surfaces) · resumable Tier-B downloads that survive process death · CI on two runners · baseline profile
+· accessibility (announce + focus preservation).
+
+**Phase 2** is hardening this into an actual e-commerce app: cart, checkout, payments, orders, and the
+production concerns a real store brings with it. None of that serves the generative-UI thesis, which is
+what this phase exists to prove, so it is deliberately out of scope here.
+
+## Build and verify
+
+```bash
+./gradlew :shared:testAndroidHostTest -Proborazzi.test.verify=true # unit + snapshot + architecture
+./gradlew :shared:iosSimulatorArm64Test # Kotlin/Native
+./gradlew :androidApp:testDebugUnitTest # Compose interaction
+./gradlew :androidApp:assembleDebug # Android app
+```
+
+iOS needs Xcode: open `iosApp/iosApp.xcodeproj`. Tier A on iOS requires Apple Intelligence hardware; without
+it the app degrades to the rule-table parser by design.
+
+## Documentation
+
+Seven [ADRs](docs/adr/) carry the reasoning — including the decisions that turned out to be wrong. They are
+worth reading in order: 0006 (NL engine boundary) and 0007 (encryption and threat model) are where the
+on-device constraints stop being abstract.
+
+## Stack
+
+Kotlin Multiplatform · Compose Multiplatform · Coroutines/Flow · Koin · SQLDelight + SQLCipher · DataStore ·
+Ktor · Roborazzi · ML Kit GenAI (Gemini Nano) · Apple Foundation Models · llama.cpp · AppFunctions · App
+Intents · Baseline Profiles
+
+---
-We would appreciate your feedback on Compose/Web and Kotlin/Wasm in the public Slack channel [#compose-web](https://slack-chats.kotlinlang.org/c/compose-web).
-If you face any issues, please report them on [YouTrack](https://youtrack.jetbrains.com/newIssue?project=CMP).
\ No newline at end of file
+A proof-of-concept: the goal is engineering depth on a hard problem, not a shippable store.
diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts
index b09e5b6..2cf8866 100644
--- a/androidApp/build.gradle.kts
+++ b/androidApp/build.gradle.kts
@@ -4,6 +4,8 @@ plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
+ alias(libs.plugins.ksp)
+ alias(libs.plugins.baselineprofile)
}
kotlin {
@@ -20,18 +22,59 @@ dependencies {
implementation(libs.compose.uiToolingPreview)
debugImplementation(libs.compose.uiTooling)
+
+ // Tier A (Gemini Nano via AICore). Deliberately in :androidApp, not :shared — it declares
+ // minSdk 26 against this app's 24 and binds an AICore service, so confining it here is what keeps
+ // the shared module vendor-free and Tier A genuinely optional (ADR 0006).
+ implementation(libs.mlkit.genai.prompt)
+ // ProcessLifecycleOwner answers "are we foreground?", which is the only way to tell AICore's
+ // BUSY-means-quota apart from BUSY-means-background-blocked.
+ implementation(libs.androidx.lifecycle.process)
+ // Installs the bundled baseline profile at first run. Without it the recorded profile ships but is
+ // never applied, which is the quiet way this feature ends up doing nothing.
+ implementation(libs.androidx.profileinstaller)
+ baselineProfile(projects.baselineprofile)
+ implementation(libs.androidx.appfunctions)
+ ksp(libs.androidx.appfunctions.compiler)
+
+ // Compose *interaction* tests live here rather than in :shared, because they need a host Activity
+ // registered in a manifest — see src/debug/AndroidManifest.xml. Snapshot tests render state; these
+ // drive input, which is the only way to catch a keyboard action that is wired but never reachable.
+ testImplementation(libs.compose.uiTest)
+ testImplementation(libs.robolectric)
+ testImplementation(libs.junit)
+ testImplementation(libs.kotlin.test)
+
+ androidTestImplementation(libs.androidx.testExt.junit)
+ androidTestImplementation(libs.androidx.test.runner)
+ androidTestImplementation(libs.kotlin.test)
}
android {
namespace = "org.itstanany.storefront"
+
+ testOptions {
+ unitTests.isIncludeAndroidResources = true
+ }
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
applicationId = "org.itstanany.storefront"
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
+
+ ndk {
+ // llama.cpp is ~30 MB of native code *per ABI*, and Llamatik ships four. Keeping only
+ // arm64-v8a (every modern device) and x86_64 (emulators) removes ~45 MB. A 32-bit-only
+ // device still installs and still works — it just falls back to the rule-table parser,
+ // because Tier B degrades rather than failing hard when the library cannot load.
+ abiFilters += listOf("arm64-v8a", "x86_64")
+ }
versionCode = 1
versionName = "1.0"
+ // Tier B's only honest proof is on a device: the native library either loads and generates, or
+ // it does not, and no host test can answer that.
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
packaging {
resources {
diff --git a/androidApp/src/androidTest/kotlin/org/itstanany/storefront/channel/AppFunctionsOnDeviceTest.kt b/androidApp/src/androidTest/kotlin/org/itstanany/storefront/channel/AppFunctionsOnDeviceTest.kt
new file mode 100644
index 0000000..ab1f5e9
--- /dev/null
+++ b/androidApp/src/androidTest/kotlin/org/itstanany/storefront/channel/AppFunctionsOnDeviceTest.kt
@@ -0,0 +1,255 @@
+package org.itstanany.storefront.channel
+
+import android.content.Context
+import androidx.appfunctions.AppFunctionData
+import androidx.appfunctions.AppFunctionManager
+import androidx.appfunctions.AppFunctionSearchSpec
+import androidx.appfunctions.ExecuteAppFunctionRequest
+import androidx.appfunctions.ExecuteAppFunctionResponse
+import androidx.appfunctions.metadata.AppFunctionMetadata
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeoutOrNull
+import org.itstanany.storefront.StorefrontApplication
+import org.itstanany.storefront.preference.DataStorePreferenceOverlayRepository
+import org.itstanany.storefront.preference.PreferenceOverlay
+import org.itstanany.storefront.preference.liveColumns
+import org.itstanany.storefront.preference.liveDensity
+import org.itstanany.storefront.preference.liveLayout
+import org.itstanany.storefront.preference.liveSectionOrder
+import org.itstanany.storefront.preference.liveShowPrices
+import org.itstanany.storefront.spec.SectionRole
+import org.junit.After
+import org.junit.Assume.assumeTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertTrue
+
+/**
+ * The OS-assistant channel, driven through the real AppFunctions runtime rather than by calling
+ * [StorefrontAppFunctions] directly.
+ *
+ * This closes the gap the README used to state as "registered but never invoked". Registration was
+ * verifiable with `dumpsys`; *execution* was not, because the caller is normally an assistant and no
+ * emulator ships one. `AppFunctionManager.executeAppFunction` turns out to need the privileged
+ * `EXECUTE_APP_FUNCTIONS` permission only for **other** packages — an app may invoke its own functions
+ * — so the whole dispatch path is reachable from an instrumented test after all.
+ *
+ * What that buys, none of which a host test can reach:
+ *
+ * - **The KDoc really is the schema.** Parameters can only be built from metadata the runtime indexed,
+ * so a passing test proves KSP extracted the `@AppFunction` signatures and AppSearch stored them.
+ * - **Argument marshalling across the IPC boundary** for String, Boolean and Int.
+ * - **The real dispatcher** finding `StorefrontAppFunctions` through the app's
+ * `appFunctionConfiguration` factory — the thing that makes it write to the same overlay the app reads.
+ *
+ * Each case asserts the *effect*, not just the response. A function that returned "Done." and wrote
+ * nowhere would pass a response-only assertion, which is precisely the failure worth catching.
+ *
+ * Not covered, and still honestly a gap: invocation by an actual assistant, and whether the refusal
+ * strings read well spoken aloud.
+ */
+@RunWith(AndroidJUnit4::class)
+class AppFunctionsOnDeviceTest {
+
+ private val context: Context get() = ApplicationProvider.getApplicationContext()
+
+ private val app: StorefrontApplication
+ get() = context.applicationContext as StorefrontApplication
+
+ private val overlayRepository by lazy { DataStorePreferenceOverlayRepository(app.dataStore) }
+
+ private val overlay: PreferenceOverlay get() = overlayRepository.overlay.value
+
+ /** Overrides are TTL-based, so "live" needs a clock. Everything here is written moments ago. */
+ private val now: Long get() = System.currentTimeMillis()
+
+ @After
+ fun resetOverlay() {
+ // These write to the real app DataStore. Without this, case order would decide outcomes.
+ overlayRepository.clear()
+ }
+
+ // ---- the harness ------------------------------------------------------------------------------
+
+ private fun manager(): AppFunctionManager? = AppFunctionManager.getInstance(context)
+
+ /**
+ * Metadata for one of our own functions.
+ *
+ * Polled rather than read once: AppSearch indexes app functions asynchronously after install, so a
+ * bare lookup races the installer and would flake on a cold device.
+ */
+ private suspend fun awaitMetadata(manager: AppFunctionManager, id: String): AppFunctionMetadata? =
+ withTimeoutOrNull(METADATA_TIMEOUT_MS) {
+ while (true) {
+ val found = manager
+ .searchAppFunctions(AppFunctionSearchSpec(packageNames = setOf(context.packageName)))
+ .firstOrNull { it.id == id }
+ if (found != null) return@withTimeoutOrNull found
+ delay(POLL_INTERVAL_MS)
+ }
+ @Suppress("UNREACHABLE_CODE")
+ null
+ }
+
+ /**
+ * Executes one function by its generated id, building parameters against the metadata the runtime
+ * itself reports. Returns the response so a case can assert on the spoken sentence too.
+ */
+ private suspend fun execute(
+ id: String,
+ arguments: AppFunctionData.Builder.(AppFunctionMetadata) -> Unit = {},
+ ): ExecuteAppFunctionResponse {
+ val manager = assertNotNull(manager(), "AppFunctionManager unavailable")
+ val metadata = assertNotNull(
+ awaitMetadata(manager, id),
+ "function $id was never indexed — KSP did not register it, or AppSearch did not store it",
+ )
+
+ val parameters = AppFunctionData.Builder(metadata.parameters, metadata.components)
+ .apply { arguments(metadata) }
+ .build()
+
+ return manager.executeAppFunction(
+ ExecuteAppFunctionRequest(
+ targetPackageName = context.packageName,
+ functionIdentifier = id,
+ functionParameters = parameters,
+ ),
+ )
+ }
+
+ /** Asserts success and returns the sentence the assistant would speak. */
+ private fun ExecuteAppFunctionResponse.spokenResult(): String {
+ val success = this as? ExecuteAppFunctionResponse.Success
+ ?: error("expected success, got $this")
+ return assertNotNull(
+ success.returnValue.getString(ExecuteAppFunctionResponse.Success.PROPERTY_RETURN_VALUE),
+ "an assistant speaks its result, so the return value must be a sentence",
+ )
+ }
+
+ /** DataStore writes are asynchronous; the overlay flow needs a moment to reflect them. */
+ private suspend fun awaitOverlay(description: String, predicate: (PreferenceOverlay) -> Boolean) {
+ val settled = withTimeoutOrNull(OVERLAY_TIMEOUT_MS) {
+ while (!predicate(overlay)) delay(POLL_INTERVAL_MS)
+ true
+ }
+ assertTrue(settled == true, "the overlay never reflected $description; overlay=$overlay")
+ }
+
+ private fun assumeSupported() {
+ assumeTrue(
+ "AppFunctions needs API 36+ and a non-profile user; skipping rather than failing",
+ manager() != null,
+ )
+ }
+
+ // ---- one case per function --------------------------------------------------------------------
+
+ @Test
+ fun setLayout_reachesTheOverlayThroughTheRealDispatcher() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_LAYOUT) { setString("layout", "grid") }.spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("a layout override") { it.liveLayout(now)?.name == "GRID" }
+ }
+
+ @Test
+ fun setDensity_reachesTheOverlay() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_DENSITY) { setString("density", "compact") }.spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("a density override") { it.liveDensity(now)?.name == "COMPACT" }
+ }
+
+ /** Boolean marshalling across the IPC boundary, which no host test exercises. */
+ @Test
+ fun setPricesVisible_marshalsABoolean() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_PRICES_VISIBLE) { setBoolean("visible", false) }.spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("prices hidden") { it.liveShowPrices(now) == false }
+ }
+
+ /** Int marshalling, and the one parameter with a validated range. */
+ @Test
+ fun setColumns_marshalsAnInt() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_COLUMNS) { setInt("columns", 3) }.spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("3 columns") { it.liveColumns(now) == 3 }
+ }
+
+ @Test
+ fun reorderSections_reachesTheOverlay() = runBlocking {
+ assumeSupported()
+ val spoken = execute(REORDER_SECTIONS) { setString("first", "all") }.spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("the catalog first") {
+ it.liveSectionOrder(now)?.firstOrNull() == SectionRole.ALL
+ }
+ }
+
+ @Test
+ fun resetAppearance_clearsEveryOverride() = runBlocking {
+ assumeSupported()
+ execute(SET_LAYOUT) { setString("layout", "grid") }.spokenResult()
+ awaitOverlay("a layout override to clear") { it.liveLayout(now) != null }
+
+ val spoken = execute(RESET_APPEARANCE).spokenResult()
+
+ assertEquals("Done.", spoken)
+ awaitOverlay("every override gone") { it.liveLayout(now) == null }
+ }
+
+ // ---- refusal ----------------------------------------------------------------------------------
+
+ /**
+ * An assistant can invent a value we do not support. That must come back as a spoken sentence, not a
+ * crash and not a silently-guessed default — and this branch has never run through the real
+ * dispatcher before.
+ */
+ @Test
+ fun anUnsupportedValue_isRefusedInWordsRatherThanGuessed() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_LAYOUT) { setString("layout", "sideways") }.spokenResult()
+
+ assertEquals("I can show products as a grid or a list.", spoken)
+ awaitOverlay("no layout override at all") { it.liveLayout(now) == null }
+ }
+
+ /** Out-of-range is validated in shared code; this proves the rejection survives the IPC round trip. */
+ @Test
+ fun anOutOfRangeColumnCount_isRefused() = runBlocking {
+ assumeSupported()
+ val spoken = execute(SET_COLUMNS) { setInt("columns", 99) }.spokenResult()
+
+ assertTrue(spoken != "Done.", "99 columns must not be accepted; got \"$spoken\"")
+ awaitOverlay("no column override") { it.liveColumns(now) == null }
+ }
+
+ private companion object {
+ const val PREFIX = "org.itstanany.storefront.channel.StorefrontAppFunctions"
+ const val SET_LAYOUT = "$PREFIX.setLayout"
+ const val SET_DENSITY = "$PREFIX.setDensity"
+ const val SET_PRICES_VISIBLE = "$PREFIX.setPricesVisible"
+ const val SET_COLUMNS = "$PREFIX.setColumns"
+ const val REORDER_SECTIONS = "$PREFIX.reorderSections"
+ const val RESET_APPEARANCE = "$PREFIX.resetAppearance"
+
+ const val METADATA_TIMEOUT_MS = 30_000L
+ const val OVERLAY_TIMEOUT_MS = 5_000L
+ const val POLL_INTERVAL_MS = 100L
+ }
+}
diff --git a/androidApp/src/androidTest/kotlin/org/itstanany/storefront/nl/TierBOnDeviceTest.kt b/androidApp/src/androidTest/kotlin/org/itstanany/storefront/nl/TierBOnDeviceTest.kt
new file mode 100644
index 0000000..224971a
--- /dev/null
+++ b/androidApp/src/androidTest/kotlin/org/itstanany/storefront/nl/TierBOnDeviceTest.kt
@@ -0,0 +1,78 @@
+package org.itstanany.storefront.nl
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.runBlocking
+import org.itstanany.storefront.feature.nl.GgufLanguageModel
+import org.itstanany.storefront.feature.nl.LlamatikInference
+import org.itstanany.storefront.feature.nl.ModelResult
+import org.itstanany.storefront.feature.nl.NlContext
+import org.itstanany.storefront.feature.nl.download.InMemoryModelDownloadRecordStore
+import org.itstanany.storefront.feature.nl.download.ModelDownloadState
+import org.itstanany.storefront.feature.nl.download.ModelSpec
+import org.itstanany.storefront.feature.nl.download.androidModelDownloader
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertTrue
+
+/**
+ * Tier B on real hardware: download a GGUF, load it into llama.cpp, and generate against the schema.
+ *
+ * Everything above the native call is already unit-tested on a host with a fake inference, so what this
+ * adds is the one thing a host cannot answer — whether the native library loads on this ABI and whether
+ * constrained generation actually produces something the shared decoder can read.
+ *
+ * Uses SmolLM2-135M-Instruct (84 MB) rather than the catalogued Qwen3-0.6B (397 MB): the question here is
+ * whether the *pipeline* works, and a 135M model answers that in a fraction of the download and inference
+ * time. Its checksum is the published Git-LFS oid, so verification is exercised for real too.
+ *
+ * The catalogued model was run through this same test manually, and does produce correct patches on an
+ * API 37 emulator: "make it a grid and hide the prices" -> GRID + prices hidden (11.1s), "I want to see
+ * more items at once" -> GRID + 3 columns (6.5s), "play some jazz" -> declined (7.6s). It is not the
+ * committed fixture because a 397 MB download per run is not a reasonable test.
+ */
+@RunWith(AndroidJUnit4::class)
+class TierBOnDeviceTest {
+
+ private val context: Context get() = ApplicationProvider.getApplicationContext()
+
+ private val probe = ModelSpec(
+ id = "smollm2-135m-instruct-q2k",
+ displayName = "SmolLM2 135M Instruct",
+ url = "https://huggingface.co/unsloth/SmolLM2-135M-Instruct-GGUF/resolve/main/" +
+ "SmolLM2-135M-Instruct-Q2_K.gguf",
+ sizeBytes = 88_201_824,
+ sha256 = "c53fe6626c7165ebfd8de5db22edc3f719b813da001e662bc5cb453f2540a076",
+ quantization = "Q2_K",
+ )
+
+ @Test
+ fun downloadsVerifiesLoadsAndGenerates() = runBlocking {
+ val downloader = androidModelDownloader(context, InMemoryModelDownloadRecordStore())
+ downloader.delete(probe)
+
+ val states = downloader.download(probe, allowMetered = true).toList()
+ val ready = states.last()
+ println("TIERB download terminal state: $ready")
+ assertTrue(ready is ModelDownloadState.Ready, "download+verify must succeed, got $ready")
+
+ val progress = states.filterIsInstance()
+ println("TIERB progress updates: ${progress.size}, last=${progress.lastOrNull()?.bytesDownloaded}")
+ assertTrue(progress.isNotEmpty(), "progress must be reported for an 84 MB transfer")
+
+ val model = GgufLanguageModel(LlamatikInference(), (ready as ModelDownloadState.Ready).path)
+ val result = model.classify("make it a grid and hide the prices", NlContext.Default)
+ println("TIERB inference result: $result")
+
+ // A 135M model may well decline or misread; what must hold is that the native path ran and
+ // produced a classified outcome rather than an Unavailable (which would mean it never loaded).
+ assertTrue(
+ result !is ModelResult.Failure ||
+ result.failure !is org.itstanany.storefront.feature.nl.ModelFailure.Unavailable,
+ "model failed to load at all: $result",
+ )
+ downloader.delete(probe)
+ }
+}
diff --git a/androidApp/src/debug/AndroidManifest.xml b/androidApp/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..884d714
--- /dev/null
+++ b/androidApp/src/debug/AndroidManifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/androidApp/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml
index 73d2c3f..6f7f215 100644
--- a/androidApp/src/main/AndroidManifest.xml
+++ b/androidApp/src/main/AndroidManifest.xml
@@ -1,5 +1,12 @@
-
+
+
+
+
@@ -11,6 +18,21 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
+
+
+
+
+
+
+
diff --git a/androidApp/src/main/kotlin/org/itstanany/storefront/MainActivity.kt b/androidApp/src/main/kotlin/org/itstanany/storefront/MainActivity.kt
index 388cede..b23c95b 100644
--- a/androidApp/src/main/kotlin/org/itstanany/storefront/MainActivity.kt
+++ b/androidApp/src/main/kotlin/org/itstanany/storefront/MainActivity.kt
@@ -4,6 +4,9 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
+import org.itstanany.storefront.feature.nl.androidNlEngine
+import org.itstanany.storefront.nl.mlKitBridgeOrNull
+import org.itstanany.storefront.nl.processForegroundState
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -11,8 +14,18 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
val app = application as StorefrontApplication
+ // Tier A joins the shared graph from here, mirroring how the Swift engine joins it on iOS.
+ // Null on any device without AICore — which is every emulator — and the app then runs on the
+ // rule-table parser (ADR 0006).
+ val nlEngine = androidNlEngine(
+ bridge = mlKitBridgeOrNull(),
+ foregroundState = processForegroundState(),
+ // Tier B: reports "not ready" until a model is downloaded, and never starts a download by
+ // itself. It is the tier that still works where AICore refuses to (outside the foreground).
+ tierB = app.tierBSupport,
+ )
setContent {
- App(app.dataStore, app.sqlDriver)
+ App(app.dataStore, app.sqlDriver, nlEngine)
}
}
}
diff --git a/androidApp/src/main/kotlin/org/itstanany/storefront/StorefrontApplication.kt b/androidApp/src/main/kotlin/org/itstanany/storefront/StorefrontApplication.kt
index 00e2187..b0d702d 100644
--- a/androidApp/src/main/kotlin/org/itstanany/storefront/StorefrontApplication.kt
+++ b/androidApp/src/main/kotlin/org/itstanany/storefront/StorefrontApplication.kt
@@ -1,23 +1,127 @@
package org.itstanany.storefront
import android.app.Application
+import android.os.Build
+import android.util.Log
+import androidx.appfunctions.AppFunctionConfiguration
+import org.itstanany.storefront.channel.StorefrontAppFunctions
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
+import org.itstanany.storefront.core.SystemClock
+import org.itstanany.storefront.feature.nl.LlamatikInference
+import org.itstanany.storefront.feature.nl.channel.PreferenceCommands
+import org.itstanany.storefront.preference.DataStorePreferenceOverlayRepository
+import org.itstanany.storefront.feature.nl.TierBSupport
+import org.itstanany.storefront.feature.nl.download.DataStoreModelDownloadRecordStore
+import org.itstanany.storefront.feature.nl.download.ModelDownloader
+import org.itstanany.storefront.feature.nl.download.androidModelDownloader
import org.itstanany.storefront.preference.DATA_STORE_FILE_NAME
import org.itstanany.storefront.preference.createDataStore
+import org.itstanany.storefront.signal.AndroidDatabaseKeyProvider
+import org.itstanany.storefront.signal.Session
+import org.itstanany.storefront.signal.SqlDelightSignalLog
import org.itstanany.storefront.signal.db.StorefrontDatabase
+import org.itstanany.storefront.signal.sqlCipherFactoryOrNull
+
+class StorefrontApplication : Application(), AppFunctionConfiguration.Provider {
+
+ /**
+ * How the AppFunctions runtime constructs [StorefrontAppFunctions]. The library instantiates the
+ * enclosing class itself, so without this factory it would need a no-arg constructor and could not reach
+ * the app's singletons — the assistant would end up writing to a different overlay than the app reads.
+ */
+ override val appFunctionConfiguration: AppFunctionConfiguration
+ get() = AppFunctionConfiguration.Builder()
+ .addEnclosingClassFactory(StorefrontAppFunctions::class.java) { StorefrontAppFunctions() }
+ .build()
-class StorefrontApplication : Application() {
/** App-scoped so the DataStore file is opened exactly once for the process's lifetime. */
val dataStore: DataStore by lazy {
createDataStore { filesDir.resolve(DATA_STORE_FILE_NAME).path }
}
- /** App-scoped SQLite driver for the append-only signal log. */
+ /**
+ * App-scoped SQLite driver for the append-only signal log, encrypted at rest with a per-install
+ * SQLCipher passphrase wrapped by the Android Keystore (ADR 0007).
+ *
+ * Falls back to an unencrypted driver only if SQLCipher's native library cannot load — on an ABI it was
+ * not built for, for instance. Degrading is the right call because the alternative is an app that cannot
+ * start, but it is logged rather than silent: a store that is quietly unencrypted while the app claims
+ * otherwise is worse than one that is openly not.
+ */
val sqlDriver: SqlDriver by lazy {
- AndroidSqliteDriver(StorefrontDatabase.Schema, this, "storefront-signals.db")
+ val factory = runCatching { sqlCipherFactoryOrNull(AndroidDatabaseKeyProvider(this)) }
+ .onFailure { Log.w(TAG, "SQLCipher unavailable; signal log will not be encrypted", it) }
+ .getOrNull()
+
+ if (factory != null) {
+ AndroidSqliteDriver(
+ schema = StorefrontDatabase.Schema,
+ context = this,
+ name = SIGNAL_DB_NAME,
+ factory = factory,
+ )
+ } else {
+ AndroidSqliteDriver(StorefrontDatabase.Schema, this, SIGNAL_DB_NAME)
+ }
+ }
+
+ /**
+ * The shared command surface the OS-assistant channel adapts over. Resolved here rather than through
+ * Koin because an AppFunction is invoked with no screen alive, so there is no Compose scope to inject
+ * from — but it must be the *same* instance the in-app channel uses, or the two would write to
+ * different overlays.
+ */
+ val preferenceCommands: PreferenceCommands by lazy {
+ val clock = SystemClock()
+ PreferenceCommands(
+ overlay = DataStorePreferenceOverlayRepository(dataStore),
+ // Its own session id, because an assistant-driven change genuinely is a separate session from
+ // whatever the user last did in the app — conflating them would corrupt the session grouping the
+ // ranker and the decision log both read.
+ signalLog = SqlDelightSignalLog(
+ database = StorefrontDatabase(sqlDriver),
+ clock = clock,
+ session = Session("appfunction-${clock.nowMs()}"),
+ ),
+ clock = clock,
+ )
+ }
+
+ /**
+ * Downloads Tier-B weights. App-scoped so a download survives the screen that started it, and given
+ * the shared DataStore so the *intent* survives the process too — the `.part` file alone cannot say
+ * whether a stopped transfer was the user's doing or the OS's.
+ */
+ val modelDownloader: ModelDownloader by lazy {
+ androidModelDownloader(this, DataStoreModelDownloadRecordStore(dataStore))
+ }
+
+ /**
+ * Tier B, or null below API 26 — Llamatik's floor, overridden in the manifest so older devices still
+ * install. Constructing it is cheap and starts nothing: it reports "not ready" until a verified model
+ * is on disk, and loading the weights waits for the first use of the engine.
+ */
+ val tierBSupport: TierBSupport? by lazy {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ TierBSupport(downloader = modelDownloader, inference = LlamatikInference())
+ } else {
+ null
+ }
+ }
+
+ private companion object {
+ const val TAG = "StorefrontApplication"
+
+ /**
+ * A distinct filename from the pre-encryption build. An encrypted SQLCipher database cannot be
+ * opened by the plain driver and vice versa, so reusing the old name would make an upgrading install
+ * fail to open its own store. There is no migration because the signal log is a bounded, rebuildable
+ * behavioural cache — starting a fresh one costs a cold-start default layout, not user data.
+ */
+ const val SIGNAL_DB_NAME = "storefront-signals-enc.db"
}
}
diff --git a/androidApp/src/main/kotlin/org/itstanany/storefront/channel/StorefrontAppFunctions.kt b/androidApp/src/main/kotlin/org/itstanany/storefront/channel/StorefrontAppFunctions.kt
new file mode 100644
index 0000000..153e1ae
--- /dev/null
+++ b/androidApp/src/main/kotlin/org/itstanany/storefront/channel/StorefrontAppFunctions.kt
@@ -0,0 +1,118 @@
+package org.itstanany.storefront.channel
+
+import android.content.Context
+import androidx.annotation.RequiresApi
+import androidx.appfunctions.AppFunction
+import androidx.appfunctions.AppFunctionContext
+import org.itstanany.storefront.StorefrontApplication
+import org.itstanany.storefront.feature.nl.channel.CommandResult
+import org.itstanany.storefront.preference.Density
+import org.itstanany.storefront.preference.LayoutType
+import org.itstanany.storefront.spec.SectionRole
+
+/**
+ * The OS-assistant channel: the fourth input onto the Block-4 contract (ADR 0004 stretch).
+ *
+ * Every function here is a thin adapter over the shared `PreferenceCommands` surface, which is where the
+ * validation, the decay TTL and the signal recording live. That is the "build once, N callers" split the
+ * plan asks for — the in-app chatbox, this, and iOS App Intents all end at the same code, so the OS channel
+ * cannot drift from what the app itself does.
+ *
+ * **Typed setters only, no free-text entry point.** The assistant has already done the natural-language
+ * work; feeding its text back through our own parser would strictly degrade the result and widen the
+ * cloud-disclosure surface for nothing (ADR 0006). This is also why the channel needs no model at all,
+ * which is the only reason it can work on Android: AICore refuses to run inference outside the foreground,
+ * so a Tier-A-backed OS channel would fail by construction.
+ *
+ * KDoc *is* the schema — `isDescribedByKDoc = true` means these comments are what the assistant reads to
+ * decide when to call each function, so they are written for that reader rather than for a maintainer.
+ */
+@RequiresApi(36)
+class StorefrontAppFunctions {
+
+ /**
+ * Changes how products are arranged on the store screen.
+ *
+ * @param layout Either "grid" to show products as tiles, or "list" to show them as rows.
+ */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun setLayout(appFunctionContext: AppFunctionContext, layout: String): String =
+ commands(appFunctionContext).let { it ->
+ val parsed = when (layout.lowercase().trim()) {
+ "grid" -> LayoutType.GRID
+ "list" -> LayoutType.LIST
+ // Rejected rather than guessed: an assistant that invents a value should be told, not
+ // silently given one of the two we happen to support.
+ else -> return "I can show products as a grid or a list."
+ }
+ it.setLayout(parsed).describe()
+ }
+
+ /**
+ * Changes how much space is between products on the store screen.
+ *
+ * @param density Either "compact" to fit more on screen, or "comfortable" for more spacing.
+ */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun setDensity(appFunctionContext: AppFunctionContext, density: String): String {
+ val parsed = when (density.lowercase().trim()) {
+ "compact" -> Density.COMPACT
+ "comfortable" -> Density.COMFORTABLE
+ else -> return "I can make the layout compact or comfortable."
+ }
+ return commands(appFunctionContext).setDensity(parsed).describe()
+ }
+
+ /**
+ * Shows or hides product prices on the store screen.
+ *
+ * @param visible True to show prices, false to hide them.
+ */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun setPricesVisible(appFunctionContext: AppFunctionContext, visible: Boolean): String =
+ commands(appFunctionContext).setPricesVisible(visible).describe()
+
+ /**
+ * Sets how many columns of products the grid shows.
+ *
+ * @param columns A whole number from 2 to 4.
+ */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun setColumns(appFunctionContext: AppFunctionContext, columns: Int): String =
+ commands(appFunctionContext).setColumns(columns).describe()
+
+ /**
+ * Chooses which group of products appears first on the store screen.
+ *
+ * @param first Either "recommended" to put personalized picks first, or "all" to put the full catalog
+ * first.
+ */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun reorderSections(appFunctionContext: AppFunctionContext, first: String): String {
+ val order = when (first.lowercase().trim()) {
+ "recommended" -> listOf(SectionRole.RECOMMENDED, SectionRole.ALL)
+ "all", "everything" -> listOf(SectionRole.ALL, SectionRole.RECOMMENDED)
+ else -> return "I can put recommended products or the full catalog first."
+ }
+ return commands(appFunctionContext).reorderSections(order).describe()
+ }
+
+ /** Undoes every display change and goes back to the store's default appearance. */
+ @AppFunction(isDescribedByKDoc = true)
+ suspend fun resetAppearance(appFunctionContext: AppFunctionContext): String =
+ commands(appFunctionContext).reset().describe()
+
+ /**
+ * Resolved per call from the application rather than injected, because an assistant invokes this with no
+ * screen alive and therefore no Compose/Koin scope to inject from. The commands object itself is an app
+ * singleton, so this is a lookup rather than a construction.
+ */
+ private fun commands(context: AppFunctionContext) =
+ (context.context.applicationContext as StorefrontApplication).preferenceCommands
+
+ /** Assistants speak their result, so both outcomes have to be a sentence. */
+ private fun CommandResult.describe(): String = when (this) {
+ CommandResult.Applied -> "Done."
+ is CommandResult.Rejected -> reason
+ }
+}
diff --git a/androidApp/src/main/kotlin/org/itstanany/storefront/nl/MlKitGenerativeBridge.kt b/androidApp/src/main/kotlin/org/itstanany/storefront/nl/MlKitGenerativeBridge.kt
new file mode 100644
index 0000000..0e1832f
--- /dev/null
+++ b/androidApp/src/main/kotlin/org/itstanany/storefront/nl/MlKitGenerativeBridge.kt
@@ -0,0 +1,81 @@
+package org.itstanany.storefront.nl
+
+import android.os.Build
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.ProcessLifecycleOwner
+import com.google.mlkit.genai.common.GenAiException
+import com.google.mlkit.genai.prompt.Generation
+import com.google.mlkit.genai.prompt.GenerativeModel
+import com.google.mlkit.genai.prompt.PromptPrefix
+import com.google.mlkit.genai.prompt.TextPart
+import com.google.mlkit.genai.prompt.generateContentRequest
+import org.itstanany.storefront.feature.nl.AndroidGenAiFailure
+import org.itstanany.storefront.feature.nl.AndroidGenerativeBridge
+import org.itstanany.storefront.feature.nl.ForegroundState
+
+/**
+ * The vendor half of Tier A on Android (ADR 0006): ML Kit's GenAI Prompt API over Gemini Nano.
+ *
+ * Deliberately thin. It calls the API, translates `GenAiException` into the shared
+ * [AndroidGenAiFailure], and nothing else — classifying the failure, decoding the reply and validating
+ * it all happen in shared code, where they are unit-tested without a device. That matters more than
+ * usual here, because AICore exists only on flagship hardware and cannot be exercised on an emulator.
+ *
+ * The prompt is sent as `promptPrefix` + text, which is the API's own prefix-caching mechanism, so the
+ * invariant half of the prompt is not re-tokenised on every request.
+ */
+class MlKitGenerativeBridge(
+ private val model: GenerativeModel = Generation.getClient(),
+) : AndroidGenerativeBridge {
+
+ override suspend fun featureStatus(): Int = wrap { model.checkStatus() }
+
+ override suspend fun warmup() {
+ wrap { model.warmup() }
+ }
+
+ override suspend fun generate(prefix: String, suffix: String): String = wrap {
+ val request = generateContentRequest(TextPart(suffix)) {
+ promptPrefix = PromptPrefix(prefix)
+ // Determinism first: this is a classification, not creative writing, and the snapshot and
+ // fixture tests depend on the same input producing the same layout.
+ temperature = 0.0f
+ candidateCount = 1
+ }
+ model.generateContent(request).candidates.firstOrNull()?.text.orEmpty()
+ }
+
+ /**
+ * `getRetryDelay()` is the platform telling us how long to wait — always better than a guess, and
+ * the shared resolver honours it when present.
+ */
+ private inline fun wrap(block: () -> T): T =
+ try {
+ block()
+ } catch (exception: GenAiException) {
+ throw AndroidGenAiFailure(
+ errorCode = exception.errorCode,
+ retryAfterMs = runCatching { exception.retryDelay?.toMillis() }.getOrNull(),
+ cause = exception,
+ )
+ }
+}
+
+/**
+ * Tier A requires API 26 (ML Kit's own floor) and AICore, which no emulator provides. Returning null
+ * is a supported configuration and the common one: the app runs on the rule-table parser.
+ */
+fun mlKitBridgeOrNull(): AndroidGenerativeBridge? =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ runCatching { MlKitGenerativeBridge() }.getOrNull()
+ } else {
+ null
+ }
+
+/**
+ * The answer to AICore's documented `BUSY` ambiguity — it means transient quota *or* disallowed
+ * background use, and only our own process state distinguishes them.
+ */
+fun processForegroundState(): ForegroundState = ForegroundState {
+ ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
+}
diff --git a/androidApp/src/release/generated/baselineProfiles/baseline-prof.txt b/androidApp/src/release/generated/baselineProfiles/baseline-prof.txt
new file mode 100644
index 0000000..b035ea9
--- /dev/null
+++ b/androidApp/src/release/generated/baselineProfiles/baseline-prof.txt
@@ -0,0 +1,31991 @@
+Landroidx/activity/ActivityFlags;
+SPLandroidx/activity/ActivityFlags;->()V
+SPLandroidx/activity/ActivityFlags;->()V
+Landroidx/activity/ComponentActivity;
+SPLandroidx/activity/ComponentActivity;->()V
+SPLandroidx/activity/ComponentActivity;->()V
+SPLandroidx/activity/ComponentActivity;->_init_$lambda$1(Landroidx/activity/ComponentActivity;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+SPLandroidx/activity/ComponentActivity;->_init_$lambda$2(Landroidx/activity/ComponentActivity;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+SPLandroidx/activity/ComponentActivity;->_init_$lambda$4(Landroidx/activity/ComponentActivity;Landroid/content/Context;)V
+SPLandroidx/activity/ComponentActivity;->access$ensureViewModelStore(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity;->addObserverForBackInvoker$lambda$0(Landroidx/activity/OnBackPressedDispatcher;Landroidx/activity/ComponentActivity;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+SPLandroidx/activity/ComponentActivity;->addObserverForBackInvoker(Landroidx/activity/OnBackPressedDispatcher;)V
+SPLandroidx/activity/ComponentActivity;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
+SPLandroidx/activity/ComponentActivity;->createFullyDrawnExecutor()Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
+SPLandroidx/activity/ComponentActivity;->ensureViewModelStore()V
+SPLandroidx/activity/ComponentActivity;->getDefaultViewModelCreationExtras()Landroidx/lifecycle/viewmodel/CreationExtras;
+SPLandroidx/activity/ComponentActivity;->getLifecycle()Landroidx/lifecycle/Lifecycle;
+SPLandroidx/activity/ComponentActivity;->getNavigationEventDispatcher()Landroidx/navigationevent/NavigationEventDispatcher;
+SPLandroidx/activity/ComponentActivity;->getOnBackPressedDispatcher()Landroidx/activity/OnBackPressedDispatcher;
+SPLandroidx/activity/ComponentActivity;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
+SPLandroidx/activity/ComponentActivity;->getViewModelStore()Landroidx/lifecycle/ViewModelStore;
+SPLandroidx/activity/ComponentActivity;->initializeViewTreeOwners()V
+SPLandroidx/activity/ComponentActivity;->onBackPressedDispatcher_delegate$lambda$0(Landroidx/activity/ComponentActivity;)Landroidx/activity/OnBackPressedDispatcher;
+SPLandroidx/activity/ComponentActivity;->onCreate(Landroid/os/Bundle;)V
+SPLandroidx/activity/ComponentActivity;->setContentView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda10;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda10;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda11;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda11;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda11;->invoke()Ljava/lang/Object;
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda12;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda12;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;->(Landroidx/activity/OnBackPressedDispatcher;Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda4;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda4;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda5;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda5;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda6;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda6;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda6;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda7;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda7;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda7;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda8;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda8;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda9;
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda9;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda9;->onContextAvailable(Landroid/content/Context;)V
+Landroidx/activity/ComponentActivity$4;
+SPLandroidx/activity/ComponentActivity$4;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$4;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+Landroidx/activity/ComponentActivity$Companion;
+SPLandroidx/activity/ComponentActivity$Companion;->()V
+SPLandroidx/activity/ComponentActivity$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+Landroidx/activity/ComponentActivity$NonConfigurationInstances;
+Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
+Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutorImpl;
+SPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorImpl;->(Landroidx/activity/ComponentActivity;)V
+SPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorImpl;->onDraw()V
+PLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorImpl;->run()V
+SPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorImpl;->viewCreated(Landroid/view/View;)V
+Landroidx/activity/ComponentActivity$activityResultRegistry$1;
+SPLandroidx/activity/ComponentActivity$activityResultRegistry$1;->(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/ComponentDialog;
+SPLandroidx/activity/ComponentDialog;->(Landroid/content/Context;I)V
+SPLandroidx/activity/ComponentDialog;->(Landroid/content/Context;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/activity/ComponentDialog;->getLifecycle()Landroidx/lifecycle/Lifecycle;
+SPLandroidx/activity/ComponentDialog;->getLifecycleRegistry()Landroidx/lifecycle/LifecycleRegistry;
+SPLandroidx/activity/ComponentDialog;->getOnBackPressedDispatcher()Landroidx/activity/OnBackPressedDispatcher;
+SPLandroidx/activity/ComponentDialog;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
+SPLandroidx/activity/ComponentDialog;->initializeViewTreeOwners()V
+SPLandroidx/activity/ComponentDialog;->onBackPressedDispatcher_delegate$lambda$0(Landroidx/activity/ComponentDialog;)Landroidx/activity/OnBackPressedDispatcher;
+SPLandroidx/activity/ComponentDialog;->onCreate(Landroid/os/Bundle;)V
+SPLandroidx/activity/ComponentDialog;->onStart()V
+SPLandroidx/activity/ComponentDialog;->onStop()V
+SPLandroidx/activity/ComponentDialog;->setContentView(Landroid/view/View;)V
+Landroidx/activity/ComponentDialog$$ExternalSyntheticLambda0;
+SPLandroidx/activity/ComponentDialog$$ExternalSyntheticLambda0;->(Landroidx/activity/ComponentDialog;)V
+Landroidx/activity/ComponentDialog$$ExternalSyntheticLambda1;
+SPLandroidx/activity/ComponentDialog$$ExternalSyntheticLambda1;->(Landroidx/activity/ComponentDialog;)V
+Landroidx/activity/ComponentDialog$$ExternalSyntheticLambda2;
+SPLandroidx/activity/ComponentDialog$$ExternalSyntheticLambda2;->(Landroidx/activity/ComponentDialog;)V
+SPLandroidx/activity/ComponentDialog$$ExternalSyntheticLambda2;->invoke()Ljava/lang/Object;
+Landroidx/activity/EdgeToEdge;
+SPLandroidx/activity/EdgeToEdge;->()V
+SPLandroidx/activity/EdgeToEdge;->enable$default(Landroidx/activity/ComponentActivity;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;ILjava/lang/Object;)V
+SPLandroidx/activity/EdgeToEdge;->enable(Landroidx/activity/ComponentActivity;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;)V
+SPLandroidx/activity/EdgeToEdge;->enableEdgeToEdge$lambda$1(Landroidx/activity/EdgeToEdgeImpl;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;Landroidx/activity/ComponentActivity;Landroid/view/View;)V
+Landroidx/activity/EdgeToEdge$$ExternalSyntheticLambda0;
+SPLandroidx/activity/EdgeToEdge$$ExternalSyntheticLambda0;->(Landroidx/activity/EdgeToEdgeImpl;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;Landroidx/activity/ComponentActivity;Landroid/view/View;)V
+SPLandroidx/activity/EdgeToEdge$$ExternalSyntheticLambda0;->run()V
+Landroidx/activity/EdgeToEdge$enableEdgeToEdge$1$2;
+SPLandroidx/activity/EdgeToEdge$enableEdgeToEdge$1$2;->(Ljava/lang/Runnable;Landroid/content/Context;)V
+Landroidx/activity/EdgeToEdgeApi26;
+SPLandroidx/activity/EdgeToEdgeApi26;->()V
+Landroidx/activity/EdgeToEdgeApi28;
+SPLandroidx/activity/EdgeToEdgeApi28;->()V
+Landroidx/activity/EdgeToEdgeApi29;
+SPLandroidx/activity/EdgeToEdgeApi29;->()V
+Landroidx/activity/EdgeToEdgeApi30;
+SPLandroidx/activity/EdgeToEdgeApi30;->()V
+SPLandroidx/activity/EdgeToEdgeApi30;->adjustLayoutInDisplayCutoutMode(Landroid/view/Window;)V
+Landroidx/activity/EdgeToEdgeApi35;
+SPLandroidx/activity/EdgeToEdgeApi35;->()V
+SPLandroidx/activity/EdgeToEdgeApi35;->setUp(Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;Landroid/view/Window;Landroid/view/View;ZZ)V
+Landroidx/activity/EdgeToEdgeBase;
+SPLandroidx/activity/EdgeToEdgeBase;->()V
+Landroidx/activity/EdgeToEdgeImpl;
+Landroidx/activity/FullyDrawnReporterOwner;
+Landroidx/activity/OnBackPressedCallback;
+SPLandroidx/activity/OnBackPressedCallback;->(Z)V
+SPLandroidx/activity/OnBackPressedCallback;->addCloseable$activity(Ljava/lang/AutoCloseable;)V
+SPLandroidx/activity/OnBackPressedCallback;->createNavigationEventHandler$activity(Landroidx/navigationevent/NavigationEventInfo;)Landroidx/activity/OnBackPressedCallback$OnBackPressedEventHandler;
+SPLandroidx/activity/OnBackPressedCallback;->isEnabled()Z
+SPLandroidx/activity/OnBackPressedCallback;->setEnabled(Z)V
+Landroidx/activity/OnBackPressedCallback$OnBackPressedEventHandler;
+SPLandroidx/activity/OnBackPressedCallback$OnBackPressedEventHandler;->(Landroidx/activity/OnBackPressedCallback;Landroidx/navigationevent/NavigationEventInfo;)V
+SPLandroidx/activity/OnBackPressedCallback$OnBackPressedEventHandler;->setLifecycleActive(Z)V
+Landroidx/activity/OnBackPressedCallbackInfo;
+SPLandroidx/activity/OnBackPressedCallbackInfo;->(Landroidx/activity/OnBackPressedCallback;Landroidx/lifecycle/LifecycleOwner;)V
+Landroidx/activity/OnBackPressedDispatcher;
+SPLandroidx/activity/OnBackPressedDispatcher;->(Ljava/lang/Runnable;)V
+SPLandroidx/activity/OnBackPressedDispatcher;->(Ljava/lang/Runnable;Landroidx/core/util/Consumer;)V
+SPLandroidx/activity/OnBackPressedDispatcher;->access$getOnHasEnabledCallbacksChanged$p(Landroidx/activity/OnBackPressedDispatcher;)Landroidx/core/util/Consumer;
+SPLandroidx/activity/OnBackPressedDispatcher;->access$setHasEnabledCallbacks$p(Landroidx/activity/OnBackPressedDispatcher;Z)V
+SPLandroidx/activity/OnBackPressedDispatcher;->addCallback(Landroidx/lifecycle/LifecycleOwner;Landroidx/activity/OnBackPressedCallback;)V
+SPLandroidx/activity/OnBackPressedDispatcher;->eventInput_delegate$lambda$0(Landroidx/activity/OnBackPressedDispatcher;)Landroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;
+SPLandroidx/activity/OnBackPressedDispatcher;->getEventDispatcher$activity()Landroidx/navigationevent/NavigationEventDispatcher;
+SPLandroidx/activity/OnBackPressedDispatcher;->getEventInput()Landroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;
+SPLandroidx/activity/OnBackPressedDispatcher;->setOnBackInvokedDispatcher(Landroid/window/OnBackInvokedDispatcher;)V
+Landroidx/activity/OnBackPressedDispatcher$$ExternalSyntheticLambda0;
+SPLandroidx/activity/OnBackPressedDispatcher$$ExternalSyntheticLambda0;->(Landroidx/activity/OnBackPressedDispatcher;)V
+SPLandroidx/activity/OnBackPressedDispatcher$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object;
+Landroidx/activity/OnBackPressedDispatcher$$ExternalSyntheticLambda1;
+SPLandroidx/activity/OnBackPressedDispatcher$$ExternalSyntheticLambda1;->(Landroidx/lifecycle/Lifecycle;Landroidx/activity/OnBackPressedDispatcher$addCallback$observer$1;)V
+Landroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;
+SPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;->(Landroidx/activity/OnBackPressedDispatcher;)V
+SPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;->getDispatcher()Landroidx/navigationevent/NavigationEventDispatcher;
+SPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput;->onHasEnabledHandlersChanged(Z)V
+Landroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput$$ExternalSyntheticLambda0;
+SPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedEventInput$$ExternalSyntheticLambda0;->(Landroidx/activity/OnBackPressedDispatcher;)V
+Landroidx/activity/OnBackPressedDispatcher$addCallback$observer$1;
+SPLandroidx/activity/OnBackPressedDispatcher$addCallback$observer$1;->(Landroidx/activity/OnBackPressedCallback$OnBackPressedEventHandler;Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/Lifecycle;)V
+SPLandroidx/activity/OnBackPressedDispatcher$addCallback$observer$1;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
+Landroidx/activity/OnBackPressedDispatcher$addCallback$observer$1$WhenMappings;
+SPLandroidx/activity/OnBackPressedDispatcher$addCallback$observer$1$WhenMappings;->()V
+Landroidx/activity/OnBackPressedDispatcherKt;
+SPLandroidx/activity/OnBackPressedDispatcherKt;->addCallback$default(Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Landroidx/activity/OnBackPressedCallback;
+SPLandroidx/activity/OnBackPressedDispatcherKt;->addCallback(Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function1;)Landroidx/activity/OnBackPressedCallback;
+Landroidx/activity/OnBackPressedDispatcherKt$addCallback$callback$1;
+SPLandroidx/activity/OnBackPressedDispatcherKt$addCallback$callback$1;->(ZLkotlin/jvm/functions/Function1;)V
+Landroidx/activity/OnBackPressedDispatcherOwner;
+Landroidx/activity/R$id;
+Landroidx/activity/SystemBarStyle;
+SPLandroidx/activity/SystemBarStyle;->()V
+SPLandroidx/activity/SystemBarStyle;->(IIILkotlin/jvm/functions/Function1;)V
+SPLandroidx/activity/SystemBarStyle;->(IIILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/activity/SystemBarStyle;->getDetectDarkMode$activity()Lkotlin/jvm/functions/Function1;
+SPLandroidx/activity/SystemBarStyle;->getNightMode$activity()I
+SPLandroidx/activity/SystemBarStyle;->getScrimWithEnforcedContrast$activity(Z)I
+Landroidx/activity/SystemBarStyle$Companion;
+SPLandroidx/activity/SystemBarStyle$Companion;->()V
+SPLandroidx/activity/SystemBarStyle$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/activity/SystemBarStyle$Companion;->auto$default(Landroidx/activity/SystemBarStyle$Companion;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Landroidx/activity/SystemBarStyle;
+SPLandroidx/activity/SystemBarStyle$Companion;->auto$lambda$0(Landroid/content/res/Resources;)Z
+SPLandroidx/activity/SystemBarStyle$Companion;->auto(IILkotlin/jvm/functions/Function1;)Landroidx/activity/SystemBarStyle;
+Landroidx/activity/SystemBarStyle$Companion$$ExternalSyntheticLambda2;
+SPLandroidx/activity/SystemBarStyle$Companion$$ExternalSyntheticLambda2;->()V
+SPLandroidx/activity/SystemBarStyle$Companion$$ExternalSyntheticLambda2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/activity/ViewTreeFullyDrawnReporterOwner;
+SPLandroidx/activity/ViewTreeFullyDrawnReporterOwner;->set(Landroid/view/View;Landroidx/activity/FullyDrawnReporterOwner;)V
+Landroidx/activity/ViewTreeOnBackPressedDispatcherOwner;
+SPLandroidx/activity/ViewTreeOnBackPressedDispatcherOwner;->set(Landroid/view/View;Landroidx/activity/OnBackPressedDispatcherOwner;)V
+Landroidx/activity/compose/ComponentActivityKt;
+SPLandroidx/activity/compose/ComponentActivityKt;->()V
+SPLandroidx/activity/compose/ComponentActivityKt;->setContent$default(Landroidx/activity/ComponentActivity;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+SPLandroidx/activity/compose/ComponentActivityKt;->setContent(Landroidx/activity/ComponentActivity;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;)V
+SPLandroidx/activity/compose/ComponentActivityKt;->setOwners(Landroidx/activity/ComponentActivity;)V
+Landroidx/activity/compose/ComposePredictiveBackHandler;
+SPLandroidx/activity/compose/ComposePredictiveBackHandler;->(Lkotlinx/coroutines/CoroutineScope;Landroidx/activity/compose/PredictiveBackHandlerInfo;)V
+SPLandroidx/activity/compose/ComposePredictiveBackHandler;->setBackEnabled(Z)V
+SPLandroidx/activity/compose/ComposePredictiveBackHandler;->setCurrentOnBack(Lkotlin/jvm/functions/Function2;)V
+Landroidx/activity/compose/ComposePredictiveBackHandler$currentOnBack$1;
+SPLandroidx/activity/compose/ComposePredictiveBackHandler$currentOnBack$1;->(Lkotlin/coroutines/Continuation;)V
+Landroidx/activity/compose/PredictiveBackHandlerInfo;
+SPLandroidx/activity/compose/PredictiveBackHandlerInfo;->(Ljava/lang/Object;J)V
+Landroidx/activity/compose/PredictiveBackHandlerKt;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->$r8$lambda$-I2Xi7-mOChmMAZ9qZZEwheaxs4(Landroidx/activity/compose/ComposePredictiveBackHandler;Lkotlin/jvm/functions/Function2;)Lkotlin/Unit;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->$r8$lambda$D8a2kH5mKpDy4Fdrtpqcav0aLMg(Landroidx/activity/compose/ComposePredictiveBackHandler;ZLandroidx/lifecycle/compose/LifecycleStartStopEffectScope;)Landroidx/lifecycle/compose/LifecycleStopOrDisposeEffectResult;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->$r8$lambda$Qyg5QBqA91q-6Cfl0DPwFa5-Xpg(Landroidx/activity/compose/internal/BackHandlerDispatcherCompat;Landroidx/activity/compose/ComposePredictiveBackHandler;Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->PredictiveBackHandler$lambda$2$0(Landroidx/activity/compose/ComposePredictiveBackHandler;Lkotlin/jvm/functions/Function2;)Lkotlin/Unit;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->PredictiveBackHandler$lambda$3$0(Landroidx/activity/compose/ComposePredictiveBackHandler;ZLandroidx/lifecycle/compose/LifecycleStartStopEffectScope;)Landroidx/lifecycle/compose/LifecycleStopOrDisposeEffectResult;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->PredictiveBackHandler$lambda$4$0(Landroidx/activity/compose/internal/BackHandlerDispatcherCompat;Landroidx/activity/compose/ComposePredictiveBackHandler;Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt;->PredictiveBackHandler(ZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
+Landroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda0;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda0;->(Landroidx/activity/compose/ComposePredictiveBackHandler;Lkotlin/jvm/functions/Function2;)V
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object;
+Landroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda1;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda1;->(Landroidx/activity/compose/ComposePredictiveBackHandler;Z)V
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda2;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda2;->(Landroidx/activity/compose/internal/BackHandlerDispatcherCompat;Landroidx/activity/compose/ComposePredictiveBackHandler;)V
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$$ExternalSyntheticLambda2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/activity/compose/PredictiveBackHandlerKt$PredictiveBackHandler$lambda$3$0$$inlined$onStopOrDispose$1;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$PredictiveBackHandler$lambda$3$0$$inlined$onStopOrDispose$1;->(Landroidx/lifecycle/compose/LifecycleStartStopEffectScope;Landroidx/activity/compose/ComposePredictiveBackHandler;)V
+Landroidx/activity/compose/PredictiveBackHandlerKt$PredictiveBackHandler$lambda$4$0$$inlined$onDispose$1;
+SPLandroidx/activity/compose/PredictiveBackHandlerKt$PredictiveBackHandler$lambda$4$0$$inlined$onDispose$1;->(Landroidx/activity/compose/internal/BackHandlerDispatcherCompat;Landroidx/activity/compose/ComposePredictiveBackHandler;)V
+Landroidx/activity/compose/internal/BackHandlerCompat;
+SPLandroidx/activity/compose/internal/BackHandlerCompat;->()V
+SPLandroidx/activity/compose/internal/BackHandlerCompat;->(Landroidx/navigationevent/NavigationEventInfo;)V
+SPLandroidx/activity/compose/internal/BackHandlerCompat;->getNavigationEventHandler()Landroidx/navigationevent/NavigationEventHandler;
+SPLandroidx/activity/compose/internal/BackHandlerCompat;->isBackEnabled()Z
+SPLandroidx/activity/compose/internal/BackHandlerCompat;->setBackEnabled(Z)V
+Landroidx/activity/compose/internal/BackHandlerCompat$navigationEventHandler$1;
+SPLandroidx/activity/compose/internal/BackHandlerCompat$navigationEventHandler$1;->(Landroidx/activity/compose/internal/BackHandlerCompat;Landroidx/navigationevent/NavigationEventInfo;)V
+Landroidx/activity/compose/internal/BackHandlerCompat$onBackPressedCallback$1;
+SPLandroidx/activity/compose/internal/BackHandlerCompat$onBackPressedCallback$1;->(Landroidx/activity/compose/internal/BackHandlerCompat;)V
+Landroidx/activity/compose/internal/BackHandlerDispatcherCompat;
+SPLandroidx/activity/compose/internal/BackHandlerDispatcherCompat;->()V
+SPLandroidx/activity/compose/internal/BackHandlerDispatcherCompat;->(Landroidx/navigationevent/NavigationEventDispatcher;Landroidx/activity/OnBackPressedDispatcher;)V
+SPLandroidx/activity/compose/internal/BackHandlerDispatcherCompat;->addHandler(Landroidx/activity/compose/internal/BackHandlerCompat;)V
+Landroidx/activity/contextaware/ContextAware;
+Landroidx/activity/contextaware/ContextAwareHelper;
+SPLandroidx/activity/contextaware/ContextAwareHelper;->()V
+SPLandroidx/activity/contextaware/ContextAwareHelper;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
+SPLandroidx/activity/contextaware/ContextAwareHelper;->dispatchOnContextAvailable(Landroid/content/Context;)V
+Landroidx/activity/contextaware/OnContextAvailableListener;
+Landroidx/activity/result/ActivityResultCaller;
+Landroidx/activity/result/ActivityResultRegistry;
+SPLandroidx/activity/result/ActivityResultRegistry;->()V
+SPLandroidx/activity/result/ActivityResultRegistry;->()V
+Landroidx/activity/result/ActivityResultRegistry$Companion;
+SPLandroidx/activity/result/ActivityResultRegistry$Companion;->()V
+SPLandroidx/activity/result/ActivityResultRegistry$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+Landroidx/activity/result/ActivityResultRegistryOwner;
+Landroidx/appfunctions/AppFunctionConfiguration$Provider;
+PLandroidx/appfunctions/internal/AppSearchUtilsKt$$ExternalSyntheticLambda0;->()V
+Landroidx/arch/core/executor/ArchTaskExecutor;
+SPLandroidx/arch/core/executor/ArchTaskExecutor;->()V
+SPLandroidx/arch/core/executor/ArchTaskExecutor;->()V
+SPLandroidx/arch/core/executor/ArchTaskExecutor;->getInstance()Landroidx/arch/core/executor/ArchTaskExecutor;
+SPLandroidx/arch/core/executor/ArchTaskExecutor;->isMainThread()Z
+Landroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda0;
+SPLandroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda0;->()V
+Landroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda1;
+SPLandroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda1;->()V
+Landroidx/arch/core/executor/DefaultTaskExecutor;
+SPLandroidx/arch/core/executor/DefaultTaskExecutor;->()V
+SPLandroidx/arch/core/executor/DefaultTaskExecutor;->isMainThread()Z
+Landroidx/arch/core/executor/DefaultTaskExecutor$1;
+SPLandroidx/arch/core/executor/DefaultTaskExecutor$1;->(Landroidx/arch/core/executor/DefaultTaskExecutor;)V
+Landroidx/arch/core/executor/TaskExecutor;
+SPLandroidx/arch/core/executor/TaskExecutor;->()V
+Landroidx/collection/ArraySet;
+SPLandroidx/collection/ArraySet;->()V
+SPLandroidx/collection/ArraySet;->(I)V
+SPLandroidx/collection/ArraySet;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ArraySet;->add(Ljava/lang/Object;)Z
+SPLandroidx/collection/ArraySet;->clear()V
+SPLandroidx/collection/ArraySet;->getArray$collection()[Ljava/lang/Object;
+SPLandroidx/collection/ArraySet;->getHashes$collection()[I
+SPLandroidx/collection/ArraySet;->get_size$collection()I
+SPLandroidx/collection/ArraySet;->setArray$collection([Ljava/lang/Object;)V
+SPLandroidx/collection/ArraySet;->setHashes$collection([I)V
+SPLandroidx/collection/ArraySet;->set_size$collection(I)V
+SPLandroidx/collection/ArraySet;->toArray()[Ljava/lang/Object;
+Landroidx/collection/ArraySetKt;
+SPLandroidx/collection/ArraySetKt;->allocArrays(Landroidx/collection/ArraySet;I)V
+SPLandroidx/collection/ArraySetKt;->indexOf(Landroidx/collection/ArraySet;Ljava/lang/Object;I)I
+Landroidx/collection/FloatFloatPair;
+SPLandroidx/collection/FloatFloatPair;->constructor-impl(FF)J
+SPLandroidx/collection/FloatFloatPair;->constructor-impl(J)J
+Landroidx/collection/FloatSet;
+SPLandroidx/collection/FloatSet;->()V
+SPLandroidx/collection/FloatSet;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/FloatSet;->getCapacity()I
+Landroidx/collection/FloatSetKt;
+SPLandroidx/collection/FloatSetKt;->()V
+SPLandroidx/collection/FloatSetKt;->getEmptyFloatArray()[F
+Landroidx/collection/IntIntMap;
+SPLandroidx/collection/IntIntMap;->()V
+SPLandroidx/collection/IntIntMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HPLandroidx/collection/IntIntMap;->findKeyIndex(I)I
+SPLandroidx/collection/IntIntMap;->getCapacity()I
+HPLandroidx/collection/IntIntMap;->getOrDefault(II)I
+Landroidx/collection/IntIntMapKt;
+SPLandroidx/collection/IntIntMapKt;->()V
+SPLandroidx/collection/IntIntMapKt;->mutableIntIntMapOf()Landroidx/collection/MutableIntIntMap;
+Landroidx/collection/IntIntPair;
+SPLandroidx/collection/IntIntPair;->(J)V
+SPLandroidx/collection/IntIntPair;->box-impl(J)Landroidx/collection/IntIntPair;
+SPLandroidx/collection/IntIntPair;->constructor-impl(II)J
+SPLandroidx/collection/IntIntPair;->constructor-impl(J)J
+SPLandroidx/collection/IntIntPair;->getFirst-impl(J)I
+SPLandroidx/collection/IntIntPair;->getSecond-impl(J)I
+SPLandroidx/collection/IntIntPair;->unbox-impl()J
+Landroidx/collection/IntList;
+SPLandroidx/collection/IntList;->(I)V
+SPLandroidx/collection/IntList;->(ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/IntList;->binarySearch$default(Landroidx/collection/IntList;IIIILjava/lang/Object;)I
+SPLandroidx/collection/IntList;->binarySearch(III)I
+SPLandroidx/collection/IntList;->get(I)I
+SPLandroidx/collection/IntList;->last()I
+Landroidx/collection/IntListKt;
+SPLandroidx/collection/IntListKt;->()V
+SPLandroidx/collection/IntListKt;->emptyIntList()Landroidx/collection/IntList;
+SPLandroidx/collection/IntListKt;->intListOf([I)Landroidx/collection/IntList;
+Landroidx/collection/IntObjectMap;
+SPLandroidx/collection/IntObjectMap;->()V
+SPLandroidx/collection/IntObjectMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/IntObjectMap;->containsKey(I)Z
+HSPLandroidx/collection/IntObjectMap;->get(I)Ljava/lang/Object;
+SPLandroidx/collection/IntObjectMap;->getCapacity()I
+SPLandroidx/collection/IntObjectMap;->getSize()I
+Landroidx/collection/IntObjectMapKt;
+SPLandroidx/collection/IntObjectMapKt;->()V
+SPLandroidx/collection/IntObjectMapKt;->intObjectMapOf()Landroidx/collection/IntObjectMap;
+SPLandroidx/collection/IntObjectMapKt;->mutableIntObjectMapOf()Landroidx/collection/MutableIntObjectMap;
+SPLandroidx/collection/IntObjectMapKt;->mutableIntObjectMapOf(ILjava/lang/Object;ILjava/lang/Object;ILjava/lang/Object;)Landroidx/collection/MutableIntObjectMap;
+Landroidx/collection/IntSet;
+SPLandroidx/collection/IntSet;->()V
+SPLandroidx/collection/IntSet;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/IntSet;->contains(I)Z
+SPLandroidx/collection/IntSet;->getCapacity()I
+SPLandroidx/collection/IntSet;->isEmpty()Z
+SPLandroidx/collection/IntSet;->isNotEmpty()Z
+Landroidx/collection/IntSetKt;
+SPLandroidx/collection/IntSetKt;->()V
+SPLandroidx/collection/IntSetKt;->getEmptyIntArray()[I
+SPLandroidx/collection/IntSetKt;->mutableIntSetOf()Landroidx/collection/MutableIntSet;
+Landroidx/collection/LongList;
+SPLandroidx/collection/LongList;->(I)V
+SPLandroidx/collection/LongList;->(ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/LongList;->get(I)J
+Landroidx/collection/LongObjectMap;
+SPLandroidx/collection/LongObjectMap;->()V
+SPLandroidx/collection/LongObjectMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/LongObjectMap;->get(J)Ljava/lang/Object;
+SPLandroidx/collection/LongObjectMap;->getCapacity()I
+Landroidx/collection/LongObjectMapKt;
+SPLandroidx/collection/LongObjectMapKt;->()V
+SPLandroidx/collection/LongObjectMapKt;->mutableLongObjectMapOf()Landroidx/collection/MutableLongObjectMap;
+Landroidx/collection/LongSet;
+SPLandroidx/collection/LongSet;->()V
+SPLandroidx/collection/LongSet;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+PLandroidx/collection/LongSet;->contains(J)Z
+SPLandroidx/collection/LongSet;->getCapacity()I
+Landroidx/collection/LongSetKt;
+SPLandroidx/collection/LongSetKt;->()V
+SPLandroidx/collection/LongSetKt;->getEmptyLongArray()[J
+Landroidx/collection/LongSparseArray;
+SPLandroidx/collection/LongSparseArray;->(I)V
+SPLandroidx/collection/LongSparseArray;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/LongSparseArray;->clear()V
+SPLandroidx/collection/LongSparseArray;->containsKey(J)Z
+SPLandroidx/collection/LongSparseArray;->get(J)Ljava/lang/Object;
+SPLandroidx/collection/LongSparseArray;->indexOfKey(J)I
+SPLandroidx/collection/LongSparseArray;->isEmpty()Z
+SPLandroidx/collection/LongSparseArray;->keyAt(I)J
+SPLandroidx/collection/LongSparseArray;->put(JLjava/lang/Object;)V
+SPLandroidx/collection/LongSparseArray;->remove(J)V
+SPLandroidx/collection/LongSparseArray;->size()I
+SPLandroidx/collection/LongSparseArray;->valueAt(I)Ljava/lang/Object;
+Landroidx/collection/LongSparseArrayKt;
+PLandroidx/collection/LongSparseArrayKt;->()V
+SPLandroidx/collection/LongSparseArrayKt;->access$getDELETED$p()Ljava/lang/Object;
+Landroidx/collection/LruCache;
+SPLandroidx/collection/LruCache;->(I)V
+SPLandroidx/collection/LruCache;->create(Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/collection/LruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/collection/LruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/collection/LruCache;->safeSizeOf(Ljava/lang/Object;Ljava/lang/Object;)I
+SPLandroidx/collection/LruCache;->sizeOf(Ljava/lang/Object;Ljava/lang/Object;)I
+SPLandroidx/collection/LruCache;->trimToSize(I)V
+Landroidx/collection/MutableFloatSet;
+SPLandroidx/collection/MutableFloatSet;->(I)V
+SPLandroidx/collection/MutableFloatSet;->initializeGrowth()V
+SPLandroidx/collection/MutableFloatSet;->initializeMetadata(I)V
+SPLandroidx/collection/MutableFloatSet;->initializeStorage(I)V
+Landroidx/collection/MutableIntIntMap;
+SPLandroidx/collection/MutableIntIntMap;->(I)V
+SPLandroidx/collection/MutableIntIntMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableIntIntMap;->adjustStorage$collection()V
+SPLandroidx/collection/MutableIntIntMap;->findFirstAvailableSlot(I)I
+HPLandroidx/collection/MutableIntIntMap;->findInsertIndex(I)I
+SPLandroidx/collection/MutableIntIntMap;->initializeGrowth()V
+SPLandroidx/collection/MutableIntIntMap;->initializeMetadata(I)V
+SPLandroidx/collection/MutableIntIntMap;->initializeStorage(I)V
+PLandroidx/collection/MutableIntIntMap;->put(II)V
+SPLandroidx/collection/MutableIntIntMap;->resizeStorage$collection(I)V
+HPLandroidx/collection/MutableIntIntMap;->set(II)V
+Landroidx/collection/MutableIntList;
+SPLandroidx/collection/MutableIntList;->(I)V
+SPLandroidx/collection/MutableIntList;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableIntList;->add(I)Z
+SPLandroidx/collection/MutableIntList;->add(II)V
+SPLandroidx/collection/MutableIntList;->addAll(I[I)Z
+PLandroidx/collection/MutableIntList;->clear()V
+SPLandroidx/collection/MutableIntList;->ensureCapacity(I)V
+SPLandroidx/collection/MutableIntList;->removeAt(I)I
+SPLandroidx/collection/MutableIntList;->removeRange(II)V
+SPLandroidx/collection/MutableIntList;->set(II)I
+SPLandroidx/collection/MutableIntList;->sort()V
+Landroidx/collection/MutableIntObjectMap;
+SPLandroidx/collection/MutableIntObjectMap;->(I)V
+SPLandroidx/collection/MutableIntObjectMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableIntObjectMap;->adjustStorage$collection()V
+PLandroidx/collection/MutableIntObjectMap;->dropDeletes$collection()V
+HSPLandroidx/collection/MutableIntObjectMap;->findAbsoluteInsertIndex(I)I
+SPLandroidx/collection/MutableIntObjectMap;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableIntObjectMap;->initializeGrowth()V
+SPLandroidx/collection/MutableIntObjectMap;->initializeMetadata(I)V
+SPLandroidx/collection/MutableIntObjectMap;->initializeStorage(I)V
+SPLandroidx/collection/MutableIntObjectMap;->remove(I)Ljava/lang/Object;
+SPLandroidx/collection/MutableIntObjectMap;->removeValueAt(I)Ljava/lang/Object;
+SPLandroidx/collection/MutableIntObjectMap;->resizeStorage$collection(I)V
+SPLandroidx/collection/MutableIntObjectMap;->set(ILjava/lang/Object;)V
+Landroidx/collection/MutableIntSet;
+SPLandroidx/collection/MutableIntSet;->(I)V
+SPLandroidx/collection/MutableIntSet;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableIntSet;->add(I)Z
+SPLandroidx/collection/MutableIntSet;->findAbsoluteInsertIndex(I)I
+SPLandroidx/collection/MutableIntSet;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableIntSet;->initializeGrowth()V
+SPLandroidx/collection/MutableIntSet;->initializeMetadata(I)V
+SPLandroidx/collection/MutableIntSet;->initializeStorage(I)V
+SPLandroidx/collection/MutableIntSet;->remove(I)Z
+SPLandroidx/collection/MutableIntSet;->removeElementAt(I)V
+Landroidx/collection/MutableLongList;
+SPLandroidx/collection/MutableLongList;->(I)V
+PLandroidx/collection/MutableLongList;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableLongList;->add(J)Z
+SPLandroidx/collection/MutableLongList;->clear()V
+SPLandroidx/collection/MutableLongList;->ensureCapacity(I)V
+Landroidx/collection/MutableLongObjectMap;
+SPLandroidx/collection/MutableLongObjectMap;->(I)V
+SPLandroidx/collection/MutableLongObjectMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableLongObjectMap;->clear()V
+SPLandroidx/collection/MutableLongObjectMap;->findAbsoluteInsertIndex(J)I
+SPLandroidx/collection/MutableLongObjectMap;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableLongObjectMap;->initializeGrowth()V
+SPLandroidx/collection/MutableLongObjectMap;->initializeMetadata(I)V
+SPLandroidx/collection/MutableLongObjectMap;->initializeStorage(I)V
+SPLandroidx/collection/MutableLongObjectMap;->set(JLjava/lang/Object;)V
+Landroidx/collection/MutableLongSet;
+SPLandroidx/collection/MutableLongSet;->(I)V
+PLandroidx/collection/MutableLongSet;->findAbsoluteInsertIndex(J)I
+PLandroidx/collection/MutableLongSet;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableLongSet;->initializeGrowth()V
+SPLandroidx/collection/MutableLongSet;->initializeMetadata(I)V
+SPLandroidx/collection/MutableLongSet;->initializeStorage(I)V
+PLandroidx/collection/MutableLongSet;->plusAssign(J)V
+PLandroidx/collection/MutableLongSet;->remove(J)Z
+PLandroidx/collection/MutableLongSet;->removeElementAt(I)V
+Landroidx/collection/MutableObjectFloatMap;
+SPLandroidx/collection/MutableObjectFloatMap;->(I)V
+SPLandroidx/collection/MutableObjectFloatMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableObjectFloatMap;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableObjectFloatMap;->findIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/MutableObjectFloatMap;->initializeGrowth()V
+SPLandroidx/collection/MutableObjectFloatMap;->initializeMetadata(I)V
+SPLandroidx/collection/MutableObjectFloatMap;->initializeStorage(I)V
+SPLandroidx/collection/MutableObjectFloatMap;->set(Ljava/lang/Object;F)V
+Landroidx/collection/MutableObjectIntMap;
+SPLandroidx/collection/MutableObjectIntMap;->(I)V
+SPLandroidx/collection/MutableObjectIntMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableObjectIntMap;->adjustStorage$collection()V
+SPLandroidx/collection/MutableObjectIntMap;->clear()V
+SPLandroidx/collection/MutableObjectIntMap;->findFirstAvailableSlot(I)I
+HSPLandroidx/collection/MutableObjectIntMap;->findIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/MutableObjectIntMap;->initializeGrowth()V
+SPLandroidx/collection/MutableObjectIntMap;->initializeMetadata(I)V
+SPLandroidx/collection/MutableObjectIntMap;->initializeStorage(I)V
+HSPLandroidx/collection/MutableObjectIntMap;->put(Ljava/lang/Object;II)I
+SPLandroidx/collection/MutableObjectIntMap;->removeValueAt(I)V
+SPLandroidx/collection/MutableObjectIntMap;->resizeStorage$collection(I)V
+SPLandroidx/collection/MutableObjectIntMap;->set(Ljava/lang/Object;I)V
+Landroidx/collection/MutableObjectList;
+SPLandroidx/collection/MutableObjectList;->(I)V
+SPLandroidx/collection/MutableObjectList;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableObjectList;->add(Ljava/lang/Object;)Z
+PLandroidx/collection/MutableObjectList;->addAll(Ljava/util/List;)Z
+SPLandroidx/collection/MutableObjectList;->clear()V
+PLandroidx/collection/MutableObjectList;->plusAssign(Ljava/util/List;)V
+SPLandroidx/collection/MutableObjectList;->remove(Ljava/lang/Object;)Z
+SPLandroidx/collection/MutableObjectList;->removeAt(I)Ljava/lang/Object;
+SPLandroidx/collection/MutableObjectList;->removeRange(II)V
+SPLandroidx/collection/MutableObjectList;->resizeStorage(I[Ljava/lang/Object;)V
+SPLandroidx/collection/MutableObjectList;->set(ILjava/lang/Object;)Ljava/lang/Object;
+Landroidx/collection/MutableOrderedScatterSet;
+SPLandroidx/collection/MutableOrderedScatterSet;->(I)V
+SPLandroidx/collection/MutableOrderedScatterSet;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableOrderedScatterSet;->add(Ljava/lang/Object;)Z
+PLandroidx/collection/MutableOrderedScatterSet;->adjustStorage$collection()V
+SPLandroidx/collection/MutableOrderedScatterSet;->clear()V
+SPLandroidx/collection/MutableOrderedScatterSet;->findAbsoluteInsertIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/MutableOrderedScatterSet;->findFirstAvailableSlot(I)I
+PLandroidx/collection/MutableOrderedScatterSet;->fixupNodes([I)V
+SPLandroidx/collection/MutableOrderedScatterSet;->initializeGrowth()V
+SPLandroidx/collection/MutableOrderedScatterSet;->initializeMetadata(I)V
+SPLandroidx/collection/MutableOrderedScatterSet;->initializeStorage(I)V
+PLandroidx/collection/MutableOrderedScatterSet;->remove(Ljava/lang/Object;)Z
+PLandroidx/collection/MutableOrderedScatterSet;->removeElementAt(I)V
+PLandroidx/collection/MutableOrderedScatterSet;->resizeStorage$collection(I)V
+Landroidx/collection/MutableScatterMap;
+HSPLandroidx/collection/MutableScatterMap;->(I)V
+SPLandroidx/collection/MutableScatterMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/MutableScatterMap;->adjustStorage$collection()V
+SPLandroidx/collection/MutableScatterMap;->clear()V
+PLandroidx/collection/MutableScatterMap;->dropDeletes$collection()V
+HSPLandroidx/collection/MutableScatterMap;->findFirstAvailableSlot(I)I
+HSPLandroidx/collection/MutableScatterMap;->findInsertIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/MutableScatterMap;->initializeGrowth()V
+HSPLandroidx/collection/MutableScatterMap;->initializeMetadata(I)V
+HSPLandroidx/collection/MutableScatterMap;->initializeStorage(I)V
+SPLandroidx/collection/MutableScatterMap;->putAll(Landroidx/collection/ScatterMap;)V
+SPLandroidx/collection/MutableScatterMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/collection/MutableScatterMap;->removeValueAt(I)Ljava/lang/Object;
+SPLandroidx/collection/MutableScatterMap;->resizeStorage$collection(I)V
+HSPLandroidx/collection/MutableScatterMap;->set(Ljava/lang/Object;Ljava/lang/Object;)V
+Landroidx/collection/MutableScatterSet;
+SPLandroidx/collection/MutableScatterSet;->(I)V
+SPLandroidx/collection/MutableScatterSet;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/collection/MutableScatterSet;->add(Ljava/lang/Object;)Z
+PLandroidx/collection/MutableScatterSet;->addAll(Landroidx/collection/ScatterSet;)Z
+SPLandroidx/collection/MutableScatterSet;->adjustStorage$collection()V
+SPLandroidx/collection/MutableScatterSet;->asMutableSet()Ljava/util/Set;
+HSPLandroidx/collection/MutableScatterSet;->clear()V
+PLandroidx/collection/MutableScatterSet;->dropDeletes$collection()V
+HSPLandroidx/collection/MutableScatterSet;->findAbsoluteInsertIndex(Ljava/lang/Object;)I
+HSPLandroidx/collection/MutableScatterSet;->findFirstAvailableSlot(I)I
+SPLandroidx/collection/MutableScatterSet;->initializeGrowth()V
+SPLandroidx/collection/MutableScatterSet;->initializeMetadata(I)V
+SPLandroidx/collection/MutableScatterSet;->initializeStorage(I)V
+SPLandroidx/collection/MutableScatterSet;->minusAssign(Ljava/lang/Object;)V
+SPLandroidx/collection/MutableScatterSet;->plusAssign(Landroidx/collection/ScatterSet;)V
+SPLandroidx/collection/MutableScatterSet;->plusAssign(Ljava/lang/Object;)V
+SPLandroidx/collection/MutableScatterSet;->remove(Ljava/lang/Object;)Z
+SPLandroidx/collection/MutableScatterSet;->removeElementAt(I)V
+SPLandroidx/collection/MutableScatterSet;->resizeStorage$collection(I)V
+Landroidx/collection/MutableSetWrapper;
+SPLandroidx/collection/MutableSetWrapper;->(Landroidx/collection/MutableScatterSet;)V
+SPLandroidx/collection/MutableSetWrapper;->add(Ljava/lang/Object;)Z
+SPLandroidx/collection/MutableSetWrapper;->remove(Ljava/lang/Object;)Z
+Landroidx/collection/ObjectFloatMap;
+SPLandroidx/collection/ObjectFloatMap;->()V
+SPLandroidx/collection/ObjectFloatMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ObjectFloatMap;->findKeyIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/ObjectFloatMap;->getCapacity()I
+Landroidx/collection/ObjectFloatMapKt;
+SPLandroidx/collection/ObjectFloatMapKt;->()V
+SPLandroidx/collection/ObjectFloatMapKt;->mutableObjectFloatMapOf()Landroidx/collection/MutableObjectFloatMap;
+Landroidx/collection/ObjectIntMap;
+SPLandroidx/collection/ObjectIntMap;->()V
+SPLandroidx/collection/ObjectIntMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ObjectIntMap;->equals(Ljava/lang/Object;)Z
+SPLandroidx/collection/ObjectIntMap;->findKeyIndex(Ljava/lang/Object;)I
+SPLandroidx/collection/ObjectIntMap;->getCapacity()I
+SPLandroidx/collection/ObjectIntMap;->getOrDefault(Ljava/lang/Object;I)I
+SPLandroidx/collection/ObjectIntMap;->getSize()I
+SPLandroidx/collection/ObjectIntMap;->isNotEmpty()Z
+Landroidx/collection/ObjectIntMapKt;
+SPLandroidx/collection/ObjectIntMapKt;->()V
+SPLandroidx/collection/ObjectIntMapKt;->emptyObjectIntMap()Landroidx/collection/ObjectIntMap;
+SPLandroidx/collection/ObjectIntMapKt;->mutableObjectIntMapOf()Landroidx/collection/MutableObjectIntMap;
+Landroidx/collection/ObjectList;
+SPLandroidx/collection/ObjectList;->(I)V
+SPLandroidx/collection/ObjectList;->(ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ObjectList;->contains(Ljava/lang/Object;)Z
+SPLandroidx/collection/ObjectList;->get(I)Ljava/lang/Object;
+SPLandroidx/collection/ObjectList;->getSize()I
+SPLandroidx/collection/ObjectList;->indexOf(Ljava/lang/Object;)I
+SPLandroidx/collection/ObjectList;->isEmpty()Z
+SPLandroidx/collection/ObjectList;->isNotEmpty()Z
+Landroidx/collection/ObjectListKt;
+SPLandroidx/collection/ObjectListKt;->()V
+PLandroidx/collection/ObjectListKt;->access$getEmptyArray$p()[Ljava/lang/Object;
+SPLandroidx/collection/ObjectListKt;->emptyObjectList()Landroidx/collection/ObjectList;
+PLandroidx/collection/ObjectListKt;->mutableObjectListOf(Ljava/lang/Object;Ljava/lang/Object;)Landroidx/collection/MutableObjectList;
+Landroidx/collection/OrderedScatterSet;
+SPLandroidx/collection/OrderedScatterSet;->()V
+SPLandroidx/collection/OrderedScatterSet;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/OrderedScatterSet;->contains(Ljava/lang/Object;)Z
+SPLandroidx/collection/OrderedScatterSet;->getCapacity()I
+SPLandroidx/collection/OrderedScatterSet;->getSize()I
+Landroidx/collection/OrderedScatterSetKt;
+SPLandroidx/collection/OrderedScatterSetKt;->()V
+SPLandroidx/collection/OrderedScatterSetKt;->mutableOrderedScatterSetOf()Landroidx/collection/MutableOrderedScatterSet;
+Landroidx/collection/ScatterMap;
+SPLandroidx/collection/ScatterMap;->()V
+SPLandroidx/collection/ScatterMap;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ScatterMap;->contains(Ljava/lang/Object;)Z
+SPLandroidx/collection/ScatterMap;->getCapacity()I
+SPLandroidx/collection/ScatterMap;->getSize()I
+SPLandroidx/collection/ScatterMap;->isEmpty()Z
+SPLandroidx/collection/ScatterMap;->isNotEmpty()Z
+Landroidx/collection/ScatterMapKt;
+SPLandroidx/collection/ScatterMapKt;->()V
+SPLandroidx/collection/ScatterMapKt;->loadedCapacity(I)I
+SPLandroidx/collection/ScatterMapKt;->mutableScatterMapOf()Landroidx/collection/MutableScatterMap;
+SPLandroidx/collection/ScatterMapKt;->nextCapacity(I)I
+SPLandroidx/collection/ScatterMapKt;->normalizeCapacity(I)I
+SPLandroidx/collection/ScatterMapKt;->unloadedCapacity(I)I
+Landroidx/collection/ScatterSet;
+SPLandroidx/collection/ScatterSet;->()V
+SPLandroidx/collection/ScatterSet;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/ScatterSet;->contains(Ljava/lang/Object;)Z
+SPLandroidx/collection/ScatterSet;->getCapacity()I
+SPLandroidx/collection/ScatterSet;->getSize()I
+SPLandroidx/collection/ScatterSet;->isEmpty()Z
+SPLandroidx/collection/ScatterSet;->isNotEmpty()Z
+Landroidx/collection/ScatterSetKt;
+SPLandroidx/collection/ScatterSetKt;->()V
+PLandroidx/collection/ScatterSetKt;->emptyScatterSet()Landroidx/collection/ScatterSet;
+SPLandroidx/collection/ScatterSetKt;->mutableScatterSetOf()Landroidx/collection/MutableScatterSet;
+Landroidx/collection/SetWrapper;
+SPLandroidx/collection/SetWrapper;->(Landroidx/collection/ScatterSet;)V
+SPLandroidx/collection/SetWrapper;->isEmpty()Z
+Landroidx/collection/SieveCacheKt;
+SPLandroidx/collection/SieveCacheKt;->()V
+SPLandroidx/collection/SieveCacheKt;->getEmptyNodes()[J
+Landroidx/collection/SimpleArrayMap;
+SPLandroidx/collection/SimpleArrayMap;->()V
+SPLandroidx/collection/SimpleArrayMap;->(I)V
+SPLandroidx/collection/SimpleArrayMap;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+Landroidx/collection/SparseArrayCompat;
+SPLandroidx/collection/SparseArrayCompat;->(I)V
+SPLandroidx/collection/SparseArrayCompat;->(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/collection/SparseArrayCompat;->get(I)Ljava/lang/Object;
+SPLandroidx/collection/SparseArrayCompat;->keyAt(I)I
+SPLandroidx/collection/SparseArrayCompat;->put(ILjava/lang/Object;)V
+SPLandroidx/collection/SparseArrayCompat;->size()I
+SPLandroidx/collection/SparseArrayCompat;->valueAt(I)Ljava/lang/Object;
+Landroidx/collection/SparseArrayCompatKt;
+SPLandroidx/collection/SparseArrayCompatKt;->()V
+SPLandroidx/collection/SparseArrayCompatKt;->commonGet(Landroidx/collection/SparseArrayCompat;I)Ljava/lang/Object;
+Landroidx/collection/SparseArrayKt;
+SPLandroidx/collection/SparseArrayKt;->keyIterator(Landroidx/collection/SparseArrayCompat;)Lkotlin/collections/IntIterator;
+SPLandroidx/collection/SparseArrayKt;->valueIterator(Landroidx/collection/SparseArrayCompat;)Ljava/util/Iterator;
+Landroidx/collection/SparseArrayKt$keyIterator$1;
+SPLandroidx/collection/SparseArrayKt$keyIterator$1;->(Landroidx/collection/SparseArrayCompat;)V
+SPLandroidx/collection/SparseArrayKt$keyIterator$1;->hasNext()Z
+Landroidx/collection/SparseArrayKt$valueIterator$1;
+SPLandroidx/collection/SparseArrayKt$valueIterator$1;->(Landroidx/collection/SparseArrayCompat;)V
+SPLandroidx/collection/SparseArrayKt$valueIterator$1;->hasNext()Z
+SPLandroidx/collection/SparseArrayKt$valueIterator$1;->next()Ljava/lang/Object;
+Landroidx/collection/internal/ContainerHelpersKt;
+SPLandroidx/collection/internal/ContainerHelpersKt;->()V
+SPLandroidx/collection/internal/ContainerHelpersKt;->binarySearch([III)I
+SPLandroidx/collection/internal/ContainerHelpersKt;->binarySearch([JIJ)I
+SPLandroidx/collection/internal/ContainerHelpersKt;->idealByteArraySize(I)I
+SPLandroidx/collection/internal/ContainerHelpersKt;->idealIntArraySize(I)I
+SPLandroidx/collection/internal/ContainerHelpersKt;->idealLongArraySize(I)I
+Landroidx/collection/internal/Lock;
+SPLandroidx/collection/internal/Lock;->()V
+Landroidx/collection/internal/LruHashMap;
+SPLandroidx/collection/internal/LruHashMap;->(IF)V
+SPLandroidx/collection/internal/LruHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/collection/internal/LruHashMap;->isEmpty()Z
+SPLandroidx/collection/internal/LruHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+PLandroidx/compose/animation/AndroidFlingSpline;->()V
+PLandroidx/compose/animation/AndroidFlingSpline;->()V
+PLandroidx/compose/animation/AndroidFlingSpline;->deceleration(FF)D
+PLandroidx/compose/animation/AndroidFlingSpline;->flingPosition(F)Landroidx/compose/animation/AndroidFlingSpline$FlingResult;
+PLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->()V
+PLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->(FF)V
+PLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->getDistanceCoefficient()F
+PLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->getVelocityCoefficient()F
+Landroidx/compose/animation/AnimatedContentKt;
+SPLandroidx/compose/animation/AnimatedContentKt;->()V
+SPLandroidx/compose/animation/AnimatedContentKt;->AnimatedContent(Landroidx/compose/animation/core/Transition;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Alignment;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V
+SPLandroidx/compose/animation/AnimatedContentKt;->access$getUnspecifiedSize$p()J
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1;->(Landroidx/compose/animation/core/Transition;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;Landroidx/compose/runtime/snapshots/SnapshotStateList;Lkotlin/jvm/functions/Function4;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1;->invoke(Landroidx/compose/runtime/Composer;I)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1;->(Landroidx/compose/animation/ContentTransform;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1;->invoke-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1$1;->(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/animation/ContentTransform;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$1$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$3$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$3$1;->(Ljava/lang/Object;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$3$1;->invoke(Ljava/lang/Object;)Ljava/lang/Boolean;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$3$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$4$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$4$1;->(Landroidx/compose/animation/ExitTransition;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$4$1;->invoke(Landroidx/compose/animation/EnterExitState;Landroidx/compose/animation/EnterExitState;)Ljava/lang/Boolean;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$4$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5;->(Landroidx/compose/runtime/snapshots/SnapshotStateList;Ljava/lang/Object;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;Lkotlin/jvm/functions/Function4;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5;->invoke(Landroidx/compose/animation/AnimatedVisibilityScope;Landroidx/compose/runtime/Composer;I)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1;->(Landroidx/compose/runtime/snapshots/SnapshotStateList;Ljava/lang/Object;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;)V
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1$invoke$$inlined$onDispose$1;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$6$1$5$1$1$invoke$$inlined$onDispose$1;->(Landroidx/compose/runtime/snapshots/SnapshotStateList;Ljava/lang/Object;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;)V
+Landroidx/compose/animation/AnimatedContentKt$AnimatedContent$9;
+SPLandroidx/compose/animation/AnimatedContentKt$AnimatedContent$9;->(Landroidx/compose/animation/core/Transition;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Alignment;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;II)V
+Landroidx/compose/animation/AnimatedContentMeasurePolicy;
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy;->(Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;)V
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy;->getRootScope()Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
+Landroidx/compose/animation/AnimatedContentMeasurePolicy$measure$3;
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy$measure$3;->([Landroidx/compose/ui/layout/Placeable;Landroidx/compose/animation/AnimatedContentMeasurePolicy;II)V
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy$measure$3;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
+SPLandroidx/compose/animation/AnimatedContentMeasurePolicy$measure$3;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedContentScope;
+Landroidx/compose/animation/AnimatedContentScopeImpl;
+SPLandroidx/compose/animation/AnimatedContentScopeImpl;->(Landroidx/compose/animation/AnimatedVisibilityScope;)V
+Landroidx/compose/animation/AnimatedContentTransitionScope;
+Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->()V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->(Landroidx/compose/animation/core/Transition;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/unit/LayoutDirection;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->createSizeAnimationModifier$animation(Landroidx/compose/animation/ContentTransform;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->createSizeAnimationModifier$lambda$1(Landroidx/compose/runtime/MutableState;)Z
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->createSizeAnimationModifier$lambda$2(Landroidx/compose/runtime/MutableState;Z)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->getContentAlignment()Landroidx/compose/ui/Alignment;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->getInitialState()Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->getTargetSizeMap$animation()Landroidx/collection/MutableScatterMap;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->getTargetState()Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->setContentAlignment(Landroidx/compose/ui/Alignment;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->setLayoutDirection$animation(Landroidx/compose/ui/unit/LayoutDirection;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl;->setMeasuredSize-ozmzZPI$animation(J)V
+Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;->()V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;->(Z)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;->isTarget()Z
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$ChildData;->setTarget(Z)V
+Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierElement;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierElement;->(Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/runtime/State;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierElement;->create()Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierElement;->create()Landroidx/compose/ui/Modifier$Node;
+Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;->(Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/runtime/State;Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;->getScope()Landroidx/compose/animation/AnimatedContentTransitionScopeImpl;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
+Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode$measure$1;
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode$measure$1;->(Landroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode;Landroidx/compose/ui/layout/Placeable;J)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
+SPLandroidx/compose/animation/AnimatedContentTransitionScopeImpl$SizeModifierNode$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedEnterExitMeasurePolicy;
+SPLandroidx/compose/animation/AnimatedEnterExitMeasurePolicy;->(Landroidx/compose/animation/AnimatedVisibilityScopeImpl;)V
+SPLandroidx/compose/animation/AnimatedEnterExitMeasurePolicy;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
+Landroidx/compose/animation/AnimatedEnterExitMeasurePolicy$measure$1;
+SPLandroidx/compose/animation/AnimatedEnterExitMeasurePolicy$measure$1;->(Ljava/util/List;)V
+SPLandroidx/compose/animation/AnimatedEnterExitMeasurePolicy$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
+SPLandroidx/compose/animation/AnimatedEnterExitMeasurePolicy$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedVisibilityKt;
+SPLandroidx/compose/animation/AnimatedVisibilityKt;->AnimatedEnterExitImpl(Landroidx/compose/animation/core/Transition;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Lkotlin/jvm/functions/Function2;Landroidx/compose/animation/OnLookaheadMeasured;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
+SPLandroidx/compose/animation/AnimatedVisibilityKt;->access$getExitFinished(Landroidx/compose/animation/core/Transition;)Z
+SPLandroidx/compose/animation/AnimatedVisibilityKt;->getExitFinished(Landroidx/compose/animation/core/Transition;)Z
+SPLandroidx/compose/animation/AnimatedVisibilityKt;->targetEnterExit(Landroidx/compose/animation/core/Transition;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Landroidx/compose/animation/EnterExitState;
+Landroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$4;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$4;->(Landroidx/compose/animation/core/Transition;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Lkotlin/jvm/functions/Function2;Landroidx/compose/animation/OnLookaheadMeasured;Lkotlin/jvm/functions/Function3;II)V
+Landroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;->(Landroidx/compose/animation/core/Transition;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;->invoke(Landroidx/compose/runtime/ProduceStateScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$1;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$1;->(Landroidx/compose/animation/core/Transition;)V
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$1;->invoke()Ljava/lang/Boolean;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$1;->invoke()Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$2;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$2;->(Landroidx/compose/runtime/ProduceStateScope;Landroidx/compose/animation/core/Transition;Landroidx/compose/runtime/State;)V
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+SPLandroidx/compose/animation/AnimatedVisibilityKt$AnimatedEnterExitImpl$shouldDisposeAfterExit$2$1$2;->emit(ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
+Landroidx/compose/animation/AnimatedVisibilityScope;
+Landroidx/compose/animation/AnimatedVisibilityScopeImpl;
+SPLandroidx/compose/animation/AnimatedVisibilityScopeImpl;->()V
+SPLandroidx/compose/animation/AnimatedVisibilityScopeImpl;->(Landroidx/compose/animation/core/Transition;)V
+SPLandroidx/compose/animation/AnimatedVisibilityScopeImpl;->getTargetSize$animation()Landroidx/compose/runtime/MutableState;
+Landroidx/compose/animation/AnimationModifierKt;
+SPLandroidx/compose/animation/AnimationModifierKt;->()V
+SPLandroidx/compose/animation/AnimationModifierKt;->getInvalidSize()J
+SPLandroidx/compose/animation/AnimationModifierKt;->isValid-ozmzZPI(J)Z
+Landroidx/compose/animation/ColorVectorConverterKt;
+SPLandroidx/compose/animation/ColorVectorConverterKt;->()V
+SPLandroidx/compose/animation/ColorVectorConverterKt;->getVectorConverter(Landroidx/compose/ui/graphics/Color$Companion;)Lkotlin/jvm/functions/Function1;
+Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->()V
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->()V
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->invoke(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroidx/compose/animation/core/TwoWayConverter;
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->()V
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->()V
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->invoke-8_81llA(J)Landroidx/compose/animation/core/AnimationVector4D;
+Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$2;
+SPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$2;->(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)V
+Landroidx/compose/animation/ContentTransform;
+SPLandroidx/compose/animation/ContentTransform;->()V
+SPLandroidx/compose/animation/ContentTransform;->(Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;FLandroidx/compose/animation/SizeTransform;)V
+SPLandroidx/compose/animation/ContentTransform;->getSizeTransform()Landroidx/compose/animation/SizeTransform;
+SPLandroidx/compose/animation/ContentTransform;->getTargetContentEnter()Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/ContentTransform;->getTargetContentZIndex()F
+Landroidx/compose/animation/EnterExitState;
+SPLandroidx/compose/animation/EnterExitState;->$values()[Landroidx/compose/animation/EnterExitState;
+SPLandroidx/compose/animation/EnterExitState;->()V
+SPLandroidx/compose/animation/EnterExitState;->(Ljava/lang/String;I)V
+Landroidx/compose/animation/EnterExitTransitionElement;
+SPLandroidx/compose/animation/EnterExitTransitionElement;->(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Lkotlin/jvm/functions/Function0;Landroidx/compose/animation/GraphicsLayerBlockForEnterExit;)V
+SPLandroidx/compose/animation/EnterExitTransitionElement;->create()Landroidx/compose/animation/EnterExitTransitionModifierNode;
+SPLandroidx/compose/animation/EnterExitTransitionElement;->create()Landroidx/compose/ui/Modifier$Node;
+Landroidx/compose/animation/EnterExitTransitionKt;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->$r8$lambda$IsnwG04bc30lhOT0dz7f2KRJk-w(Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Landroidx/compose/animation/core/Transition$DeferredAnimation;)Lkotlin/jvm/functions/Function1;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->()V
+SPLandroidx/compose/animation/EnterExitTransitionKt;->createGraphicsLayerBlock$lambda$2$0(Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Landroidx/compose/animation/core/Transition$DeferredAnimation;)Lkotlin/jvm/functions/Function1;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->createGraphicsLayerBlock(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Ljava/lang/String;Landroidx/compose/runtime/Composer;I)Landroidx/compose/animation/GraphicsLayerBlockForEnterExit;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->createModifier(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;ZLkotlin/jvm/functions/Function0;Ljava/lang/String;Landroidx/compose/runtime/Composer;II)Landroidx/compose/ui/Modifier;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->fadeIn$default(Landroidx/compose/animation/core/FiniteAnimationSpec;FILjava/lang/Object;)Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->fadeIn(Landroidx/compose/animation/core/FiniteAnimationSpec;F)Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->fadeOut$default(Landroidx/compose/animation/core/FiniteAnimationSpec;FILjava/lang/Object;)Landroidx/compose/animation/ExitTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->fadeOut(Landroidx/compose/animation/core/FiniteAnimationSpec;F)Landroidx/compose/animation/ExitTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveEnter$lambda$1(Landroidx/compose/runtime/MutableState;)Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveEnter$lambda$2(Landroidx/compose/runtime/MutableState;Landroidx/compose/animation/EnterTransition;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveEnter(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/runtime/Composer;I)Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveExit$lambda$1(Landroidx/compose/runtime/MutableState;)Landroidx/compose/animation/ExitTransition;
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveExit$lambda$2(Landroidx/compose/runtime/MutableState;Landroidx/compose/animation/ExitTransition;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt;->trackActiveExit(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/ExitTransition;Landroidx/compose/runtime/Composer;I)Landroidx/compose/animation/ExitTransition;
+Landroidx/compose/animation/EnterExitTransitionKt$$ExternalSyntheticLambda0;
+SPLandroidx/compose/animation/EnterExitTransitionKt$$ExternalSyntheticLambda0;->(Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Landroidx/compose/animation/core/Transition$DeferredAnimation;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt$$ExternalSyntheticLambda0;->init()Lkotlin/jvm/functions/Function1;
+Landroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$1;
+SPLandroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$1;->()V
+SPLandroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$1;->()V
+Landroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$2;
+SPLandroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$2;->()V
+SPLandroidx/compose/animation/EnterExitTransitionKt$TransformOriginVectorConverter$2;->()V
+Landroidx/compose/animation/EnterExitTransitionKt$createGraphicsLayerBlock$1$1$block$1;
+SPLandroidx/compose/animation/EnterExitTransitionKt$createGraphicsLayerBlock$1$1$block$1;->(Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createGraphicsLayerBlock$1$1$block$1;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createGraphicsLayerBlock$1$1$block$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/EnterExitTransitionKt$createModifier$1$1;
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$1$1;->()V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$1$1;->()V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$1$1;->invoke()Ljava/lang/Boolean;
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$1$1;->invoke()Ljava/lang/Object;
+Landroidx/compose/animation/EnterExitTransitionKt$createModifier$2$1;
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$2$1;->(ZLkotlin/jvm/functions/Function0;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$2$1;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
+SPLandroidx/compose/animation/EnterExitTransitionKt$createModifier$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/EnterExitTransitionModifierNode;
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode;->(Landroidx/compose/animation/core/Transition;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/core/Transition$DeferredAnimation;Landroidx/compose/animation/EnterTransition;Landroidx/compose/animation/ExitTransition;Lkotlin/jvm/functions/Function0;Landroidx/compose/animation/GraphicsLayerBlockForEnterExit;)V
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode;->onAttach()V
+Landroidx/compose/animation/EnterExitTransitionModifierNode$measure$2;
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode$measure$2;->(Landroidx/compose/ui/layout/Placeable;JJLkotlin/jvm/functions/Function1;)V
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode$measure$2;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode$measure$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+Landroidx/compose/animation/EnterExitTransitionModifierNode$sizeTransitionSpec$1;
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode$sizeTransitionSpec$1;->(Landroidx/compose/animation/EnterExitTransitionModifierNode;)V
+Landroidx/compose/animation/EnterExitTransitionModifierNode$slideSpec$1;
+SPLandroidx/compose/animation/EnterExitTransitionModifierNode$slideSpec$1;->(Landroidx/compose/animation/EnterExitTransitionModifierNode;)V
+Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterTransition;->()V
+SPLandroidx/compose/animation/EnterTransition;->()V
+SPLandroidx/compose/animation/EnterTransition;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/compose/animation/EnterTransition;->access$getNone$cp()Landroidx/compose/animation/EnterTransition;
+SPLandroidx/compose/animation/EnterTransition;->equals(Ljava/lang/Object;)Z
+Landroidx/compose/animation/EnterTransition$Companion;
+SPLandroidx/compose/animation/EnterTransition$Companion;->()V
+SPLandroidx/compose/animation/EnterTransition$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/compose/animation/EnterTransition$Companion;->getNone()Landroidx/compose/animation/EnterTransition;
+Landroidx/compose/animation/EnterTransitionImpl;
+SPLandroidx/compose/animation/EnterTransitionImpl;->(Landroidx/compose/animation/TransitionData;)V
+SPLandroidx/compose/animation/EnterTransitionImpl;->getData$animation()Landroidx/compose/animation/TransitionData;
+Landroidx/compose/animation/ExitTransition;
+SPLandroidx/compose/animation/ExitTransition;->()V
+SPLandroidx/compose/animation/ExitTransition;->()V
+SPLandroidx/compose/animation/ExitTransition;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/compose/animation/ExitTransition;->access$getNone$cp()Landroidx/compose/animation/ExitTransition;
+SPLandroidx/compose/animation/ExitTransition;->equals(Ljava/lang/Object;)Z
+Landroidx/compose/animation/ExitTransition$Companion;
+SPLandroidx/compose/animation/ExitTransition$Companion;->()V
+SPLandroidx/compose/animation/ExitTransition$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+SPLandroidx/compose/animation/ExitTransition$Companion;->getNone()Landroidx/compose/animation/ExitTransition;
+Landroidx/compose/animation/ExitTransitionImpl;
+SPLandroidx/compose/animation/ExitTransitionImpl;->(Landroidx/compose/animation/TransitionData;)V
+SPLandroidx/compose/animation/ExitTransitionImpl;->getData$animation()Landroidx/compose/animation/TransitionData;
+Landroidx/compose/animation/Fade;
+SPLandroidx/compose/animation/Fade;->()V
+SPLandroidx/compose/animation/Fade;->(FLandroidx/compose/animation/core/FiniteAnimationSpec;)V
+Landroidx/compose/animation/FlingCalculator;
+SPLandroidx/compose/animation/FlingCalculator;->()V
+SPLandroidx/compose/animation/FlingCalculator;->(FLandroidx/compose/ui/unit/Density;)V
+SPLandroidx/compose/animation/FlingCalculator;->computeDeceleration(Landroidx/compose/ui/unit/Density;)F
+PLandroidx/compose/animation/FlingCalculator;->flingDistance(F)F
+PLandroidx/compose/animation/FlingCalculator;->flingDuration(F)J
+PLandroidx/compose/animation/FlingCalculator;->flingInfo(F)Landroidx/compose/animation/FlingCalculator$FlingInfo;
+PLandroidx/compose/animation/FlingCalculator;->getSplineDeceleration(F)D
+PLandroidx/compose/animation/FlingCalculator$FlingInfo;->()V
+PLandroidx/compose/animation/FlingCalculator$FlingInfo;->(FFJ)V
+PLandroidx/compose/animation/FlingCalculator$FlingInfo;->position(J)F
+PLandroidx/compose/animation/FlingCalculator$FlingInfo;->velocity(J)F
+Landroidx/compose/animation/FlingCalculatorKt;
+SPLandroidx/compose/animation/FlingCalculatorKt;->