mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-08-08 06:46:11 +00:00
build: enable reproducible Android releases
This commit is contained in:
parent
96340a35aa
commit
3f8b596361
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@ -0,0 +1,6 @@
|
||||
.git
|
||||
.gradle
|
||||
.reproducible-build
|
||||
**/build
|
||||
local.properties
|
||||
tools/arti-build/.arti-source
|
||||
184
.github/workflows/android-build.yml
vendored
184
.github/workflows/android-build.yml
vendored
@ -3,102 +3,140 @@ name: Android CI
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "main", "develop" ]
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [ "main", "develop" ]
|
||||
branches: [main, develop]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 21.0.11+10
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Test & Lint
|
||||
runs-on: ubuntu-latest
|
||||
name: Test and lint
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Set up pinned JDK
|
||||
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v3
|
||||
- name: Set up and validate Gradle
|
||||
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Verify native library inputs
|
||||
run: tools/arti-build/verify-checksums.sh
|
||||
|
||||
- name: Cache Gradle packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Run unit tests
|
||||
run: ./gradlew testDebugUnitTest
|
||||
|
||||
- name: Run unit tests
|
||||
run: ./gradlew testDebugUnitTest
|
||||
- name: Run lint
|
||||
run: ./gradlew lintDebug
|
||||
|
||||
- name: Run lint
|
||||
run: ./gradlew lintDebug
|
||||
- name: Upload test reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: test-reports
|
||||
path: |
|
||||
**/build/test-results/
|
||||
**/build/reports/tests/
|
||||
|
||||
- name: Upload test reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-reports
|
||||
path: |
|
||||
**/build/test-results/
|
||||
**/build/reports/tests/
|
||||
- name: Upload lint results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: lint-results
|
||||
path: "**/build/reports/lint-results-*.html"
|
||||
|
||||
- name: Upload lint results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: lint-results
|
||||
path: '**/build/reports/lint-results-*.html'
|
||||
build-debug:
|
||||
name: Build debug APK
|
||||
runs-on: ubuntu-24.04
|
||||
needs: verify
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.variant }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Set up pinned JDK
|
||||
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
|
||||
- name: Set up and validate Gradle
|
||||
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
|
||||
|
||||
- name: Build debug APK
|
||||
run: ./gradlew assembleDebug
|
||||
|
||||
- name: Upload debug APK
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: Debug-apk
|
||||
path: app/build/outputs/apk/debug/*.apk
|
||||
|
||||
reproducible-build:
|
||||
name: Reproducible release build ${{ matrix.replica }}
|
||||
runs-on: ubuntu-24.04
|
||||
needs: verify
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
variant: [Debug, Release]
|
||||
replica: [a, b]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Set up pinned JDK
|
||||
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v3
|
||||
- name: Set up and validate Gradle
|
||||
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
|
||||
with:
|
||||
cache-disabled: true
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build canonical unsigned release
|
||||
run: tools/reproducible-builds/build-in-container.sh "$RUNNER_TEMP/release-${{ matrix.replica }}"
|
||||
|
||||
- name: Cache Gradle packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Upload build replica
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: reproducible-release-${{ matrix.replica }}
|
||||
path: ${{ runner.temp }}/release-${{ matrix.replica }}/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build ${{ matrix.variant }} APK
|
||||
run: ./gradlew assemble${{ matrix.variant }}
|
||||
compare-reproducible-builds:
|
||||
name: Compare release bytes
|
||||
runs-on: ubuntu-24.04
|
||||
needs: reproducible-build
|
||||
|
||||
- name: Upload ${{ matrix.variant }} APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.variant }}-apk
|
||||
path: app/build/outputs/apk/**/*.apk
|
||||
steps:
|
||||
- name: Checkout verification script
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Download replica A
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: reproducible-release-a
|
||||
path: ${{ runner.temp }}/release-a
|
||||
|
||||
- name: Download replica B
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: reproducible-release-b
|
||||
path: ${{ runner.temp }}/release-b
|
||||
|
||||
- name: Compare every canonical byte
|
||||
run: tools/reproducible-builds/compare-release.sh "$RUNNER_TEMP/release-a" "$RUNNER_TEMP/release-b"
|
||||
|
||||
6
.github/workflows/fetch-georelays.yml
vendored
6
.github/workflows/fetch-georelays.yml
vendored
@ -10,11 +10,11 @@ permissions:
|
||||
|
||||
jobs:
|
||||
update-relay-data:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@ -37,4 +37,4 @@ jobs:
|
||||
git commit -m "Automated update of relay data - $(date -u)"
|
||||
git push
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
212
.github/workflows/release.yml
vendored
212
.github/workflows/release.yml
vendored
@ -2,106 +2,152 @@ name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Existing vX.Y.Z tag to build and publish
|
||||
required: true
|
||||
type: string
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*' # Triggers for tags like v1.0.0
|
||||
- "v*.*.*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 21.0.11+10
|
||||
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build unsigned release ${{ matrix.replica }}
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
replica: [a, b]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
|
||||
- name: Cache Gradle files
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
gradle-${{ runner.os }}-
|
||||
|
||||
- name: Grant execute permission for Gradlew
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Build Release APKs (with architecture splits)
|
||||
run: ./gradlew assembleRelease --no-daemon --stacktrace
|
||||
|
||||
- name: List APK files
|
||||
- name: Validate release tag
|
||||
run: |
|
||||
echo "APK files built:"
|
||||
find app/build/outputs/apk/release -name "*.apk" -type f -exec ls -lh {} \;
|
||||
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "error: release tag must look like vX.Y.Z" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Rename APKs for GitHub Release
|
||||
run: |
|
||||
cd app/build/outputs/apk/release
|
||||
[ -f "app-arm64-v8a-release-unsigned.apk" ] && mv app-arm64-v8a-release-unsigned.apk bitchat-android-arm64.apk
|
||||
[ -f "app-x86_64-release-unsigned.apk" ] && mv app-x86_64-release-unsigned.apk bitchat-android-x86_64.apk
|
||||
[ -f "app-universal-release-unsigned.apk" ] && mv app-universal-release-unsigned.apk bitchat-android-universal.apk
|
||||
|
||||
- name: DEBUG
|
||||
run: |
|
||||
set -x
|
||||
pwd
|
||||
ls -all
|
||||
cd app/build/outputs/
|
||||
ls -all
|
||||
tree || ls -R
|
||||
|
||||
# Optional: Sign APKs (uncomment and configure secrets when ready)
|
||||
# - name: Sign APKs
|
||||
# uses: r0adkll/sign-android-release@v1
|
||||
# with:
|
||||
# releaseDirectory: app/build/outputs/apk/release
|
||||
# signingKeyBase64: ${{ secrets.SIGNING_KEY }}
|
||||
# alias: ${{ secrets.ALIAS }}
|
||||
# keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
# keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
|
||||
- name: Upload APKs as artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Checkout tagged source
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
name: bitchat-android-release-${{ github.ref_name }}
|
||||
path: app/build/outputs/apk/release/*.apk
|
||||
ref: ${{ env.RELEASE_TAG }}
|
||||
|
||||
- name: Validate the Gradle wrapper
|
||||
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
|
||||
with:
|
||||
cache-disabled: true
|
||||
|
||||
- name: Build canonical unsigned APKs and AAB
|
||||
run: tools/reproducible-builds/build-in-container.sh "$RUNNER_TEMP/release-${{ matrix.replica }}"
|
||||
|
||||
- name: Upload unsigned replica
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: unsigned-release-${{ matrix.replica }}
|
||||
path: ${{ runner.temp }}/release-${{ matrix.replica }}/*
|
||||
retention-days: 30
|
||||
if-no-files-found: error
|
||||
|
||||
release:
|
||||
compare:
|
||||
name: Verify reproducibility
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download release artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Checkout verification script
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
name: bitchat-android-release-${{ github.ref_name }}
|
||||
ref: ${{ env.RELEASE_TAG }}
|
||||
|
||||
- name: Download replica A
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: unsigned-release-a
|
||||
path: ${{ runner.temp }}/release-a
|
||||
|
||||
- name: Download replica B
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: unsigned-release-b
|
||||
path: ${{ runner.temp }}/release-b
|
||||
|
||||
- name: Compare every canonical byte
|
||||
run: tools/reproducible-builds/compare-release.sh "$RUNNER_TEMP/release-a" "$RUNNER_TEMP/release-b"
|
||||
|
||||
- name: Upload verified unsigned release
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: verified-unsigned-release
|
||||
path: ${{ runner.temp }}/release-a/*
|
||||
retention-days: 30
|
||||
if-no-files-found: error
|
||||
|
||||
sign-and-release:
|
||||
name: Sign, attest, and publish
|
||||
runs-on: ubuntu-24.04
|
||||
needs: compare
|
||||
permissions:
|
||||
attestations: write
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout tagged source
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
ref: ${{ env.RELEASE_TAG }}
|
||||
|
||||
- name: Set up pinned JDK
|
||||
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
|
||||
- name: Download verified unsigned release
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: verified-unsigned-release
|
||||
path: release
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
release/bitchat-android-arm64.apk
|
||||
release/bitchat-android-x86_64.apk
|
||||
release/bitchat-android-universal.apk
|
||||
name: Release ${{ github.ref_name }}
|
||||
body: |
|
||||
**bitchat-android-arm64.apk** - ARM64 (most phones)
|
||||
**bitchat-android-x86_64.apk** - x86_64 (Chromebooks, tablets)
|
||||
**bitchat-android-universal.apk** - All architectures (fallback)
|
||||
- name: Install checksum-verified Android Build Tools
|
||||
run: tools/reproducible-builds/install-android-build-tools.sh "$RUNNER_TEMP/android-sdk"
|
||||
|
||||
- name: Deterministically sign verified GitHub APKs
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ANDROID_SDK_ROOT: ${{ runner.temp }}/android-sdk
|
||||
BITCHAT_SIGNING_KEY_BASE64: ${{ secrets.SIGNING_KEY }}
|
||||
BITCHAT_SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
|
||||
BITCHAT_KEYSTORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
BITCHAT_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
run: tools/reproducible-builds/sign-release.sh release
|
||||
|
||||
- name: Prepare public manifest names
|
||||
run: |
|
||||
mv release/BUILDINFO.json release/BITCHAT_BUILDINFO.json
|
||||
mv release/SHA256SUMS.unsigned release/BITCHAT_SHA256SUMS.unsigned
|
||||
sed \
|
||||
-e 's/ BUILDINFO.json$/ BITCHAT_BUILDINFO.json/' \
|
||||
-e 's/ SHA256SUMS.unsigned$/ BITCHAT_SHA256SUMS.unsigned/' \
|
||||
release/SHA256SUMS > release/BITCHAT_SHA256SUMS
|
||||
rm release/SHA256SUMS
|
||||
|
||||
- name: Attest release provenance
|
||||
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
|
||||
with:
|
||||
subject-path: release/*
|
||||
|
||||
- name: Publish GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh release create "$RELEASE_TAG" release/* \
|
||||
--title "Release $RELEASE_TAG" \
|
||||
--notes "Signed installable APKs, canonical unsigned APK/AAB inputs, checksums, and GitHub build-provenance attestations are attached. See docs/reproducible-builds.md for verification instructions."
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -57,6 +57,7 @@ gen/
|
||||
*~
|
||||
*.swp
|
||||
*.lock
|
||||
!tools/arti-build/Cargo.lock
|
||||
.goosehints
|
||||
|
||||
# Google services
|
||||
@ -69,6 +70,7 @@ google-services.json
|
||||
# Arti build artifacts (cloned repo and Rust build cache)
|
||||
tools/arti-build/.arti-source/
|
||||
tools/arti-build/target/
|
||||
.reproducible-build/
|
||||
|
||||
# JVM heap dumps (a Gradle daemon OOM drops these in the repo root)
|
||||
*.hprof
|
||||
|
||||
1
.java-version
Normal file
1
.java-version
Normal file
@ -0,0 +1 @@
|
||||
21.0.11
|
||||
@ -70,6 +70,10 @@ adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||||
|
||||
The app requests Bluetooth, location (required for BLE scanning), and notification permissions at runtime.
|
||||
|
||||
Release APKs and the Android App Bundle can be rebuilt byte-for-byte in the
|
||||
pinned Linux container. See [Reproducible builds](docs/reproducible-builds.md)
|
||||
for the build, GitHub release, and Google Play verification procedures.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import org.gradle.api.artifacts.dsl.LockMode
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
@ -24,6 +25,7 @@ require(
|
||||
android {
|
||||
namespace = "com.bitchat.android"
|
||||
compileSdk = libs.versions.compileSdk.get().toInt()
|
||||
buildToolsVersion = libs.versions.buildTools.get()
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.bitchat.droid"
|
||||
@ -64,6 +66,11 @@ android {
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
vcsInfo {
|
||||
// BUILDINFO.json and attestations carry the verified commit
|
||||
// without depending on host-specific Git/worktree paths.
|
||||
include = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,11 +113,17 @@ android {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_11)
|
||||
}
|
||||
}
|
||||
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
lockMode.set(LockMode.STRICT)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Core Android dependencies
|
||||
implementation(libs.androidx.core.ktx)
|
||||
|
||||
463
app/gradle.lockfile
Normal file
463
app/gradle.lockfile
Normal file
@ -0,0 +1,463 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
# To regenerate this file, run: ./gradlew :app:dependencies --write-locks
|
||||
androidx.activity:activity-compose:1.13.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.activity:activity-ktx:1.13.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.activity:activity:1.13.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.annotation:annotation-experimental:1.4.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.annotation:annotation-jvm:1.10.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.annotation:annotation:1.10.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.appcompat:appcompat-resources:1.7.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.appcompat:appcompat:1.7.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.arch.core:core-common:2.2.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.arch.core:core-runtime:2.2.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.autofill:autofill:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera.featurecombinationquery:featurecombinationquery:1.6.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera.viewfinder:viewfinder-compose:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera.viewfinder:viewfinder-core:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera:camera-camera2-pipe:1.6.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera:camera-camera2:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera:camera-compose:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera:camera-core:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.camera:camera-lifecycle:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.collection:collection-jvm:1.5.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.collection:collection-ktx:1.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.collection:collection:1.5.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.animation:animation-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.animation:animation-core-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.animation:animation-core:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.animation:animation:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.foundation:foundation-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.foundation:foundation-layout-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.foundation:foundation-layout:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.foundation:foundation:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material3:material3-android:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material3:material3:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-icons-core-android:1.7.8=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-icons-core-desktop:1.7.8=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugUnitTestLintChecksClasspath,releaseLintChecksClasspath
|
||||
androidx.compose.material:material-icons-core:1.7.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-icons-extended-android:1.7.8=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-icons-extended-desktop:1.7.8=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugUnitTestLintChecksClasspath,releaseLintChecksClasspath
|
||||
androidx.compose.material:material-icons-extended:1.7.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-ripple-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.material:material-ripple:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-annotation-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-annotation:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-retain-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-retain:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-saveable-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime-saveable:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.runtime:runtime:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-geometry-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-geometry:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-graphics-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-graphics:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-test-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-test-junit4-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-test-junit4:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-test-manifest:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-test:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-text-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-text:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling-data-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling-data:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling-preview-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling-preview:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-tooling:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.compose.ui:ui-unit-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-unit:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-util-android:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui-util:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose.ui:ui:1.11.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.compose:compose-bom:2026.06.01=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.concurrent:concurrent-futures-ktx:1.1.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.concurrent:concurrent-futures-ktx:1.2.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.concurrent:concurrent-futures:1.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.concurrent:concurrent-futures:1.2.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.core:core-backported-fixes:1.0.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.core:core-ktx:1.19.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.core:core-viewtree:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.core:core:1.19.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.cursoradapter:cursoradapter:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.customview:customview-poolingcontainer:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.customview:customview:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.documentfile:documentfile:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.drawerlayout:drawerlayout:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.dynamicanimation:dynamicanimation:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.emoji2:emoji2-views-helper:1.4.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.emoji2:emoji2:1.4.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.exifinterface:exifinterface:1.4.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.fragment:fragment:1.5.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.graphics:graphics-path:1.0.1=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.interpolator:interpolator:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.legacy:legacy-support-core-utils:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-common-java8:2.11.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-common-jvm:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-common:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-livedata-core-ktx:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-livedata-core:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-livedata:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-process:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime-compose-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime-compose:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime-ktx-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime-ktx:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-runtime:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-service:2.11.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-compose-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-compose:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.lifecycle:lifecycle-viewmodel:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.loader:loader:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-common-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-common:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-compose-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-compose:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-runtime-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigation:navigation-runtime:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigationevent:navigationevent-android:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigationevent:navigationevent-compose-android:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigationevent:navigationevent-compose:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.navigationevent:navigationevent:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.print:print:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.profileinstaller:profileinstaller:1.4.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.resourceinspection:resourceinspection-annotation:1.0.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.room:room-common:2.6.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.room:room-ktx:2.6.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.room:room-runtime:2.6.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.savedstate:savedstate-android:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.savedstate:savedstate-compose-android:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.savedstate:savedstate-compose:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.savedstate:savedstate-ktx:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.savedstate:savedstate:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.security:security-crypto:1.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.sqlite:sqlite-framework:2.4.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.sqlite:sqlite:2.4.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.startup:startup-runtime:1.1.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugUnitTestCompileClasspath,releaseCompileClasspath
|
||||
androidx.startup:startup-runtime:1.2.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.test.espresso:espresso-core:3.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test.espresso:espresso-core:3.7.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test.espresso:espresso-idling-resource:3.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test.espresso:espresso-idling-resource:3.7.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test.ext:junit:1.1.5=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test.ext:junit:1.3.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test.services:storage:1.4.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test.services:storage:1.6.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test:annotation:1.0.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test:core:1.5.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test:core:1.7.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test:monitor:1.6.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test:monitor:1.8.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.test:runner:1.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
androidx.test:runner:1.7.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
androidx.tracing:tracing-android:1.3.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.tracing:tracing-ktx:1.3.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.tracing:tracing:1.0.0=debugAndroidTestCompileClasspath
|
||||
androidx.tracing:tracing:1.1.0=debugUnitTestCompileClasspath
|
||||
androidx.tracing:tracing:1.3.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.transition:transition:1.6.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.vectordrawable:vectordrawable-animated:1.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.vectordrawable:vectordrawable:1.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.viewpager:viewpager:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.window:window-core-android:1.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.window:window-core:1.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.window:window:1.5.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.work:work-runtime-ktx:2.10.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
androidx.work:work-runtime:2.10.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.almworks.sqlite4java:sqlite4java:1.0.392=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.android.tools.analytics-library:protos:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools.analytics-library:shared:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools.analytics-library:tracker:32.3.1=androidLintTool
|
||||
com.android.tools.build:aapt2-proto:9.3.1-15703166=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools.build:builder-model:9.3.1=androidLintTool
|
||||
com.android.tools.build:manifest-merger:32.3.1=androidLintTool
|
||||
com.android.tools.ddms:ddmlib:32.3.1=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.android.tools.emulator:proto:32.3.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
com.android.tools.external.com-intellij:intellij-core:32.3.1=androidLintTool
|
||||
com.android.tools.external.com-intellij:kotlin-compiler:32.3.1=androidLintTool
|
||||
com.android.tools.external.org-jetbrains:uast:32.3.1=androidLintTool
|
||||
com.android.tools.layoutlib:layoutlib-api:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools.lint:lint-api:32.3.1=androidLintTool
|
||||
com.android.tools.lint:lint-checks:32.3.1=androidLintTool
|
||||
com.android.tools.lint:lint-gradle:32.3.1=androidLintTool
|
||||
com.android.tools.lint:lint-model:32.3.1=androidLintTool
|
||||
com.android.tools.lint:lint-typedef-remover:32.3.1=androidLintTool
|
||||
com.android.tools.lint:lint:32.3.1=androidLintTool
|
||||
com.android.tools.utp:android-device-provider-ddmlib-proto:32.3.1=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-device-provider-ddmlib:32.3.1=unified-test-platform-android-device-provider-ddmlib
|
||||
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:32.3.1=unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-host-additional-test-output:32.3.1=unified-test-platform-android-test-plugin-host-additional-test-output
|
||||
com.android.tools.utp:android-test-plugin-host-apk-installer-proto:32.3.1=unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-host-apk-installer:32.3.1=unified-test-platform-android-test-plugin-host-apk-installer
|
||||
com.android.tools.utp:android-test-plugin-host-coverage-proto:32.3.1=unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-host-coverage:32.3.1=unified-test-platform-android-test-plugin-host-coverage
|
||||
com.android.tools.utp:android-test-plugin-host-device-info-proto:32.3.1=unified-test-platform-android-test-plugin-host-device-info
|
||||
com.android.tools.utp:android-test-plugin-host-device-info:32.3.1=unified-test-platform-android-test-plugin-host-device-info
|
||||
com.android.tools.utp:android-test-plugin-host-emulator-control-proto:32.3.1=unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-host-emulator-control:32.3.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
com.android.tools.utp:android-test-plugin-host-logcat-proto:32.3.1=unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-host-logcat:32.3.1=unified-test-platform-android-test-plugin-host-logcat
|
||||
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:32.3.1=unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:android-test-plugin-result-listener-gradle:32.3.1=unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools.utp:gradle-work-action:32.3.1=unified-test-platform-gradle-work-action
|
||||
com.android.tools.utp:utp-common:32.3.1=unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-logcat
|
||||
com.android.tools:annotations:32.3.1=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.android.tools:common:32.3.1=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.android.tools:dvlib:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools:play-sdk-proto:32.3.1=androidLintTool
|
||||
com.android.tools:repository:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools:sdk-common:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.android.tools:sdklib:32.3.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.accompanist:accompanist-permissions:0.37.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.datatransport:transport-api:2.2.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.datatransport:transport-backend-cct:2.3.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.datatransport:transport-runtime:2.2.6=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.gms:play-services-base:18.9.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.gms:play-services-basement:18.9.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.gms:play-services-location:21.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.gms:play-services-tasks:18.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android.odml:image:1.0.0-beta1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.android:annotations:4.1.1.4=unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-core
|
||||
com.google.api.grpc:proto-google-common-protos:2.17.0=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core
|
||||
com.google.api.grpc:proto-google-common-protos:2.48.0=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
com.google.auto.service:auto-service-annotations:1.1.1=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.auto.service:auto-service:1.1.1=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.auto.value:auto-value-annotations:1.11.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.6.3=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.auto:auto-common:1.2.1=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.code.findbugs:jsr305:3.0.2=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.code.gson:gson:2.10.1=unified-test-platform-core,unified-test-platform-gradle-work-action
|
||||
com.google.code.gson:gson:2.11.0=androidLintTool,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.code.gson:gson:2.14.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.code.gson:gson:2.8.9=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher
|
||||
com.google.crypto.tink:tink-android:1.23.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.crypto.tink:tink:1.18.0=unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action
|
||||
com.google.dagger:dagger:2.48=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action
|
||||
com.google.dagger:dagger:2.59=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.38.0=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
com.google.errorprone:error_prone_annotations:2.36.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.google.errorprone:error_prone_annotations:2.48.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.firebase:firebase-annotations:16.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.firebase:firebase-components:16.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.firebase:firebase-encoders-json:17.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.firebase:firebase-encoders:16.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.guava:failureaccess:1.0.1=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
com.google.guava:failureaccess:1.0.2=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.google.guava:failureaccess:1.0.3=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.google.guava:guava:32.0.1-jre=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
com.google.guava:guava:33.4.0-jre=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.google.guava:guava:33.4.8-jre=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.google.guava:listenablefuture:1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=androidLintTool,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.j2objc:j2objc-annotations:2.8=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
com.google.j2objc:j2objc-annotations:3.0.0=androidLintTool,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.google.jimfs:jimfs:1.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.mlkit:barcode-scanning-common:17.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.mlkit:barcode-scanning:17.3.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.mlkit:common:18.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.mlkit:vision-common:17.3.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.mlkit:vision-interfaces:16.3.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.22.3=unified-test-platform-core
|
||||
com.google.protobuf:protobuf-java-util:4.28.3=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.protobuf:protobuf-java:3.25.5=androidLintTool
|
||||
com.google.protobuf:protobuf-java:4.28.3=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.protobuf:protobuf-kotlin:4.28.3=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.testing.platform:android-device-provider-local:0.0.9-alpha04=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.google.testing.platform:android-driver-instrumentation:0.0.9-alpha04=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control
|
||||
com.google.testing.platform:android-test-plugin:0.0.9-alpha04=unified-test-platform-android-test-plugin
|
||||
com.google.testing.platform:core-proto:0.0.9-alpha04=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
com.google.testing.platform:core:0.0.9-alpha04=unified-test-platform-core
|
||||
com.google.testing.platform:launcher:0.0.9-alpha04=unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
com.google.testparameterinjector:test-parameter-injector:1.18=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.google.zxing:core:3.5.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.ibm.icu:icu4j:77.1=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
com.squareup.okhttp3:okhttp-android:5.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.squareup.okhttp3:okhttp:5.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.squareup.okio:okio-jvm:3.17.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.squareup.okio:okio:3.17.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
com.squareup:javawriter:2.1.1=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
com.sun.istack:istack-commons-runtime:3.0.8=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.16=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
commons-codec:commons-codec:1.17.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
commons-io:commons-io:2.16.1=androidLintTool,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
commons-logging:commons-logging:1.2=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
io.grpc:grpc-api:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-api:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-context:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-context:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-core:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-core:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-netty:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-netty:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-protobuf-lite:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-protobuf-lite:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-protobuf:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-protobuf:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-services:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-stub:1.57.2=unified-test-platform-core
|
||||
io.grpc:grpc-stub:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.grpc:grpc-util:1.69.1=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-buffer:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-buffer:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-codec-http2:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-codec-http2:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-codec-http:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-codec-http:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-codec-socks:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-codec-socks:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-codec:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-codec:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-common:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-common:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-handler-proxy:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-handler-proxy:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-handler:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-handler:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-resolver:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-resolver:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-transport-native-unix-common:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-transport-native-unix-common:4.1.93.Final=unified-test-platform-core
|
||||
io.netty:netty-transport:4.1.110.Final=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
io.netty:netty-transport:4.1.93.Final=unified-test-platform-core
|
||||
io.opencensus:opencensus-api:0.31.0=unified-test-platform-core
|
||||
io.opencensus:opencensus-proto:0.2.0=unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
io.perfmark:perfmark-api:0.26.0=unified-test-platform-core
|
||||
io.perfmark:perfmark-api:0.27.0=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
jakarta.activation:jakarta.activation-api:1.2.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
jakarta.inject:jakarta.inject-api:2.0.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
jakarta.xml.bind:jakarta.xml.bind-api:2.3.2=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
javax.annotation:javax.annotation-api:1.3.2=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-test-plugin-host-emulator-control
|
||||
javax.inject:javax.inject:1=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action
|
||||
junit:junit:4.13.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.17.7=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.17.7=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
net.java.dev.jna:jna-platform:5.6.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
net.java.dev.jna:jna:5.6.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
net.sf.kxml:kxml2:2.3.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
no.nordicsemi.android:ble:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.27.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.apache.commons:commons-lang3:3.16.0=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.apache.httpcomponents:httpclient:4.5.6=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.apache.httpcomponents:httpcore:4.4.16=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.apache.httpcomponents:httpmime:4.5.6=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.bouncycastle:bcpkix-jdk18on:1.79=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.bouncycastle:bcprov-jdk18on:1.79=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.bouncycastle:bcprov-jdk18on:1.85=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.79=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.checkerframework:checker-qual:3.33.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
org.checkerframework:checker-qual:3.43.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
org.codehaus.groovy:groovy:3.0.22=androidLintTool
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=unified-test-platform-core
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.24=unified-test-platform-android-test-plugin-host-emulator-control
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.2=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.glassfish.jaxb:txw2:2.3.2=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.hamcrest:hamcrest-core:1.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.hamcrest:hamcrest-integration:1.3=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath
|
||||
org.hamcrest:hamcrest-library:1.3=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.jetbrains.kotlin:compose-group-mapping:2.4.10=composeMappingProducerClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-api:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-api:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-build-tools-compat:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-cri-impl:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-cri-impl:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-impl:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-impl:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable:2.4.10=kotlin-extension,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-reflect:2.2.10=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.jetbrains.kotlin:kotlin-script-runtime:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-script-runtime:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21=unified-test-platform-android-test-plugin,unified-test-platform-core
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:2.2.10=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-gradle-work-action
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:2.4.10=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.8.21=unified-test-platform-android-test-plugin,unified-test-platform-core
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.9.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher
|
||||
org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
|
||||
org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
|
||||
org.jetbrains.kotlinx:atomicfu-jvm:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlinx:atomicfu-jvm:0.28.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:atomicfu:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlinx:atomicfu:0.28.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.9.0=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=composeMappingProducerClasspath,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
|
||||
org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
|
||||
org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.mockito.kotlin:mockito-kotlin:6.3.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.mockito:mockito-core:5.23.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.nanohttpd:nanohttpd:2.3.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
|
||||
org.objenesis:objenesis:3.3=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:9.9=androidLintTool
|
||||
org.ow2.asm:asm-commons:9.8=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.9=androidLintTool
|
||||
org.ow2.asm:asm-tree:9.8=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.ow2.asm:asm-tree:9.9=androidLintTool
|
||||
org.ow2.asm:asm-tree:9.9.1=composeMappingProducerClasspath
|
||||
org.ow2.asm:asm:9.8=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.ow2.asm:asm:9.9=androidLintTool
|
||||
org.ow2.asm:asm:9.9.1=composeMappingProducerClasspath
|
||||
org.robolectric:annotations:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:junit:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:nativeruntime-dist-compat:1.0.17=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:nativeruntime:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:pluginapi:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:plugins-maven-dependency-resolver:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:resources:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:robolectric:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:sandbox:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:shadowapi:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:shadows-framework:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:utils-reflector:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.robolectric:utils:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.4=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
|
||||
empty=androidApis,androidJdkImage,androidTestUtil,coreLibraryDesugaring,debugAndroidTestAnnotationProcessorClasspath,debugAndroidTestImplementationDependenciesMetadata,debugAnnotationProcessorClasspath,debugImplementationDependenciesMetadata,debugReverseMetadataValues,debugUnitTestAnnotationProcessorClasspath,debugUnitTestImplementationDependenciesMetadata,kotlinCompilerPluginClasspath,lintChecks,lintPublish,releaseAnnotationProcessorClasspath,releaseImplementationDependenciesMetadata,releaseReverseMetadataValues
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
258
docs/reproducible-builds.md
Normal file
258
docs/reproducible-builds.md
Normal file
@ -0,0 +1,258 @@
|
||||
# Reproducible builds
|
||||
|
||||
Bitchat's canonical release build produces byte-for-byte reproducible unsigned
|
||||
APKs and an unsigned Android App Bundle (AAB). CI builds the release twice in
|
||||
independent jobs and refuses to publish it unless every canonical byte matches.
|
||||
|
||||
The signing key is intentionally not public. Anyone can reproduce the unsigned
|
||||
artifacts; GitHub Actions signs only the already-verified APKs, checks that
|
||||
signing itself is deterministic, verifies the expected certificate, and
|
||||
publishes checksums and provenance attestations for both unsigned and signed
|
||||
artifacts.
|
||||
|
||||
## What is pinned
|
||||
|
||||
- Gradle wrapper version and distribution SHA-256
|
||||
- dependency versions, strict Gradle dependency locks, and downloaded-artifact
|
||||
SHA-256 verification metadata
|
||||
- exact Temurin JDK release and digest-pinned Linux builder image
|
||||
- Android platform, Platform Tools, and Build Tools archives by filename and
|
||||
SHA-256, plus the accepted SDK license-text SHA-1 required to use them
|
||||
- Kotlin/JVM toolchain and bytecode target
|
||||
- Arti source tag and full commit, stable native build epoch, Rust, `cargo-ndk`,
|
||||
Android NDK, Cargo lockfile, digest-pinned Rust builder image, and immutable
|
||||
Debian package snapshot
|
||||
- immutable full commit SHAs for every third-party GitHub Action
|
||||
|
||||
The build uses a clean source tree, an isolated Gradle user home, UTC, a stable
|
||||
locale, `SOURCE_DATE_EPOCH` from the Git commit, no Gradle build or configuration
|
||||
cache, fresh tasks, and a non-incremental in-process Kotlin compiler. Native
|
||||
builds remap source paths and release validation rejects host paths in packaged
|
||||
libraries.
|
||||
|
||||
AGP's embedded VCS record is disabled because its Git discovery depends on the
|
||||
host checkout layout. The canonical `BUILDINFO.json` and GitHub provenance
|
||||
attestation record the host-verified commit instead.
|
||||
|
||||
The authoritative pins are:
|
||||
|
||||
- `gradle/wrapper/gradle-wrapper.properties`
|
||||
- `gradle/libs.versions.toml`
|
||||
- `settings-gradle.lockfile`
|
||||
- `app/gradle.lockfile`
|
||||
- `gradle/verification-metadata.xml`
|
||||
- `tools/reproducible-builds/TOOLCHAIN.env`
|
||||
- `tools/arti-build/TOOLCHAIN.env`
|
||||
- `tools/arti-build/Cargo.lock`
|
||||
|
||||
## Reproduce a release locally
|
||||
|
||||
Requirements are Git, Docker with Linux/amd64 support, and enough free space for
|
||||
the Android and Gradle images and dependencies.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/permissionlesstech/bitchat-android.git
|
||||
cd bitchat-android
|
||||
git checkout vX.Y.Z
|
||||
tools/reproducible-builds/build-in-container.sh \
|
||||
.reproducible-build/local-vX.Y.Z
|
||||
```
|
||||
|
||||
The output contains:
|
||||
|
||||
- unsigned APKs for arm64, armv7, x86, x86_64, and universal installs
|
||||
- `bitchat-android-release-unsigned.aab`
|
||||
- `BUILDINFO.json`
|
||||
- `SHA256SUMS.unsigned`
|
||||
|
||||
The output directory must not already contain files. The script rejects a dirty
|
||||
checkout so the commit in `BUILDINFO.json` identifies all source inputs.
|
||||
|
||||
To test reproducibility yourself, build into two empty directories and compare:
|
||||
|
||||
```bash
|
||||
BITCHAT_CONTAINER_GRADLE_HOME_NAME=gradle-home-first \
|
||||
tools/reproducible-builds/build-in-container.sh .reproducible-build/first
|
||||
BITCHAT_CONTAINER_GRADLE_HOME_NAME=gradle-home-second \
|
||||
tools/reproducible-builds/build-in-container.sh .reproducible-build/second
|
||||
tools/reproducible-builds/compare-release.sh \
|
||||
.reproducible-build/first \
|
||||
.reproducible-build/second
|
||||
```
|
||||
|
||||
If a comparison fails and `diffoscope` is installed, the comparison script
|
||||
automatically reports the first differing artifact.
|
||||
|
||||
## Verify a GitHub release
|
||||
|
||||
Install the GitHub CLI, authenticate it if necessary, check out the release tag,
|
||||
and run:
|
||||
|
||||
```bash
|
||||
git checkout vX.Y.Z
|
||||
tools/reproducible-builds/verify-github-release.sh vX.Y.Z
|
||||
```
|
||||
|
||||
That command:
|
||||
|
||||
1. downloads all release APKs, the AAB, build information, and checksum files;
|
||||
2. verifies each GitHub artifact-attestation subject against this repository;
|
||||
3. verifies `BITCHAT_SHA256SUMS`;
|
||||
4. checks that the local source commit is the release commit;
|
||||
5. rebuilds in the pinned container; and
|
||||
6. byte-compares every unsigned APK, the unsigned AAB, build information, and
|
||||
the unsigned checksum manifest.
|
||||
|
||||
To verify the published checksums and attestations without rebuilding:
|
||||
|
||||
```bash
|
||||
tools/reproducible-builds/verify-github-release.sh vX.Y.Z --no-rebuild
|
||||
```
|
||||
|
||||
For a manual signature check, use the exact `apksigner` from Android Build Tools
|
||||
37.0.0:
|
||||
|
||||
```bash
|
||||
apksigner verify --verbose --print-certs bitchat-android-universal.apk
|
||||
```
|
||||
|
||||
Compare the reported signer certificate SHA-256 with
|
||||
`BITCHAT_GITHUB_RELEASE_CERT_SHA256` in `gradle.properties`. A matching
|
||||
certificate proves who signed the APK; the checksum, attestation, and local
|
||||
unsigned rebuild establish which source and build produced it. A third party
|
||||
cannot recreate the signed bytes without the private release key.
|
||||
|
||||
You can also prove that the signed APK contains the same archive entries and
|
||||
uncompressed payload bytes as the reproduced unsigned APK:
|
||||
|
||||
```bash
|
||||
tools/reproducible-builds/compare-archive-payloads.sh \
|
||||
.reproducible-build/local-vX.Y.Z/bitchat-android-universal-unsigned.apk \
|
||||
bitchat-android-universal.apk
|
||||
```
|
||||
|
||||
GitHub's manual equivalents are:
|
||||
|
||||
```bash
|
||||
gh release download vX.Y.Z
|
||||
sha256sum -c BITCHAT_SHA256SUMS
|
||||
gh attestation verify bitchat-android-universal.apk \
|
||||
--repo permissionlesstech/bitchat-android
|
||||
```
|
||||
|
||||
## Verify a Google Play release
|
||||
|
||||
Google Play App Signing changes the verification boundary:
|
||||
|
||||
- maintainers upload a signed AAB using the upload key;
|
||||
- Google Play generates optimized, device-specific APK splits from that AAB;
|
||||
- Google signs the delivered APKs with the app-signing key.
|
||||
|
||||
Consequently, a Play-delivered APK is not expected to be byte-identical to the
|
||||
GitHub universal APK or to a locally built APK. Use this procedure instead:
|
||||
|
||||
1. In Play Console, open **Test and release > App bundle explorer**, select the
|
||||
release/version code, and download the original app bundle if that option is
|
||||
available to your account. Compare its unsigned payload with the reproduced
|
||||
`bitchat-android-release-unsigned.aab`:
|
||||
|
||||
```bash
|
||||
tools/reproducible-builds/compare-archive-payloads.sh \
|
||||
.reproducible-build/local-vX.Y.Z/bitchat-android-release-unsigned.aab \
|
||||
downloaded-from-play.aab
|
||||
```
|
||||
|
||||
The helper excludes JAR-signing metadata and compares every other entry name
|
||||
and uncompressed byte.
|
||||
2. In **Setup > App integrity**, record the SHA-256 fingerprint under **App
|
||||
signing key certificate**. This is different from the upload-key certificate
|
||||
and may be different from the GitHub release certificate.
|
||||
3. In App bundle explorer, download the Play-generated universal APK or the APKs
|
||||
for a representative device. Verify each APK:
|
||||
|
||||
```bash
|
||||
apksigner verify --verbose --print-certs downloaded-from-play.apk
|
||||
```
|
||||
|
||||
The signer SHA-256 must equal the Play Console app-signing certificate.
|
||||
4. Confirm package name `com.bitchat.droid`, version code, version name, and
|
||||
manifest/security configuration with Android's `apkanalyzer` or `aapt2`.
|
||||
5. Recreate Google's split-generation behavior from the reproduced AAB with the
|
||||
same `bundletool` version and a saved device specification:
|
||||
|
||||
```bash
|
||||
bundletool build-apks \
|
||||
--bundle=bitchat-android-release-unsigned.aab \
|
||||
--output=local.apks \
|
||||
--device-spec=device.json
|
||||
```
|
||||
|
||||
This last check validates bundle-to-APK behavior, but it is not a byte-equality
|
||||
claim: Play's server-side `bundletool` version, optimization, and signing inputs
|
||||
are controlled by Google. The strongest public Play verification requires
|
||||
maintainers to retain the uploaded AAB, publish its digest and provenance, and
|
||||
record the Play version code and app-signing certificate fingerprint alongside
|
||||
the release.
|
||||
|
||||
The current GitHub release workflow publishes the canonical unsigned AAB for
|
||||
verification; it does not upload to Google Play.
|
||||
|
||||
## Maintainer release process
|
||||
|
||||
Pushing a `vX.Y.Z` tag runs `.github/workflows/release.yml`:
|
||||
|
||||
1. two jobs independently build the canonical unsigned release;
|
||||
2. a comparison job requires exact byte equality;
|
||||
3. the signing job reads `SIGNING_KEY`, `ALIAS`, `KEY_STORE_PASSWORD`, and
|
||||
`KEY_PASSWORD` from GitHub Actions secrets;
|
||||
4. each published GitHub APK is signed twice and the two results must match;
|
||||
5. the signing certificate must match the public fingerprint in
|
||||
`gradle.properties`;
|
||||
6. GitHub generates build-provenance attestations and publishes all artifacts.
|
||||
|
||||
Never store a keystore or password in the repository, workflow artifacts, logs,
|
||||
or build information.
|
||||
|
||||
## Updating dependencies or toolchains
|
||||
|
||||
Dependency changes must update and review both the lock state and verification
|
||||
metadata:
|
||||
|
||||
```bash
|
||||
./gradlew testDebugUnitTest lintDebug \
|
||||
--write-locks \
|
||||
--write-verification-metadata sha256
|
||||
```
|
||||
|
||||
Generate release lock entries in separate invocations because split APK and AAB
|
||||
intermediates cannot coexist:
|
||||
|
||||
```bash
|
||||
./gradlew clean bundleRelease \
|
||||
--write-locks \
|
||||
--write-verification-metadata sha256
|
||||
./gradlew clean assembleRelease \
|
||||
--write-locks \
|
||||
--write-verification-metadata sha256
|
||||
```
|
||||
|
||||
Review every new repository, component, artifact name, version, and checksum.
|
||||
Do not accept verification metadata generated after an unexplained checksum
|
||||
failure.
|
||||
|
||||
When changing Gradle, update the wrapper and independently verify the new
|
||||
distribution SHA-256. When changing JDK or Android tools, update the exact
|
||||
version, archive checksum, and base-image digest together. Native updates follow
|
||||
[`tools/arti-build/README.md`](../tools/arti-build/README.md).
|
||||
|
||||
## References
|
||||
|
||||
- [Gradle dependency locking](https://docs.gradle.org/current/userguide/dependency_locking.html)
|
||||
- [Gradle dependency verification](https://docs.gradle.org/current/userguide/dependency_verification.html)
|
||||
- [Gradle wrapper checksum verification](https://docs.gradle.org/current/userguide/best_practices_security.html#use_the_gradle_wrapper_and_verify_the_wrapper_checksum)
|
||||
- [GitHub Actions security hardening](https://docs.github.com/en/actions/reference/security/secure-use)
|
||||
- [GitHub artifact attestation verification](https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations)
|
||||
- [Google Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756)
|
||||
- [Play Console App bundle explorer](https://support.google.com/googleplay/android-developer/answer/9859152)
|
||||
- [Android `bundletool`](https://developer.android.com/tools/bundletool)
|
||||
- [Android `apksigner`](https://developer.android.com/tools/apksigner)
|
||||
@ -5,6 +5,7 @@ kotlin = "2.4.10"
|
||||
compileSdk = "37"
|
||||
minSdk = "26" # API 26 for proper BLE support
|
||||
targetSdk = "37"
|
||||
buildTools = "37.0.0"
|
||||
|
||||
# AndroidX Core
|
||||
core-ktx = "1.19.0"
|
||||
|
||||
4620
gradle/verification-metadata.xml
Normal file
4620
gradle/verification-metadata.xml
Normal file
File diff suppressed because it is too large
Load Diff
1
gradle/wrapper/gradle-wrapper.properties
vendored
1
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||
distributionSha256Sum=9c0f7faeeb306cb14e4279a3e084ca6b596894089a0638e68a07c945a32c9e14
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
5
settings-gradle.lockfile
Normal file
5
settings-gradle.lockfile
Normal file
@ -0,0 +1,5 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
# To regenerate this file, run: ./gradlew dependencies --write-locks
|
||||
empty=incomingCatalogForLibs0
|
||||
@ -10,8 +10,6 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// Guardian Project raw GitHub Maven (hosts info.guardianproject:arti-mobile-ex)
|
||||
maven { url = uri("https://raw.githubusercontent.com/guardianproject/gpmaven/master") }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1 +0,0 @@
|
||||
arti-v1.9.0
|
||||
5429
tools/arti-build/Cargo.lock
generated
Normal file
5429
tools/arti-build/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "arti-android-wrapper"
|
||||
version = "1.7.0"
|
||||
version = "1.9.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
@ -11,8 +11,8 @@ crate-type = ["cdylib"]
|
||||
name = "arti_android"
|
||||
|
||||
[dependencies]
|
||||
arti-client = { path = "../crates/arti-client", default-features = false, features = ["tokio", "rustls", "compression", "bridge-client", "onion-service-client", "static-sqlite"] }
|
||||
tor-rtcompat = { path = "../crates/tor-rtcompat", features = ["tokio", "rustls"] }
|
||||
arti-client = { path = "../crates/arti-client", default-features = false, features = ["tokio", "rustls", "compression", "bridge-client", "onion-service-client", "static", "static-sqlite"] }
|
||||
tor-rtcompat = { path = "../crates/tor-rtcompat", features = ["tokio", "rustls", "static"] }
|
||||
jni = "0.21"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
anyhow = "1.0"
|
||||
@ -22,4 +22,4 @@ opt-level = "z" # Optimize for size
|
||||
lto = true # Link-time optimization
|
||||
codegen-units = 1 # Better optimization
|
||||
strip = true # Strip symbols
|
||||
panic = "abort" # Smaller panic handler
|
||||
panic = "abort" # Smaller panic handler
|
||||
|
||||
58
tools/arti-build/Dockerfile
Normal file
58
tools/arti-build/Dockerfile
Normal file
@ -0,0 +1,58 @@
|
||||
# syntax=docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89
|
||||
FROM rust:1.95.0-slim-bookworm@sha256:d7482085ff5b415f84dba5647ae71606650bdef00db7aeb69f4b3d170c3e4082
|
||||
|
||||
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
|
||||
|
||||
COPY tools/arti-build/TOOLCHAIN.env /tmp/TOOLCHAIN.env
|
||||
|
||||
RUN source /tmp/TOOLCHAIN.env \
|
||||
&& printf '%s\n' \
|
||||
'Types: deb' \
|
||||
"URIs: https://snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT}" \
|
||||
'Suites: bookworm bookworm-updates' \
|
||||
'Components: main' \
|
||||
'Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg' \
|
||||
'Check-Valid-Until: no' \
|
||||
'' \
|
||||
'Types: deb' \
|
||||
"URIs: https://snapshot.debian.org/archive/debian-security/${DEBIAN_SNAPSHOT}" \
|
||||
'Suites: bookworm-security' \
|
||||
'Components: main' \
|
||||
'Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg' \
|
||||
'Check-Valid-Until: no' \
|
||||
> /etc/apt/sources.list.d/debian.sources \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
binutils \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN source /tmp/TOOLCHAIN.env \
|
||||
&& curl -fsSL \
|
||||
"https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE}" \
|
||||
-o "/tmp/${ANDROID_NDK_ARCHIVE}" \
|
||||
&& echo "${ANDROID_NDK_SHA256} /tmp/${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
|
||||
&& unzip -q "/tmp/${ANDROID_NDK_ARCHIVE}" -d /opt \
|
||||
&& rm "/tmp/${ANDROID_NDK_ARCHIVE}" \
|
||||
&& test "$(sed -n 's/^Pkg.Revision *= *//p' /opt/android-ndk-r27d/source.properties | tr -d '\r')" = "$ANDROID_NDK_VERSION"
|
||||
|
||||
RUN source /tmp/TOOLCHAIN.env \
|
||||
&& test "$(rustc --version | awk '{print $2}')" = "$RUST_VERSION" \
|
||||
&& cargo install cargo-ndk --version "$CARGO_NDK_VERSION" --locked \
|
||||
&& rustup target add \
|
||||
aarch64-linux-android \
|
||||
armv7-linux-androideabi \
|
||||
i686-linux-android \
|
||||
x86_64-linux-android
|
||||
|
||||
ENV ANDROID_NDK_HOME=/opt/android-ndk-r27d
|
||||
ENV PATH=/usr/local/cargo/bin:${PATH}
|
||||
ENV TZ=UTC
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "tools/arti-build/build-arti.sh", "--clean"]
|
||||
@ -1,223 +1,70 @@
|
||||
# Arti Android Build Tools
|
||||
# Rebuilding Arti for Android
|
||||
|
||||
This directory contains the build scripts and source files for compiling the custom Arti (Tor in Rust) library for Android.
|
||||
|
||||
## Overview
|
||||
|
||||
bitchat-android uses a custom-built Arti library instead of Guardian Project's outdated `arti-mobile-ex` AAR. This provides:
|
||||
|
||||
- **Smaller APK size**: ~11MB total vs ~140MB with Guardian Project AAR (28x reduction)
|
||||
- **Latest Arti version**: Currently v1.7.0 with pure Rust TLS (rustls)
|
||||
- **16KB page size support**: Required for Google Play (Nov 2025)
|
||||
- **Full transparency**: Build from official Arti source + our JNI wrapper
|
||||
|
||||
## Quick Start
|
||||
|
||||
The pre-built `.so` files are committed to the repo, so you don't need to build unless you want to:
|
||||
|
||||
1. **Verify the binaries** match the source
|
||||
2. **Update to a new Arti version**
|
||||
3. **Modify the JNI wrapper**
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
tools/arti-build/
|
||||
├── README.md # This file
|
||||
├── build-arti.sh # Main build script (clones Arti, builds .so files)
|
||||
├── ARTI_VERSION # Pinned Arti version tag (e.g., arti-v1.7.0)
|
||||
├── Cargo.toml # Rust package configuration
|
||||
├── src/
|
||||
│ └── lib.rs # JNI wrapper (Rust -> Kotlin/Java bridge)
|
||||
└── .arti-source/ # [GITIGNORED] Cloned official Arti repo
|
||||
|
||||
app/src/main/jniLibs/ # [COMMITTED] Pre-built native libraries
|
||||
├── arm64-v8a/
|
||||
│ └── libarti_android.so (~5.3MB)
|
||||
└── x86_64/
|
||||
└── libarti_android.so (~6.2MB)
|
||||
```
|
||||
|
||||
## Rebuilding from Source
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **Rust toolchain** with Android targets:
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
rustup target add aarch64-linux-android x86_64-linux-android
|
||||
```
|
||||
|
||||
2. **cargo-ndk** for Android cross-compilation:
|
||||
```bash
|
||||
cargo install cargo-ndk
|
||||
```
|
||||
|
||||
3. **Android NDK 25+** (for 16KB page size support):
|
||||
```bash
|
||||
# Via Android Studio SDK Manager, or:
|
||||
$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.0.12077973"
|
||||
|
||||
# Set environment variable
|
||||
export ANDROID_NDK_HOME="$HOME/Library/Android/sdk/ndk/27.0.12077973"
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
The four committed `libarti_android.so` files are built from the official Arti
|
||||
source plus the JNI wrapper in this directory. The supported build path is the
|
||||
pinned Linux container:
|
||||
|
||||
```bash
|
||||
cd tools/arti-build
|
||||
|
||||
# Build both architectures (arm64 + x86_64 for emulator)
|
||||
./build-arti.sh
|
||||
|
||||
# Build ARM64 only (smaller, for production releases)
|
||||
./build-arti.sh --release
|
||||
|
||||
# Clean rebuild (re-clone Arti source)
|
||||
./build-arti.sh --clean
|
||||
tools/arti-build/rebuild-in-container.sh
|
||||
tools/arti-build/verify-checksums.sh
|
||||
```
|
||||
|
||||
The script will:
|
||||
1. Clone official Arti from https://gitlab.torproject.org/tpo/core/arti
|
||||
2. Checkout the version specified in `ARTI_VERSION`
|
||||
3. Copy our JNI wrapper into the cloned repo
|
||||
4. Build with `cargo ndk`
|
||||
5. Copy `.so` files to `app/src/main/jniLibs/`
|
||||
The container builds all four Android ABIs, verifies the exported JNI symbols
|
||||
and rejects native binaries containing host-specific paths. It then rewrites
|
||||
`tools/arti-build/SHA256SUMS`; both that manifest and the rebuilt libraries are
|
||||
release inputs.
|
||||
|
||||
### Verification
|
||||
## Pinned inputs
|
||||
|
||||
After building, verify the libraries:
|
||||
- `TOOLCHAIN.env`: Arti tag and commit, stable build epoch, Rust, `cargo-ndk`,
|
||||
Android NDK, and immutable Debian snapshot
|
||||
- `rust-toolchain.toml`: Rust release and Android targets
|
||||
- `Cargo.lock`: complete Rust dependency graph
|
||||
- `Dockerfile`: digest-pinned Rust base image and checksum-verified NDK archive
|
||||
- `Cargo.toml` and `src/lib.rs`: JNI wrapper package and source
|
||||
|
||||
```bash
|
||||
# Check file sizes
|
||||
ls -lh ../../app/src/main/jniLibs/*/libarti_android.so
|
||||
Rust source paths are remapped to stable virtual paths, incremental compilation
|
||||
is disabled, and `SOURCE_DATE_EPOCH` is pinned to the value used for the
|
||||
committed libraries.
|
||||
|
||||
# Verify JNI symbols are exported
|
||||
nm -gU ../../app/src/main/jniLibs/arm64-v8a/libarti_android.so | grep Java_org_torproject
|
||||
## Updating Arti or the native toolchain
|
||||
|
||||
# Verify 16KB page alignment
|
||||
readelf -l ../../app/src/main/jniLibs/arm64-v8a/libarti_android.so | grep LOAD
|
||||
# Look for: Align 0x4000 (16KB)
|
||||
```
|
||||
1. Update the tag, full source commit, stable build epoch, tool versions,
|
||||
archive name, and archive checksum in `TOOLCHAIN.env`.
|
||||
2. Update `Cargo.toml` if Arti changed its crate features or wrapper version.
|
||||
3. Regenerate `Cargo.lock` against the exact Arti checkout and review every
|
||||
dependency change:
|
||||
|
||||
## Updating Arti Version
|
||||
|
||||
1. **Check available versions**:
|
||||
```bash
|
||||
git ls-remote --tags https://gitlab.torproject.org/tpo/core/arti.git | grep arti-v
|
||||
tools/arti-build/rebuild-in-container.sh --update-lockfile
|
||||
```
|
||||
|
||||
2. **Update the version file**:
|
||||
```bash
|
||||
echo "arti-v1.8.0" > ARTI_VERSION
|
||||
```
|
||||
4. Update the digest-pinned base image and `rust-toolchain.toml` when changing
|
||||
Rust.
|
||||
5. Run `tools/arti-build/rebuild-in-container.sh` twice from clean generated
|
||||
state and confirm `tools/arti-build/SHA256SUMS` is unchanged.
|
||||
6. Run the Android tests and the two-build release comparison described in
|
||||
[`docs/reproducible-builds.md`](../../docs/reproducible-builds.md).
|
||||
|
||||
3. **Rebuild from scratch**:
|
||||
```bash
|
||||
./build-arti.sh --clean
|
||||
```
|
||||
Do not build release native libraries with an unpinned local NDK or Rust
|
||||
toolchain. `build-arti.sh` deliberately rejects mismatched tool versions.
|
||||
|
||||
4. **Test the build**:
|
||||
```bash
|
||||
cd ../..
|
||||
./gradlew clean assembleDebug
|
||||
./gradlew installDebug
|
||||
# Enable Tor in app and verify it works
|
||||
```
|
||||
## JNI surface
|
||||
|
||||
5. **Commit the new libraries**:
|
||||
```bash
|
||||
git add app/src/main/jniLibs/ tools/arti-build/ARTI_VERSION
|
||||
git commit -m "chore: update Arti to v1.8.0"
|
||||
```
|
||||
The wrapper exports the native methods used by `ArtiNative`:
|
||||
|
||||
## JNI Wrapper Architecture
|
||||
- `getVersion`
|
||||
- `setLogCallback`
|
||||
- `initialize`
|
||||
- `startSocksProxy`
|
||||
- `stop`
|
||||
|
||||
The `src/lib.rs` file implements a JNI bridge between Kotlin and Rust:
|
||||
|
||||
```
|
||||
Kotlin (ArtiNative.kt)
|
||||
↓ JNI
|
||||
Rust (lib.rs)
|
||||
↓
|
||||
Arti Client (TorClient)
|
||||
↓
|
||||
SOCKS5 Proxy (localhost:9060)
|
||||
```
|
||||
|
||||
**Exported JNI Functions**:
|
||||
- `getVersion()` - Returns Arti version string
|
||||
- `setLogCallback(callback)` - Registers log listener for bootstrap progress
|
||||
- `initialize(dataDir)` - Creates Tokio runtime and TorClient
|
||||
- `startSocksProxy(port)` - Starts SOCKS5 proxy on specified port
|
||||
- `stop()` - Stops SOCKS proxy (TorClient is reused)
|
||||
|
||||
**Key Design Decisions**:
|
||||
- Global `TorClient` persists across stop/start cycles (fixes Nov 2024 toggle bug)
|
||||
- Tokio runtime created once and never destroyed
|
||||
- Log messages bridged to Java via `GlobalRef` callback
|
||||
|
||||
## Feature Configuration
|
||||
|
||||
Edit `Cargo.toml` to customize Arti features:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
arti-client = {
|
||||
path = "../crates/arti-client",
|
||||
default-features = false,
|
||||
features = [
|
||||
"tokio", # Required: async runtime
|
||||
"rustls", # Required: pure Rust TLS (no OpenSSL)
|
||||
"compression", # Optional: directory compression
|
||||
"bridge-client", # Optional: Tor bridge support
|
||||
"onion-service-client", # Optional: .onion site support
|
||||
"static-sqlite" # Required: bundled SQLite
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Size Comparison
|
||||
|
||||
| Configuration | arm64-v8a | x86_64 | Total | APK Size |
|
||||
|---------------|-----------|--------|-------|----------|
|
||||
| Guardian Project AAR | - | - | ~140 MB | ~150 MB |
|
||||
| Custom (both arch) | 5.3 MB | 6.2 MB | 11.5 MB | ~15 MB |
|
||||
| Custom (ARM-only) | 5.3 MB | - | 5.3 MB | ~10 MB |
|
||||
|
||||
**28x size reduction** vs Guardian Project implementation.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "cargo-ndk not found"
|
||||
```bash
|
||||
cargo install cargo-ndk
|
||||
```
|
||||
|
||||
### "Android NDK not found"
|
||||
```bash
|
||||
export ANDROID_NDK_HOME="$HOME/Library/Android/sdk/ndk/27.0.12077973"
|
||||
```
|
||||
|
||||
### "Rust target not installed"
|
||||
```bash
|
||||
rustup target add aarch64-linux-android x86_64-linux-android
|
||||
```
|
||||
|
||||
### "Version not found"
|
||||
Check available versions:
|
||||
```bash
|
||||
git ls-remote --tags https://gitlab.torproject.org/tpo/core/arti.git | grep arti-v | tail -10
|
||||
```
|
||||
|
||||
### Library too large
|
||||
1. Ensure building with `--release` flag
|
||||
2. Verify `strip = true` in `Cargo.toml` `[profile.release]`
|
||||
3. Consider removing optional features
|
||||
The build fails if any expected symbol is absent. The NDK `readelf` check also
|
||||
reports ELF load-segment alignment for Android's 16 KiB page-size requirement.
|
||||
|
||||
## References
|
||||
|
||||
- [Arti Documentation](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/doc/README.md)
|
||||
- [cargo-ndk](https://github.com/bbqsrc/cargo-ndk)
|
||||
- [Android NDK Guide](https://developer.android.com/ndk/guides)
|
||||
- [Google Play 16KB Page Size](https://developer.android.com/guide/practices/page-sizes)
|
||||
- [Arti source](https://gitlab.torproject.org/tpo/core/arti)
|
||||
- [Cargo lockfiles](https://doc.rust-lang.org/cargo/faq.html#why-have-cargolock-in-version-control)
|
||||
- [Rust source-path remapping](https://doc.rust-lang.org/rustc/remap-source-paths.html)
|
||||
- [Install a specific Android NDK](https://developer.android.com/studio/projects/install-ndk)
|
||||
|
||||
4
tools/arti-build/SHA256SUMS
Normal file
4
tools/arti-build/SHA256SUMS
Normal file
@ -0,0 +1,4 @@
|
||||
bb92268898b51a7b2979e74aa5263bdffb6450a1703c2fa6f2779e714e154d61 app/src/main/jniLibs/arm64-v8a/libarti_android.so
|
||||
2a037d0cef4cef2227dba4bd8ad6c10ccf29064c5718298b21dae0de0a7c11ad app/src/main/jniLibs/armeabi-v7a/libarti_android.so
|
||||
e70eece0ccf425032c11c3177801fe10b964c8be0e14c926da6b613a2d06aead app/src/main/jniLibs/x86/libarti_android.so
|
||||
ae6f389c4fe9d969c65e64a1d55169fc941e7d95737aa3ba0b8d42f5d54d6c56 app/src/main/jniLibs/x86_64/libarti_android.so
|
||||
9
tools/arti-build/TOOLCHAIN.env
Normal file
9
tools/arti-build/TOOLCHAIN.env
Normal file
@ -0,0 +1,9 @@
|
||||
ARTI_VERSION=arti-v1.9.0
|
||||
ARTI_COMMIT=ba421ece1acb47e5c554c2bfa043cc9156451bab
|
||||
NATIVE_SOURCE_DATE_EPOCH=1785193050
|
||||
DEBIAN_SNAPSHOT=20260720T000000Z
|
||||
RUST_VERSION=1.95.0
|
||||
CARGO_NDK_VERSION=4.1.2
|
||||
ANDROID_NDK_VERSION=27.3.13750724
|
||||
ANDROID_NDK_ARCHIVE=android-ndk-r27d-linux.zip
|
||||
ANDROID_NDK_SHA256=601246087a682d1944e1e16dd85bc6e49560fe8b6d61255be2829178c8ed15d9
|
||||
@ -8,17 +8,14 @@
|
||||
# - Update to a new Arti version
|
||||
# - Debug or modify the wrapper code
|
||||
#
|
||||
# Requirements:
|
||||
# - Bash 4+ (macOS default bash is 3.2; install via Homebrew: brew install bash)
|
||||
# - Rust toolchain with Android targets:
|
||||
# rustup target add aarch64-linux-android x86_64-linux-android
|
||||
# - cargo-ndk: cargo install cargo-ndk
|
||||
# - Android NDK 25+ (for 16KB page size support)
|
||||
# Requirements are pinned in TOOLCHAIN.env and rust-toolchain.toml. The
|
||||
# supported entry point is rebuild-in-container.sh, which supplies all of them.
|
||||
#
|
||||
# Usage:
|
||||
# ./build-arti.sh # Build both architectures (debug/emulator)
|
||||
# ./build-arti.sh --release # Build ARM64 only (production)
|
||||
# ./build-arti.sh --release # Build ARM targets only
|
||||
# ./build-arti.sh --clean # Remove cloned Arti repo and rebuild
|
||||
# ./build-arti.sh --update-lockfile # Refresh Cargo.lock without building
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@ -38,57 +35,21 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
ARTI_SOURCE_DIR="$SCRIPT_DIR/.arti-source"
|
||||
JNILIBS_DIR="$PROJECT_ROOT/app/src/main/jniLibs"
|
||||
TOOLCHAIN_FILE="$SCRIPT_DIR/TOOLCHAIN.env"
|
||||
LOCKFILE_SOURCE="$SCRIPT_DIR/Cargo.lock"
|
||||
|
||||
|
||||
detect_default_ndk_home() {
|
||||
local candidates=(
|
||||
"$HOME/Library/Android/sdk/ndk/27.0.12077973"
|
||||
"$HOME/Library/Android/sdk/ndk"
|
||||
"$HOME/Library/Android/sdk/ndk-bundle"
|
||||
"$HOME/Android/Sdk/ndk/27.0.12077973"
|
||||
"$HOME/Android/Sdk/ndk"
|
||||
"$HOME/Android/Sdk/ndk-bundle"
|
||||
)
|
||||
|
||||
for candidate in "${candidates[@]}"; do
|
||||
if [ -d "$candidate" ]; then
|
||||
echo "$candidate"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
local base
|
||||
for base in "$HOME/Library/Android/sdk/ndk" "$HOME/Android/Sdk/ndk"; do
|
||||
if [ -d "$base" ]; then
|
||||
local latest
|
||||
latest="$(find "$base" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sort | tail -1)"
|
||||
if [ -n "$latest" ]; then
|
||||
echo "$latest"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Read pinned version
|
||||
if [ ! -f "$SCRIPT_DIR/ARTI_VERSION" ]; then
|
||||
echo -e "${RED}Error: ARTI_VERSION file not found${NC}"
|
||||
if [ ! -f "$TOOLCHAIN_FILE" ]; then
|
||||
echo -e "${RED}Error: TOOLCHAIN.env file not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
VERSION="$(tr -d '[:space:]' < "$SCRIPT_DIR/ARTI_VERSION")"
|
||||
# shellcheck disable=SC1090
|
||||
source "$TOOLCHAIN_FILE"
|
||||
|
||||
VERSION="$ARTI_VERSION"
|
||||
export RUSTUP_TOOLCHAIN="$RUST_VERSION"
|
||||
|
||||
# Android NDK path
|
||||
if [ -z "${ANDROID_NDK_HOME:-}" ]; then
|
||||
AUTO_NDK_HOME="$(detect_default_ndk_home)"
|
||||
if [ -n "$AUTO_NDK_HOME" ]; then
|
||||
ANDROID_NDK_HOME="$AUTO_NDK_HOME"
|
||||
fi
|
||||
fi
|
||||
if [ -z "${ANDROID_NDK_HOME:-}" ]; then
|
||||
echo -e "${RED}Error: ANDROID_NDK_HOME is not set and automatic detection failed.${NC}"
|
||||
echo "Set ANDROID_NDK_HOME to your NDK installation (e.g., ~/Android/Sdk/ndk/<version>)."
|
||||
echo -e "${RED}Error: ANDROID_NDK_HOME must point to NDK $ANDROID_NDK_VERSION.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
export ANDROID_NDK_HOME
|
||||
@ -96,9 +57,29 @@ export ANDROID_NDK_HOME
|
||||
# Min SDK version (must match bitchat-android minSdk)
|
||||
MIN_SDK_VERSION=26
|
||||
|
||||
# Keep host paths and timestamps out of Rust objects and panic-location strings.
|
||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$NATIVE_SOURCE_DATE_EPOCH}"
|
||||
if ! [[ "$SOURCE_DATE_EPOCH" =~ ^[0-9]+$ ]]; then
|
||||
echo -e "${RED}Error: SOURCE_DATE_EPOCH must be an integer.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
CARGO_HOME_PATH="${CARGO_HOME:-$HOME/.cargo}"
|
||||
REPRO_RUSTFLAGS=(
|
||||
"--remap-path-prefix=$PROJECT_ROOT=/usr/src/bitchat-android"
|
||||
"--remap-path-prefix=$ARTI_SOURCE_DIR=/usr/src/arti"
|
||||
"--remap-path-prefix=$CARGO_HOME_PATH=/usr/local/cargo"
|
||||
)
|
||||
for rustflag in "${REPRO_RUSTFLAGS[@]}"; do
|
||||
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }$rustflag"
|
||||
done
|
||||
export CARGO_INCREMENTAL=0
|
||||
export RUSTFLAGS
|
||||
export SOURCE_DATE_EPOCH
|
||||
|
||||
# Parse arguments
|
||||
RELEASE_ONLY=false
|
||||
CLEAN_BUILD=false
|
||||
UPDATE_LOCKFILE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@ -110,12 +91,17 @@ while [[ $# -gt 0 ]]; do
|
||||
CLEAN_BUILD=true
|
||||
shift
|
||||
;;
|
||||
--update-lockfile)
|
||||
UPDATE_LOCKFILE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [--release] [--clean]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --release Build ARM64 only (smaller, for production)"
|
||||
echo " --release Build ARM targets only"
|
||||
echo " --clean Remove cached Arti source and rebuild from scratch"
|
||||
echo " --update-lockfile Regenerate the wrapper Cargo.lock and exit"
|
||||
echo ""
|
||||
exit 0
|
||||
;;
|
||||
@ -220,10 +206,16 @@ check_prerequisites() {
|
||||
|
||||
# Rust
|
||||
if ! command -v rustc >/dev/null 2>&1; then
|
||||
print_error "Rust is not installed. Install from https://rustup.rs/"
|
||||
print_error "Rust is not installed."
|
||||
exit 1
|
||||
fi
|
||||
print_success "Rust found: $(rustc --version)"
|
||||
local actual_rust_version
|
||||
actual_rust_version="$(rustc --version | awk '{print $2}')"
|
||||
if [ "$actual_rust_version" != "$RUST_VERSION" ]; then
|
||||
print_error "Rust $RUST_VERSION is required; found $actual_rust_version"
|
||||
exit 1
|
||||
fi
|
||||
print_success "Rust version verified: $actual_rust_version"
|
||||
|
||||
# rustup
|
||||
if ! command -v rustup >/dev/null 2>&1; then
|
||||
@ -234,10 +226,16 @@ check_prerequisites() {
|
||||
|
||||
# cargo-ndk
|
||||
if ! command -v cargo-ndk >/dev/null 2>&1; then
|
||||
print_error "cargo-ndk is not installed. Run: cargo install cargo-ndk"
|
||||
print_error "cargo-ndk $CARGO_NDK_VERSION is not installed."
|
||||
exit 1
|
||||
fi
|
||||
print_success "cargo-ndk found: $(cargo-ndk --version 2>/dev/null || echo 'installed')"
|
||||
local actual_cargo_ndk_version
|
||||
actual_cargo_ndk_version="$(cargo ndk --version | awk '{print $2}')"
|
||||
if [ "$actual_cargo_ndk_version" != "$CARGO_NDK_VERSION" ]; then
|
||||
print_error "cargo-ndk $CARGO_NDK_VERSION is required; found $actual_cargo_ndk_version"
|
||||
exit 1
|
||||
fi
|
||||
print_success "cargo-ndk version verified: $actual_cargo_ndk_version"
|
||||
|
||||
# NDK
|
||||
if [ ! -d "$ANDROID_NDK_HOME" ]; then
|
||||
@ -247,17 +245,18 @@ check_prerequisites() {
|
||||
fi
|
||||
print_success "Android NDK found: $ANDROID_NDK_HOME"
|
||||
|
||||
# NDK version (should be 25+)
|
||||
NDK_VERSION="$(basename "$ANDROID_NDK_HOME" | cut -d'.' -f1)"
|
||||
if ! [[ "$NDK_VERSION" =~ ^[0-9]+$ ]]; then
|
||||
print_error "Could not parse NDK version from ANDROID_NDK_HOME: $ANDROID_NDK_HOME"
|
||||
local ndk_properties="$ANDROID_NDK_HOME/source.properties"
|
||||
if [ ! -f "$ndk_properties" ]; then
|
||||
print_error "NDK source.properties not found."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$NDK_VERSION" -lt 25 ]; then
|
||||
print_error "NDK version $NDK_VERSION is too old. NDK 25+ required for 16KB page size support"
|
||||
local actual_ndk_version
|
||||
actual_ndk_version="$(sed -n 's/^Pkg.Revision *= *//p' "$ndk_properties" | tr -d '\r')"
|
||||
if [ "$actual_ndk_version" != "$ANDROID_NDK_VERSION" ]; then
|
||||
print_error "Android NDK $ANDROID_NDK_VERSION is required; found $actual_ndk_version"
|
||||
exit 1
|
||||
fi
|
||||
print_success "NDK version: $NDK_VERSION (supports 16KB page size)"
|
||||
print_success "Android NDK version verified: $actual_ndk_version"
|
||||
|
||||
detect_ndk_host
|
||||
if [ ! -d "$NDK_LLVM_BIN" ]; then
|
||||
@ -267,10 +266,10 @@ check_prerequisites() {
|
||||
print_success "NDK host tag: $NDK_HOST"
|
||||
|
||||
if [ ! -x "$LLVM_STRIP" ]; then
|
||||
print_info "llvm-strip not found at: $LLVM_STRIP (stripping will be skipped)"
|
||||
else
|
||||
print_success "llvm-strip found"
|
||||
print_error "Pinned llvm-strip is missing."
|
||||
exit 1
|
||||
fi
|
||||
print_success "llvm-strip found"
|
||||
|
||||
if [ ! -x "$LLVM_NM" ] && ! command -v nm >/dev/null 2>&1; then
|
||||
print_error "Neither llvm-nm nor nm found. Cannot verify JNI symbols."
|
||||
@ -301,7 +300,7 @@ check_prerequisites() {
|
||||
}
|
||||
|
||||
clone_or_update_arti() {
|
||||
print_header "Setting up Arti Source (version: $VERSION)"
|
||||
print_header "Setting up Arti Source (version: $VERSION, commit: $ARTI_COMMIT)"
|
||||
|
||||
if [ "$CLEAN_BUILD" = true ] && [ -d "$ARTI_SOURCE_DIR" ]; then
|
||||
print_info "Cleaning existing Arti source..."
|
||||
@ -310,29 +309,32 @@ clone_or_update_arti() {
|
||||
|
||||
if [ ! -d "$ARTI_SOURCE_DIR" ]; then
|
||||
print_info "Cloning official Arti repository..."
|
||||
git clone https://gitlab.torproject.org/tpo/core/arti.git "$ARTI_SOURCE_DIR"
|
||||
git clone --filter=blob:none --no-checkout \
|
||||
https://gitlab.torproject.org/tpo/core/arti.git "$ARTI_SOURCE_DIR"
|
||||
else
|
||||
print_info "Using cached Arti source at $ARTI_SOURCE_DIR"
|
||||
fi
|
||||
|
||||
cd "$ARTI_SOURCE_DIR"
|
||||
|
||||
print_info "Fetching tags..."
|
||||
git fetch --tags --quiet
|
||||
print_info "Fetching pinned commit..."
|
||||
git fetch --depth 1 origin "$ARTI_COMMIT" --quiet
|
||||
|
||||
print_info "Checking out version: $VERSION"
|
||||
git checkout "$VERSION" --quiet 2>/dev/null || {
|
||||
print_error "Version $VERSION not found. Available versions:"
|
||||
git tag | grep "^arti-v" | tail -10
|
||||
exit 1
|
||||
}
|
||||
print_info "Checking out commit: $ARTI_COMMIT"
|
||||
git checkout --detach "$ARTI_COMMIT" --quiet
|
||||
|
||||
# Ensure clean working tree to avoid cached modifications influencing builds
|
||||
print_info "Resetting repository state (hard) and cleaning untracked files..."
|
||||
git reset --hard --quiet
|
||||
git clean -ffdqx --quiet
|
||||
|
||||
print_success "Arti source ready at version $VERSION"
|
||||
local actual_commit
|
||||
actual_commit="$(git rev-parse HEAD)"
|
||||
if [ "$actual_commit" != "$ARTI_COMMIT" ]; then
|
||||
print_error "Arti checkout mismatch."
|
||||
exit 1
|
||||
fi
|
||||
print_success "Arti source commit verified"
|
||||
|
||||
# Apply patches
|
||||
if [ -d "$SCRIPT_DIR/patches" ]; then
|
||||
@ -359,11 +361,43 @@ setup_wrapper() {
|
||||
|
||||
cp "$SCRIPT_DIR/src/lib.rs" "$WRAPPER_DIR/src/"
|
||||
cp "$SCRIPT_DIR/Cargo.toml" "$WRAPPER_DIR/"
|
||||
cp "$LOCKFILE_SOURCE" "$WRAPPER_DIR/Cargo.lock"
|
||||
|
||||
print_success "Wrapper files copied to $WRAPPER_DIR"
|
||||
echo ""
|
||||
}
|
||||
|
||||
ensure_wrapper_lockfile() {
|
||||
print_header "Ensuring wrapper Cargo.lock exists"
|
||||
|
||||
local WRAPPER_DIR="$ARTI_SOURCE_DIR/arti-android-wrapper"
|
||||
local LOCKFILE="$WRAPPER_DIR/Cargo.lock"
|
||||
|
||||
if [ ! -f "$LOCKFILE_SOURCE" ] || [ ! -f "$LOCKFILE" ]; then
|
||||
print_error "Committed Cargo.lock is required."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! cmp -s "$LOCKFILE_SOURCE" "$LOCKFILE"; then
|
||||
print_error "Wrapper Cargo.lock differs from the committed lockfile."
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_success "Committed Cargo.lock verified"
|
||||
echo ""
|
||||
}
|
||||
|
||||
update_wrapper_lockfile() {
|
||||
print_header "Updating wrapper Cargo.lock"
|
||||
|
||||
local WRAPPER_DIR="$ARTI_SOURCE_DIR/arti-android-wrapper"
|
||||
cargo generate-lockfile --manifest-path "$WRAPPER_DIR/Cargo.toml"
|
||||
cp "$WRAPPER_DIR/Cargo.lock" "$LOCKFILE_SOURCE"
|
||||
|
||||
print_success "Updated $LOCKFILE_SOURCE"
|
||||
echo ""
|
||||
}
|
||||
|
||||
build_for_target() {
|
||||
local TARGET="$1"
|
||||
local ABI="${ABI_MAP[$TARGET]}"
|
||||
@ -396,10 +430,8 @@ build_for_target() {
|
||||
# Strip debug symbols safely
|
||||
print_info "Stripping debug symbols..."
|
||||
if [ -x "$LLVM_STRIP" ]; then
|
||||
"$LLVM_STRIP" --strip-debug "$OUTPUT_PATH/$LIB_NAME" 2>/dev/null || true
|
||||
"$LLVM_STRIP" --strip-debug "$OUTPUT_PATH/$LIB_NAME"
|
||||
print_success "Stripped debug symbols"
|
||||
else
|
||||
print_info "Skipping strip (llvm-strip not available)"
|
||||
fi
|
||||
|
||||
local SIZE
|
||||
@ -434,6 +466,44 @@ build_for_target() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
verify_no_host_paths() {
|
||||
print_header "Verifying Native Build Privacy"
|
||||
|
||||
if ! command -v strings >/dev/null 2>&1; then
|
||||
print_error "strings is required to check native artifacts for host paths."
|
||||
return 1
|
||||
fi
|
||||
|
||||
for TARGET in "${TARGETS[@]}"; do
|
||||
local ABI="${ABI_MAP[$TARGET]}"
|
||||
local LIB_PATH="$JNILIBS_DIR/$ABI/libarti_android.so"
|
||||
if strings "$LIB_PATH" | grep -Eq '/Users/|/home/|[A-Za-z]:\\\\Users\\\\'; then
|
||||
print_error "Host-specific path detected in $ABI native library."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "No host-specific paths detected"
|
||||
echo ""
|
||||
}
|
||||
|
||||
write_checksums() {
|
||||
print_header "Writing Native Checksums"
|
||||
|
||||
local checksum_file="$SCRIPT_DIR/SHA256SUMS"
|
||||
: > "$checksum_file"
|
||||
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
|
||||
local lib_path="$JNILIBS_DIR/$abi/libarti_android.so"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$lib_path" | sed "s# $JNILIBS_DIR/# app/src/main/jniLibs/#" >> "$checksum_file"
|
||||
else
|
||||
shasum -a 256 "$lib_path" | sed "s# $JNILIBS_DIR/# app/src/main/jniLibs/#" >> "$checksum_file"
|
||||
fi
|
||||
done
|
||||
print_success "Wrote $checksum_file"
|
||||
echo ""
|
||||
}
|
||||
|
||||
verify_jni_symbols_for_lib() {
|
||||
local LIB_PATH="$1"
|
||||
|
||||
@ -525,11 +595,11 @@ show_summary() {
|
||||
echo ""
|
||||
echo -e "${GREEN}Next steps:${NC}"
|
||||
echo " 1. Test the build: ./gradlew assembleDebug"
|
||||
echo " 2. Commit the .so files: git add app/src/main/jniLibs/"
|
||||
echo " 2. Verify checksums: tools/arti-build/verify-checksums.sh"
|
||||
echo ""
|
||||
echo -e "${GREEN}To update Arti version:${NC}"
|
||||
echo " 1. Edit ARTI_VERSION with new version tag (e.g., arti-v1.8.0)"
|
||||
echo " 2. Run: ./build-arti.sh --clean"
|
||||
echo " 1. Update TOOLCHAIN.env and regenerate Cargo.lock"
|
||||
echo " 2. Run: tools/arti-build/rebuild-in-container.sh"
|
||||
echo ""
|
||||
}
|
||||
|
||||
@ -547,6 +617,10 @@ main() {
|
||||
check_prerequisites
|
||||
clone_or_update_arti
|
||||
setup_wrapper
|
||||
if [ "$UPDATE_LOCKFILE" = true ]; then
|
||||
update_wrapper_lockfile
|
||||
return 0
|
||||
fi
|
||||
ensure_wrapper_lockfile
|
||||
|
||||
for TARGET in "${TARGETS[@]}"; do
|
||||
@ -554,31 +628,11 @@ main() {
|
||||
done
|
||||
|
||||
verify_jni_symbols
|
||||
verify_no_host_paths
|
||||
if [ "$RELEASE_ONLY" = false ]; then
|
||||
write_checksums
|
||||
fi
|
||||
show_summary
|
||||
}
|
||||
|
||||
ensure_wrapper_lockfile() {
|
||||
print_header "Ensuring wrapper Cargo.lock exists"
|
||||
|
||||
local WRAPPER_DIR="$ARTI_SOURCE_DIR/arti-android-wrapper"
|
||||
local LOCKFILE="$WRAPPER_DIR/Cargo.lock"
|
||||
|
||||
if [ -f "$LOCKFILE" ]; then
|
||||
print_success "Cargo.lock already exists"
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_info "Cargo.lock missing; generating it once (network access may be required)..."
|
||||
(cd "$WRAPPER_DIR" && cargo generate-lockfile)
|
||||
|
||||
if [ ! -f "$LOCKFILE" ]; then
|
||||
print_error "Failed to generate Cargo.lock at $LOCKFILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_success "Generated Cargo.lock"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
44
tools/arti-build/rebuild-in-container.sh
Executable file
44
tools/arti-build/rebuild-in-container.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
IMAGE_NAME="bitchat-android-arti-builder:1.9.0"
|
||||
MODE="${1:-}"
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "error: Docker is required to rebuild the native Arti libraries" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$PROJECT_ROOT/.reproducible-build/cargo-home"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/TOOLCHAIN.env"
|
||||
if ! [[ "$NATIVE_SOURCE_DATE_EPOCH" =~ ^[0-9]+$ ]]; then
|
||||
echo "error: NATIVE_SOURCE_DATE_EPOCH must be an integer" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--file "$SCRIPT_DIR/Dockerfile" \
|
||||
--tag "$IMAGE_NAME" \
|
||||
"$PROJECT_ROOT"
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--platform linux/amd64 \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--env CARGO_HOME=/workspace/.reproducible-build/cargo-home \
|
||||
--env HOME=/workspace/.reproducible-build \
|
||||
--env SOURCE_DATE_EPOCH="$NATIVE_SOURCE_DATE_EPOCH" \
|
||||
--volume "$PROJECT_ROOT:/workspace" \
|
||||
"$IMAGE_NAME" \
|
||||
${MODE:+"$MODE"}
|
||||
|
||||
if [ "$MODE" = "--update-lockfile" ]; then
|
||||
echo "Cargo.lock updated in the pinned native container; review it before rebuilding."
|
||||
exit 0
|
||||
fi
|
||||
"$SCRIPT_DIR/verify-checksums.sh"
|
||||
9
tools/arti-build/rust-toolchain.toml
Normal file
9
tools/arti-build/rust-toolchain.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[toolchain]
|
||||
channel = "1.95.0"
|
||||
profile = "minimal"
|
||||
targets = [
|
||||
"aarch64-linux-android",
|
||||
"armv7-linux-androideabi",
|
||||
"i686-linux-android",
|
||||
"x86_64-linux-android",
|
||||
]
|
||||
29
tools/arti-build/verify-checksums.sh
Executable file
29
tools/arti-build/verify-checksums.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
CHECKSUM_FILE="$SCRIPT_DIR/SHA256SUMS"
|
||||
|
||||
if [ ! -f "$CHECKSUM_FILE" ]; then
|
||||
echo "error: missing native checksum manifest: $CHECKSUM_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum -c "$CHECKSUM_FILE"
|
||||
else
|
||||
shasum -a 256 -c "$CHECKSUM_FILE"
|
||||
fi
|
||||
|
||||
for library in app/src/main/jniLibs/*/libarti_android.so; do
|
||||
if strings "$library" | grep -Eq '/Users/|/home/|[A-Za-z]:\\\\Users\\\\'; then
|
||||
echo "error: host-specific path detected in a native library" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Native Arti libraries match the pinned checksums and contain no host paths."
|
||||
58
tools/reproducible-builds/Dockerfile
Normal file
58
tools/reproducible-builds/Dockerfile
Normal file
@ -0,0 +1,58 @@
|
||||
# syntax=docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89
|
||||
FROM eclipse-temurin:21.0.11_10-jdk-noble@sha256:35685c7e23352983a48882d97cd9875f5284c228db71d1e2476e5e6c1bab1080
|
||||
|
||||
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
|
||||
|
||||
COPY tools/reproducible-builds/TOOLCHAIN.env /tmp/TOOLCHAIN.env
|
||||
COPY tools/reproducible-builds/sdk-metadata /tmp/sdk-metadata
|
||||
|
||||
ENV ANDROID_HOME=/opt/android-sdk
|
||||
ENV ANDROID_SDK_ROOT=/opt/android-sdk
|
||||
|
||||
RUN source /tmp/TOOLCHAIN.env \
|
||||
&& mkdir -p "$ANDROID_HOME/build-tools" "$ANDROID_HOME/licenses" "$ANDROID_HOME/platforms" /tmp/android-packages \
|
||||
&& printf '%s\n' "$ANDROID_SDK_LICENSE_SHA1" > "$ANDROID_HOME/licenses/android-sdk-license" \
|
||||
&& curl -fsSL \
|
||||
"https://dl.google.com/android/repository/${ANDROID_BUILD_TOOLS_ARCHIVE}" \
|
||||
-o "/tmp/${ANDROID_BUILD_TOOLS_ARCHIVE}" \
|
||||
&& echo "${ANDROID_BUILD_TOOLS_SHA256} /tmp/${ANDROID_BUILD_TOOLS_ARCHIVE}" | sha256sum -c - \
|
||||
&& mkdir -p /tmp/android-packages/build-tools \
|
||||
&& cd /tmp/android-packages/build-tools \
|
||||
&& jar xf "/tmp/${ANDROID_BUILD_TOOLS_ARCHIVE}" \
|
||||
&& mv "/tmp/android-packages/build-tools/android-${ANDROID_PLATFORM_VERSION}" \
|
||||
"$ANDROID_HOME/build-tools/${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
&& cp /tmp/sdk-metadata/build-tools-37.0.0.xml \
|
||||
"$ANDROID_HOME/build-tools/${ANDROID_BUILD_TOOLS_VERSION}/package.xml" \
|
||||
&& find "$ANDROID_HOME/build-tools/${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
-maxdepth 1 -type f -exec chmod 755 {} + \
|
||||
&& curl -fsSL \
|
||||
"https://dl.google.com/android/repository/${ANDROID_PLATFORM_ARCHIVE}" \
|
||||
-o "/tmp/${ANDROID_PLATFORM_ARCHIVE}" \
|
||||
&& echo "${ANDROID_PLATFORM_SHA256} /tmp/${ANDROID_PLATFORM_ARCHIVE}" | sha256sum -c - \
|
||||
&& cd "$ANDROID_HOME/platforms" \
|
||||
&& jar xf "/tmp/${ANDROID_PLATFORM_ARCHIVE}" \
|
||||
&& cp /tmp/sdk-metadata/platform-37.0.xml \
|
||||
"$ANDROID_HOME/platforms/android-${ANDROID_PLATFORM_VERSION}/package.xml" \
|
||||
&& test -f "$ANDROID_HOME/platforms/android-${ANDROID_PLATFORM_VERSION}/android.jar" \
|
||||
&& curl -fsSL \
|
||||
"https://dl.google.com/android/repository/${ANDROID_PLATFORM_TOOLS_ARCHIVE}" \
|
||||
-o "/tmp/${ANDROID_PLATFORM_TOOLS_ARCHIVE}" \
|
||||
&& echo "${ANDROID_PLATFORM_TOOLS_SHA256} /tmp/${ANDROID_PLATFORM_TOOLS_ARCHIVE}" | sha256sum -c - \
|
||||
&& cd "$ANDROID_HOME" \
|
||||
&& jar xf "/tmp/${ANDROID_PLATFORM_TOOLS_ARCHIVE}" \
|
||||
&& cp /tmp/sdk-metadata/platform-tools-37.0.0.xml \
|
||||
"$ANDROID_HOME/platform-tools/package.xml" \
|
||||
&& find "$ANDROID_HOME/platform-tools" -maxdepth 1 -type f -exec chmod 755 {} + \
|
||||
&& rm -rf /tmp/android-packages \
|
||||
"/tmp/${ANDROID_BUILD_TOOLS_ARCHIVE}" \
|
||||
"/tmp/${ANDROID_PLATFORM_ARCHIVE}" \
|
||||
"/tmp/${ANDROID_PLATFORM_TOOLS_ARCHIVE}"
|
||||
|
||||
ENV PATH=/opt/android-sdk/build-tools/37.0.0:${PATH}
|
||||
|
||||
ENV TZ=UTC
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "tools/reproducible-builds/build-release.sh"]
|
||||
14
tools/reproducible-builds/TOOLCHAIN.env
Normal file
14
tools/reproducible-builds/TOOLCHAIN.env
Normal file
@ -0,0 +1,14 @@
|
||||
JAVA_VERSION=21.0.11+10
|
||||
JAVA_MAJOR_VERSION=21
|
||||
GRADLE_VERSION=9.6.1
|
||||
ANDROID_COMPILE_SDK=37
|
||||
ANDROID_PLATFORM_VERSION=37.0
|
||||
ANDROID_PLATFORM_ARCHIVE=platform-37.0_r02.zip
|
||||
ANDROID_PLATFORM_SHA256=840b23e827f96e64aea4c89a1194aac3dc5f6bad37edb231c5c795d890330e8d
|
||||
ANDROID_SDK_LICENSE_SHA1=24333f8a63b6825ea9c5514f83c2829b004d1fee
|
||||
ANDROID_PLATFORM_TOOLS_VERSION=37.0.0
|
||||
ANDROID_PLATFORM_TOOLS_ARCHIVE=platform-tools_r37.0.0-linux.zip
|
||||
ANDROID_PLATFORM_TOOLS_SHA256=198ae156ab285fa555987219af237b31102fefe8b9d2bc274708a8d4f2865a07
|
||||
ANDROID_BUILD_TOOLS_VERSION=37.0.0
|
||||
ANDROID_BUILD_TOOLS_ARCHIVE=build-tools_r37_linux.zip
|
||||
ANDROID_BUILD_TOOLS_SHA256=01af179347cbcd9c208b7f8171f7b21f6dd1d2f85bcd15e88caa51d5d7b86060
|
||||
63
tools/reproducible-builds/build-in-container.sh
Executable file
63
tools/reproducible-builds/build-in-container.sh
Executable file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
IMAGE_NAME="bitchat-android-reproducible-builder:21.0.11"
|
||||
OUTPUT_DIR="${1:-$PROJECT_ROOT/.reproducible-build/release}"
|
||||
GRADLE_HOME_NAME="${BITCHAT_CONTAINER_GRADLE_HOME_NAME:-gradle-home-container}"
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "error: Docker is required for the canonical container build" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${BITCHAT_ALLOW_DIRTY:-0}" != "1" ] && [ -n "$(git -C "$PROJECT_ROOT" status --porcelain --untracked-files=normal)" ]; then
|
||||
echo "error: reproducible builds require a clean source tree" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source_commit="$(git -C "$PROJECT_ROOT" rev-parse HEAD)"
|
||||
source_date_epoch="$(git -C "$PROJECT_ROOT" log -1 --format=%ct)"
|
||||
|
||||
if ! [[ "$GRADLE_HOME_NAME" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
||||
echo "error: BITCHAT_CONTAINER_GRADLE_HOME_NAME must be a simple directory name" >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$PROJECT_ROOT/.reproducible-build/$GRADLE_HOME_NAME"
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--file "$SCRIPT_DIR/Dockerfile" \
|
||||
--tag "$IMAGE_NAME" \
|
||||
"$PROJECT_ROOT"
|
||||
|
||||
container_output="$OUTPUT_DIR"
|
||||
case "$OUTPUT_DIR" in
|
||||
"$PROJECT_ROOT"/*)
|
||||
container_output="/workspace/${OUTPUT_DIR#"$PROJECT_ROOT"/}"
|
||||
output_mount=()
|
||||
;;
|
||||
*)
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
container_output="/output"
|
||||
output_mount=(--volume "$OUTPUT_DIR:/output")
|
||||
;;
|
||||
esac
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--platform linux/amd64 \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--env BITCHAT_ALLOW_DIRTY="${BITCHAT_ALLOW_DIRTY:-0}" \
|
||||
--env BITCHAT_GRADLE_USER_HOME="/workspace/.reproducible-build/$GRADLE_HOME_NAME" \
|
||||
--env BITCHAT_SOURCE_COMMIT="$source_commit" \
|
||||
--env BITCHAT_SOURCE_TREE_VERIFIED=1 \
|
||||
--env HOME=/workspace/.reproducible-build \
|
||||
--env SOURCE_DATE_EPOCH="$source_date_epoch" \
|
||||
--volume "$PROJECT_ROOT:/workspace" \
|
||||
"${output_mount[@]}" \
|
||||
"$IMAGE_NAME" \
|
||||
"$container_output"
|
||||
115
tools/reproducible-builds/build-release.sh
Executable file
115
tools/reproducible-builds/build-release.sh
Executable file
@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
OUTPUT_DIR="${1:-$PROJECT_ROOT/.reproducible-build/release}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/TOOLCHAIN.env"
|
||||
|
||||
if [ "${BITCHAT_SOURCE_TREE_VERIFIED:-0}" != "1" ] &&
|
||||
[ "${BITCHAT_ALLOW_DIRTY:-0}" != "1" ] &&
|
||||
[ -n "$(git -C "$PROJECT_ROOT" status --porcelain --untracked-files=normal)" ]; then
|
||||
echo "error: reproducible builds require a clean source tree" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
if [ -n "$(find "$OUTPUT_DIR" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
|
||||
echo "error: output directory must be empty: $OUTPUT_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
actual_java_version="$(java -XshowSettings:properties -version 2>&1 | sed -n 's/^ *java.version = //p' | head -1)"
|
||||
expected_java_version="${JAVA_VERSION%%+*}"
|
||||
if [ "$actual_java_version" != "$expected_java_version" ]; then
|
||||
echo "error: JDK $expected_java_version is required; found $actual_java_version" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$PROJECT_ROOT/tools/arti-build/verify-checksums.sh"
|
||||
|
||||
export GRADLE_USER_HOME="${BITCHAT_GRADLE_USER_HOME:-$PROJECT_ROOT/.reproducible-build/gradle-home}"
|
||||
export LC_ALL=C.UTF-8
|
||||
export SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git -C "$PROJECT_ROOT" log -1 --format=%ct)}"
|
||||
export TZ=UTC
|
||||
if ! [[ "$SOURCE_DATE_EPOCH" =~ ^[0-9]+$ ]]; then
|
||||
echo "error: SOURCE_DATE_EPOCH must be an integer" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gradle_args=(
|
||||
-Pkotlin.compiler.execution.strategy=in-process
|
||||
-Pkotlin.incremental=false
|
||||
--no-build-cache
|
||||
--no-configuration-cache
|
||||
--no-daemon
|
||||
--no-watch-fs
|
||||
--rerun-tasks
|
||||
)
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
./gradlew "${gradle_args[@]}" clean bundleRelease
|
||||
|
||||
aab_source="$PROJECT_ROOT/app/build/outputs/bundle/release/app-release.aab"
|
||||
if [ ! -f "$aab_source" ]; then
|
||||
echo "error: expected release AAB not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
cp "$aab_source" "$OUTPUT_DIR/bitchat-android-release-unsigned.aab"
|
||||
|
||||
# AGP cannot build split APKs and an app bundle from the same intermediates.
|
||||
./gradlew "${gradle_args[@]}" clean assembleRelease
|
||||
|
||||
declare -A apk_names=(
|
||||
["app-arm64-v8a-release-unsigned.apk"]="bitchat-android-arm64-unsigned.apk"
|
||||
["app-armeabi-v7a-release-unsigned.apk"]="bitchat-android-armv7-unsigned.apk"
|
||||
["app-universal-release-unsigned.apk"]="bitchat-android-universal-unsigned.apk"
|
||||
["app-x86-release-unsigned.apk"]="bitchat-android-x86-unsigned.apk"
|
||||
["app-x86_64-release-unsigned.apk"]="bitchat-android-x86_64-unsigned.apk"
|
||||
)
|
||||
|
||||
for source_name in "${!apk_names[@]}"; do
|
||||
source_path="$PROJECT_ROOT/app/build/outputs/apk/release/$source_name"
|
||||
if [ ! -f "$source_path" ]; then
|
||||
echo "error: expected release APK not found: $source_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
cp "$source_path" "$OUTPUT_DIR/${apk_names[$source_name]}"
|
||||
done
|
||||
|
||||
source_commit="${BITCHAT_SOURCE_COMMIT:-$(git -C "$PROJECT_ROOT" rev-parse HEAD)}"
|
||||
if ! [[ "$source_commit" =~ ^([0-9a-f]{40}|[0-9a-f]{64})$ ]]; then
|
||||
echo "error: source commit must be a full Git object ID" >&2
|
||||
exit 1
|
||||
fi
|
||||
native_manifest_sha256="$(sha256sum "$PROJECT_ROOT/tools/arti-build/SHA256SUMS" | awk '{print $1}')"
|
||||
|
||||
cat > "$OUTPUT_DIR/BUILDINFO.json" <<EOF
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"sourceCommit": "$source_commit",
|
||||
"sourceDateEpoch": $SOURCE_DATE_EPOCH,
|
||||
"javaVersion": "$JAVA_VERSION",
|
||||
"gradleVersion": "$GRADLE_VERSION",
|
||||
"androidCompileSdk": "$ANDROID_COMPILE_SDK",
|
||||
"androidBuildToolsVersion": "$ANDROID_BUILD_TOOLS_VERSION",
|
||||
"nativeManifestSha256": "$native_manifest_sha256"
|
||||
}
|
||||
EOF
|
||||
|
||||
"$SCRIPT_DIR/verify-no-host-paths.sh" "$OUTPUT_DIR"
|
||||
|
||||
(
|
||||
cd "$OUTPUT_DIR"
|
||||
{
|
||||
sha256sum BUILDINFO.json
|
||||
sha256sum bitchat-android-*-unsigned.apk
|
||||
sha256sum bitchat-android-release-unsigned.aab
|
||||
} | sort -k2 > SHA256SUMS.unsigned
|
||||
)
|
||||
|
||||
echo "Reproducible unsigned release written to $OUTPUT_DIR"
|
||||
48
tools/reproducible-builds/compare-archive-payloads.sh
Executable file
48
tools/reproducible-builds/compare-archive-payloads.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
FIRST_ARCHIVE="${1:?usage: compare-archive-payloads.sh FIRST.apk|aab SECOND.apk|aab}"
|
||||
SECOND_ARCHIVE="${2:?usage: compare-archive-payloads.sh FIRST.apk|aab SECOND.apk|aab}"
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_DIR"' EXIT
|
||||
|
||||
if ! command -v unzip >/dev/null 2>&1; then
|
||||
echo "error: unzip is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
SHA256=(sha256sum)
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
SHA256=(shasum -a 256)
|
||||
else
|
||||
echo "error: sha256sum or shasum is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
write_payload_manifest() {
|
||||
local archive="$1"
|
||||
local output="$2"
|
||||
|
||||
: > "$output"
|
||||
while IFS= read -r entry; do
|
||||
case "$entry" in
|
||||
*/|META-INF/MANIFEST.MF|META-INF/*.SF|META-INF/*.RSA|META-INF/*.DSA|META-INF/*.EC)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
local digest
|
||||
digest="$(unzip -p "$archive" "$entry" | "${SHA256[@]}" | awk '{print $1}')"
|
||||
printf '%s %s\n' "$digest" "$entry" >> "$output"
|
||||
done < <(unzip -Z1 "$archive" | LC_ALL=C sort)
|
||||
}
|
||||
|
||||
write_payload_manifest "$FIRST_ARCHIVE" "$TEMP_DIR/first"
|
||||
write_payload_manifest "$SECOND_ARCHIVE" "$TEMP_DIR/second"
|
||||
|
||||
if ! diff -u "$TEMP_DIR/first" "$TEMP_DIR/second"; then
|
||||
echo "error: signed/unsigned archive payloads differ" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Archive entry names and uncompressed payload bytes match (signing metadata excluded)."
|
||||
30
tools/reproducible-builds/compare-release.sh
Executable file
30
tools/reproducible-builds/compare-release.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
FIRST_DIR="${1:?usage: compare-release.sh FIRST_DIR SECOND_DIR}"
|
||||
SECOND_DIR="${2:?usage: compare-release.sh FIRST_DIR SECOND_DIR}"
|
||||
|
||||
artifacts=(
|
||||
BUILDINFO.json
|
||||
SHA256SUMS.unsigned
|
||||
bitchat-android-arm64-unsigned.apk
|
||||
bitchat-android-armv7-unsigned.apk
|
||||
bitchat-android-release-unsigned.aab
|
||||
bitchat-android-universal-unsigned.apk
|
||||
bitchat-android-x86-unsigned.apk
|
||||
bitchat-android-x86_64-unsigned.apk
|
||||
)
|
||||
|
||||
for artifact in "${artifacts[@]}"; do
|
||||
if ! cmp -s "$FIRST_DIR/$artifact" "$SECOND_DIR/$artifact"; then
|
||||
echo "error: reproducibility mismatch: $artifact" >&2
|
||||
if command -v diffoscope >/dev/null 2>&1; then
|
||||
diffoscope "$FIRST_DIR/$artifact" "$SECOND_DIR/$artifact" || true
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
echo "MATCH $artifact"
|
||||
done
|
||||
|
||||
echo "All unsigned APK, AAB, checksum, and build-info bytes match."
|
||||
40
tools/reproducible-builds/install-android-build-tools.sh
Executable file
40
tools/reproducible-builds/install-android-build-tools.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SDK_ROOT="${1:?usage: install-android-build-tools.sh SDK_ROOT}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/TOOLCHAIN.env"
|
||||
|
||||
for command in curl sha256sum unzip; do
|
||||
if ! command -v "$command" >/dev/null 2>&1; then
|
||||
echo "error: $command is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
destination="$SDK_ROOT/build-tools/$ANDROID_BUILD_TOOLS_VERSION"
|
||||
if [ -e "$destination" ]; then
|
||||
echo "error: Android Build Tools destination already exists: $destination" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_DIR"' EXIT
|
||||
archive="$TEMP_DIR/$ANDROID_BUILD_TOOLS_ARCHIVE"
|
||||
|
||||
curl -fsSL \
|
||||
"https://dl.google.com/android/repository/$ANDROID_BUILD_TOOLS_ARCHIVE" \
|
||||
-o "$archive"
|
||||
echo "$ANDROID_BUILD_TOOLS_SHA256 $archive" | sha256sum -c -
|
||||
unzip -q "$archive" -d "$TEMP_DIR/unpacked"
|
||||
|
||||
mkdir -p "$SDK_ROOT/build-tools"
|
||||
mv "$TEMP_DIR/unpacked/android-$ANDROID_PLATFORM_VERSION" "$destination"
|
||||
test "$(
|
||||
sed -n 's/^Pkg.Revision=//p' "$destination/source.properties" | tr -d '\r'
|
||||
)" = "$ANDROID_BUILD_TOOLS_VERSION"
|
||||
|
||||
echo "Installed checksum-verified Android Build Tools $ANDROID_BUILD_TOOLS_VERSION."
|
||||
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ns2:repository
|
||||
xmlns:ns2="http://schemas.android.com/repository/android/common/02"
|
||||
xmlns:ns5="http://schemas.android.com/repository/android/generic/02">
|
||||
<localPackage path="build-tools;37.0.0" obsolete="false">
|
||||
<type-details
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:type="ns5:genericDetailsType"/>
|
||||
<revision>
|
||||
<major>37</major>
|
||||
<minor>0</minor>
|
||||
<micro>0</micro>
|
||||
</revision>
|
||||
<display-name>Android SDK Build-Tools 37</display-name>
|
||||
</localPackage>
|
||||
</ns2:repository>
|
||||
20
tools/reproducible-builds/sdk-metadata/platform-37.0.xml
Normal file
20
tools/reproducible-builds/sdk-metadata/platform-37.0.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ns2:repository
|
||||
xmlns:ns2="http://schemas.android.com/repository/android/common/02"
|
||||
xmlns:ns6="http://schemas.android.com/sdk/android/repo/repository2/04">
|
||||
<localPackage path="platforms;android-37.0" obsolete="false">
|
||||
<type-details
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:type="ns6:platformDetailsType">
|
||||
<api-level>37.0</api-level>
|
||||
<codename></codename>
|
||||
<extension-level>22</extension-level>
|
||||
<base-extension>true</base-extension>
|
||||
<layoutlib api="15"/>
|
||||
</type-details>
|
||||
<revision>
|
||||
<major>2</major>
|
||||
</revision>
|
||||
<display-name>Android SDK Platform 37.0</display-name>
|
||||
</localPackage>
|
||||
</ns2:repository>
|
||||
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ns2:repository
|
||||
xmlns:ns2="http://schemas.android.com/repository/android/common/02"
|
||||
xmlns:ns5="http://schemas.android.com/repository/android/generic/02">
|
||||
<localPackage path="platform-tools" obsolete="false">
|
||||
<type-details
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:type="ns5:genericDetailsType"/>
|
||||
<revision>
|
||||
<major>37</major>
|
||||
<minor>0</minor>
|
||||
<micro>0</micro>
|
||||
</revision>
|
||||
<display-name>Android SDK Platform-Tools</display-name>
|
||||
</localPackage>
|
||||
</ns2:repository>
|
||||
121
tools/reproducible-builds/sign-release.sh
Executable file
121
tools/reproducible-builds/sign-release.sh
Executable file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
RELEASE_DIR="${1:?usage: sign-release.sh RELEASE_DIR}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/TOOLCHAIN.env"
|
||||
|
||||
: "${BITCHAT_SIGNING_KEY_BASE64:?BITCHAT_SIGNING_KEY_BASE64 is required}"
|
||||
: "${BITCHAT_SIGNING_KEY_ALIAS:?BITCHAT_SIGNING_KEY_ALIAS is required}"
|
||||
: "${BITCHAT_KEYSTORE_PASSWORD:?BITCHAT_KEYSTORE_PASSWORD is required}"
|
||||
: "${BITCHAT_KEY_PASSWORD:?BITCHAT_KEY_PASSWORD is required}"
|
||||
|
||||
ANDROID_SDK_HOME="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}"
|
||||
if [ -z "$ANDROID_SDK_HOME" ]; then
|
||||
echo "error: ANDROID_SDK_ROOT or ANDROID_HOME is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APKSIGNER="$ANDROID_SDK_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION/apksigner"
|
||||
ZIPALIGN="$ANDROID_SDK_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION/zipalign"
|
||||
if [ ! -x "$APKSIGNER" ] || [ ! -x "$ZIPALIGN" ]; then
|
||||
echo "error: Android Build Tools $ANDROID_BUILD_TOOLS_VERSION are required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$RELEASE_DIR"
|
||||
sha256sum -c SHA256SUMS.unsigned
|
||||
)
|
||||
|
||||
EXPECTED_CERT_SHA256="$(
|
||||
sed -n 's/^BITCHAT_GITHUB_RELEASE_CERT_SHA256=//p' "$PROJECT_ROOT/gradle.properties" |
|
||||
tr -d ':\r[:space:]' |
|
||||
tr '[:upper:]' '[:lower:]'
|
||||
)"
|
||||
if ! [[ "$EXPECTED_CERT_SHA256" =~ ^[a-f0-9]{64}$ ]]; then
|
||||
echo "error: expected GitHub release certificate fingerprint is invalid" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_DIR"' EXIT
|
||||
KEYSTORE="$TEMP_DIR/release.jks"
|
||||
|
||||
if base64 --help 2>&1 | grep -q -- '--decode'; then
|
||||
printf '%s' "$BITCHAT_SIGNING_KEY_BASE64" | base64 --decode > "$KEYSTORE"
|
||||
else
|
||||
printf '%s' "$BITCHAT_SIGNING_KEY_BASE64" | base64 -D > "$KEYSTORE"
|
||||
fi
|
||||
chmod 600 "$KEYSTORE"
|
||||
|
||||
export BITCHAT_KEYSTORE_PASSWORD
|
||||
export BITCHAT_KEY_PASSWORD
|
||||
|
||||
declare -A signed_names=(
|
||||
["bitchat-android-arm64-unsigned.apk"]="bitchat-android-arm64.apk"
|
||||
["bitchat-android-universal-unsigned.apk"]="bitchat-android-universal.apk"
|
||||
["bitchat-android-x86_64-unsigned.apk"]="bitchat-android-x86_64.apk"
|
||||
)
|
||||
|
||||
for unsigned_name in "${!signed_names[@]}"; do
|
||||
unsigned_apk="$RELEASE_DIR/$unsigned_name"
|
||||
signed_apk="$RELEASE_DIR/${signed_names[$unsigned_name]}"
|
||||
first_signed="$TEMP_DIR/first.apk"
|
||||
second_signed="$TEMP_DIR/second.apk"
|
||||
|
||||
"$ZIPALIGN" -c -P 16 4 "$unsigned_apk"
|
||||
|
||||
for output_apk in "$first_signed" "$second_signed"; do
|
||||
"$APKSIGNER" sign \
|
||||
--ks "$KEYSTORE" \
|
||||
--ks-key-alias "$BITCHAT_SIGNING_KEY_ALIAS" \
|
||||
--ks-pass env:BITCHAT_KEYSTORE_PASSWORD \
|
||||
--key-pass env:BITCHAT_KEY_PASSWORD \
|
||||
--deterministic-dsa-signing true \
|
||||
--min-sdk-version 26 \
|
||||
--v1-signing-enabled false \
|
||||
--v2-signing-enabled true \
|
||||
--v3-signing-enabled true \
|
||||
--v4-signing-enabled false \
|
||||
--out "$output_apk" \
|
||||
"$unsigned_apk"
|
||||
done
|
||||
|
||||
if ! cmp -s "$first_signed" "$second_signed"; then
|
||||
echo "error: signing is not deterministic for $unsigned_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mv "$first_signed" "$signed_apk"
|
||||
actual_cert_sha256="$(
|
||||
"$APKSIGNER" verify --print-certs "$signed_apk" |
|
||||
sed -n 's/.*certificate SHA-256 digest: //p' |
|
||||
head -1 |
|
||||
tr -d ':\r[:space:]' |
|
||||
tr '[:upper:]' '[:lower:]'
|
||||
)"
|
||||
if [ "$actual_cert_sha256" != "$EXPECTED_CERT_SHA256" ]; then
|
||||
echo "error: signing certificate fingerprint mismatch" >&2
|
||||
exit 1
|
||||
fi
|
||||
"$APKSIGNER" verify --verbose "$signed_apk" >/dev/null
|
||||
rm -f "$second_signed"
|
||||
done
|
||||
|
||||
(
|
||||
cd "$RELEASE_DIR"
|
||||
{
|
||||
for artifact in *; do
|
||||
[ "$artifact" = "SHA256SUMS" ] && continue
|
||||
[ -f "$artifact" ] || continue
|
||||
sha256sum "$artifact"
|
||||
done
|
||||
} | sort -k2 > SHA256SUMS
|
||||
)
|
||||
|
||||
echo "Verified unsigned APKs were deterministically signed and checksummed."
|
||||
80
tools/reproducible-builds/verify-github-release.sh
Executable file
80
tools/reproducible-builds/verify-github-release.sh
Executable file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
TAG="${1:?usage: verify-github-release.sh TAG [--no-rebuild]}"
|
||||
MODE="${2:-}"
|
||||
REPOSITORY="${BITCHAT_GITHUB_REPOSITORY:-permissionlesstech/bitchat-android}"
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_DIR"' EXIT
|
||||
|
||||
if ! [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "error: release tag must look like vX.Y.Z" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$MODE" ] && [ "$MODE" != "--no-rebuild" ]; then
|
||||
echo "error: unknown option: $MODE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v gh >/dev/null 2>&1; then
|
||||
echo "error: gh is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
SHA256=(sha256sum)
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
SHA256=(shasum -a 256)
|
||||
else
|
||||
echo "error: sha256sum or shasum is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOWNLOAD_DIR="$TEMP_DIR/github"
|
||||
mkdir -p "$DOWNLOAD_DIR"
|
||||
gh release download "$TAG" \
|
||||
--repo "$REPOSITORY" \
|
||||
--dir "$DOWNLOAD_DIR" \
|
||||
--pattern 'BITCHAT_BUILDINFO.json' \
|
||||
--pattern 'BITCHAT_SHA256SUMS' \
|
||||
--pattern 'BITCHAT_SHA256SUMS.unsigned' \
|
||||
--pattern 'bitchat-android-*.apk' \
|
||||
--pattern 'bitchat-android-*.aab'
|
||||
|
||||
for artifact in "$DOWNLOAD_DIR"/*; do
|
||||
gh attestation verify "$artifact" --repo "$REPOSITORY" >/dev/null
|
||||
done
|
||||
echo "GitHub provenance attestations verified."
|
||||
|
||||
(
|
||||
cd "$DOWNLOAD_DIR"
|
||||
"${SHA256[@]}" -c BITCHAT_SHA256SUMS
|
||||
)
|
||||
echo "GitHub release checksums verified."
|
||||
|
||||
mv "$DOWNLOAD_DIR/BITCHAT_BUILDINFO.json" "$DOWNLOAD_DIR/BUILDINFO.json"
|
||||
mv "$DOWNLOAD_DIR/BITCHAT_SHA256SUMS" "$DOWNLOAD_DIR/SHA256SUMS"
|
||||
mv "$DOWNLOAD_DIR/BITCHAT_SHA256SUMS.unsigned" "$DOWNLOAD_DIR/SHA256SUMS.unsigned"
|
||||
|
||||
if [ "$MODE" = "--no-rebuild" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
release_commit="$(sed -n 's/.*"sourceCommit": *"\([^"]*\)".*/\1/p' "$DOWNLOAD_DIR/BUILDINFO.json")"
|
||||
local_commit="$(git -C "$PROJECT_ROOT" rev-parse HEAD)"
|
||||
if [ "$release_commit" != "$local_commit" ]; then
|
||||
echo "error: check out release commit $release_commit before rebuilding" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOCAL_DIR="$PROJECT_ROOT/.reproducible-build/verify-$TAG"
|
||||
if [ -e "$LOCAL_DIR" ]; then
|
||||
echo "error: local verification output already exists: $LOCAL_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$SCRIPT_DIR/build-in-container.sh" "$LOCAL_DIR"
|
||||
"$SCRIPT_DIR/compare-release.sh" "$LOCAL_DIR" "$DOWNLOAD_DIR"
|
||||
echo "GitHub release $TAG was reproduced successfully from source."
|
||||
35
tools/reproducible-builds/verify-no-host-paths.sh
Executable file
35
tools/reproducible-builds/verify-no-host-paths.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ARTIFACT_DIR="${1:?usage: verify-no-host-paths.sh ARTIFACT_DIR}"
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_DIR"' EXIT
|
||||
|
||||
archive_index=0
|
||||
for artifact in "$ARTIFACT_DIR"/*.apk "$ARTIFACT_DIR"/*.aab; do
|
||||
[ -f "$artifact" ] || continue
|
||||
archive_index=$((archive_index + 1))
|
||||
archive_dir="$TEMP_DIR/$archive_index"
|
||||
mkdir -p "$archive_dir"
|
||||
if command -v unzip >/dev/null 2>&1; then
|
||||
unzip -qq "$artifact" 'lib/*/*.so' 'base/lib/*/*.so' -d "$archive_dir" 2>/dev/null || true
|
||||
elif command -v jar >/dev/null 2>&1; then
|
||||
(
|
||||
cd "$archive_dir"
|
||||
jar xf "$artifact"
|
||||
)
|
||||
else
|
||||
echo "error: unzip or jar is required to inspect release artifacts" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
while IFS= read -r -d '' library; do
|
||||
if strings "$library" | grep -Eq '/Users/|/home/|[A-Za-z]:\\\\Users\\\\'; then
|
||||
echo "error: host-specific path detected in a release artifact" >&2
|
||||
exit 1
|
||||
fi
|
||||
done < <(find "$TEMP_DIR" -type f -name '*.so' -print0)
|
||||
|
||||
echo "Release artifacts contain no host-specific native paths."
|
||||
Loading…
x
Reference in New Issue
Block a user