diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml
index 7df4d792c..d59a92417 100644
--- a/.github/workflows/android-build.yml
+++ b/.github/workflows/android-build.yml
@@ -27,6 +27,39 @@ jobs:
ndk-version: r28c
link-to-sdk: true
local-cache: true
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Check formatting using spotless
uses: gradle/actions/setup-gradle@v3
with:
@@ -42,6 +75,39 @@ jobs:
with:
distribution: "temurin"
java-version: 17
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
diff --git a/.github/workflows/android-debug-artifact-ondemand.yml b/.github/workflows/android-debug-artifact-ondemand.yml
index 39eefaa4a..4dd72ba16 100644
--- a/.github/workflows/android-debug-artifact-ondemand.yml
+++ b/.github/workflows/android-debug-artifact-ondemand.yml
@@ -46,6 +46,39 @@ jobs:
ndk-version: r28c
link-to-sdk: true
local-cache: true
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
diff --git a/.github/workflows/android-debug-artifact-release.yml b/.github/workflows/android-debug-artifact-release.yml
index d4052fdd1..e837df793 100644
--- a/.github/workflows/android-debug-artifact-release.yml
+++ b/.github/workflows/android-debug-artifact-release.yml
@@ -20,6 +20,39 @@ jobs:
ndk-version: r28c
link-to-sdk: true
local-cache: true
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
diff --git a/.github/workflows/android-feature.yml b/.github/workflows/android-feature.yml
old mode 100644
new mode 100755
index abb78f30f..23aca0ec1
--- a/.github/workflows/android-feature.yml
+++ b/.github/workflows/android-feature.yml
@@ -23,6 +23,7 @@ jobs:
distribution: "temurin"
java-version: 17
- name: Set up NDK
+ id: setup-ndk
uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410
with:
ndk-version: r28c
@@ -32,6 +33,8 @@ jobs:
uses: gradle/actions/setup-gradle@v3
with:
arguments: spotlessCheck --stacktrace
+ env:
+ ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
build:
name: Build debug and run Jacoco tests
@@ -43,6 +46,39 @@ jobs:
with:
distribution: "temurin"
java-version: 17
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
diff --git a/.github/workflows/android-main.yml b/.github/workflows/android-main.yml
index 18f7e5531..ea0959f7a 100644
--- a/.github/workflows/android-main.yml
+++ b/.github/workflows/android-main.yml
@@ -45,6 +45,39 @@ jobs:
with:
distribution: "temurin"
java-version: 17
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ - name: Cache Rust dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ file_operations/target/
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-
+ - name: Setup Rust for Android
+ run: |
+ cd file_operations
+ chmod +x setup_rust_android.sh
+ ./setup_rust_android.sh
+ - name: Verify Rust setup
+ run: |
+ cd file_operations
+ echo "🔍 Verifying Rust Android targets..."
+ rustup target list --installed | grep android || echo "No Android targets found"
+ echo "🔍 Verifying cargo configuration..."
+ if [ -f .cargo/config.toml ]; then
+ echo "✅ .cargo/config.toml exists"
+ else
+ echo "❌ .cargo/config.toml missing"
+ exit 1
+ fi
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ce87f0623..180c4af72 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,6 +38,7 @@ If we feel your PR is a significant help to us, we'll award you a bounty with an
- Please follow [Android/JAVA code style](https://source.android.com/docs/setup/contribute/code-style) for writing any code. Please see [this](https://github.com/TeamAmaze/AmazeFileManager/issues/986) issue too.
- Also, follow [Android Material Design guidelines](https://m3.material.io/get-started) in case you make changes to any UI element.
+ - The `file_operations` module contains native code in Rust. Please see [file_operations/src/main/rust/README.md](file_operations/src/main/rust/README.md) for more details on how to work with it.
## PS: please make sure to
diff --git a/build.gradle b/build.gradle
index 81bda2e8f..379e3c33b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,7 @@ buildscript {
classpath libs.kotlin.gradle.plugin
classpath libs.easylauncher
classpath libs.jacoco.android.plugin
+ classpath libs.rust.android.gradle
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
diff --git a/file_operations/.cargo/config.toml.template b/file_operations/.cargo/config.toml.template
new file mode 100644
index 000000000..306ec4642
--- /dev/null
+++ b/file_operations/.cargo/config.toml.template
@@ -0,0 +1,24 @@
+# Cargo configuration for Android cross-compilation
+# This file configures the linkers for different Android architectures
+# Generated from config.toml.template by setup_rust_android.sh
+
+[target.aarch64-linux-android]
+linker = "{{NDK_PATH}}/aarch64-linux-android{{API_LEVEL}}-clang{{EXE_SUFFIX}}"
+
+[target.armv7-linux-androideabi]
+linker = "{{NDK_PATH}}/armv7a-linux-androideabi{{API_LEVEL}}-clang{{EXE_SUFFIX}}"
+
+[target.i686-linux-android]
+linker = "{{NDK_PATH}}/i686-linux-android{{API_LEVEL}}-clang{{EXE_SUFFIX}}"
+
+[target.x86_64-linux-android]
+linker = "{{NDK_PATH}}/x86_64-linux-android{{API_LEVEL}}-clang{{EXE_SUFFIX}}"
+
+# Note: This file is auto-generated. Do not edit manually.
+# To regenerate, run: ./setup_rust_android.sh
+#
+# Configuration details:
+# - API level: {{API_LEVEL}} (matching minSdkVersion from build.gradle)
+# - Platform: {{PLATFORM}}
+# - NDK version: {{NDK_VERSION}}
+# - Android SDK: {{ANDROID_SDK_PATH}}
\ No newline at end of file
diff --git a/file_operations/.gitignore b/file_operations/.gitignore
index ed6456e9a..f2869aa55 100644
--- a/file_operations/.gitignore
+++ b/file_operations/.gitignore
@@ -1,5 +1,11 @@
-/build
+# Rust build artifacts
+target/
+**/*.rs.bk
+Cargo.lock
-# External native build folder generated in Android Studio 2.2 and later
-.externalNativeBuild
-.cxx/
\ No newline at end of file
+# Auto-generated configuration (generated from template)
+.cargo/config.toml
+
+# Android build artifacts
+.cxx/
+build/
\ No newline at end of file
diff --git a/file_operations/Cargo.toml b/file_operations/Cargo.toml
new file mode 100644
index 000000000..7c2b53db8
--- /dev/null
+++ b/file_operations/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "rootoperations"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+name = "rootoperations"
+crate-type = ["cdylib"]
+path = "src/main/rust/lib.rs"
+
+[dependencies]
+jni = "0.21"
+libc = "0.2"
+
+[target.'cfg(target_os = "android")'.dependencies]
+android_logger = "0.11"
+log = "0.4"
\ No newline at end of file
diff --git a/file_operations/build.gradle b/file_operations/build.gradle
index 032d02250..5400d6445 100644
--- a/file_operations/build.gradle
+++ b/file_operations/build.gradle
@@ -1,10 +1,12 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.devtools.ksp'
+apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
android {
namespace "com.amaze.filemanager.fileoperations"
compileSdk libs.versions.compileSdk.get().toInteger()
+ ndkVersion libs.versions.ndk.get()
defaultConfig {
minSdkVersion libs.versions.minSdk.get().toInteger()
@@ -14,12 +16,6 @@ android {
consumerProguardFiles "consumer-rules.pro"
multiDexEnabled true
-
- externalNativeBuild {
- cmake {
- cFlags '-std=c11'
- }
- }
}
buildTypes {
@@ -46,21 +42,40 @@ android {
}
}
- externalNativeBuild {
- cmake {
- path file('src/main/c/CMakeLists.txt')
- }
- }
-
kotlinOptions {
jvmTarget = '17'
}
}
+// Rust configuration
+cargo {
+ module = "./"
+ libname = "rootoperations"
+ targets = ["arm", "arm64", "x86", "x86_64"]
+ profile = "release"
+
+ // Optional: Use cargo and rustc from the path
+ rustcCommand = "rustc"
+ cargoCommand = "cargo"
+ pythonCommand = "python3"
+}
+
kotlin {
jvmToolchain(17)
}
+// Ensure Rust libraries are built before Android tasks
+afterEvaluate {
+ android.libraryVariants.all { variant ->
+ variant.outputs.all { output ->
+ def buildTask = tasks.findByName("cargoBuild")
+ if (buildTask) {
+ tasks.getByName("merge${variant.name.capitalize()}JniLibFolders").dependsOn buildTask
+ }
+ }
+ }
+}
+
dependencies {
modules {
module("org.bouncycastle:bcprov-jdk15on") {
diff --git a/file_operations/doc/RUST_MIGRATION.md b/file_operations/doc/RUST_MIGRATION.md
new file mode 100644
index 000000000..2b92c0574
--- /dev/null
+++ b/file_operations/doc/RUST_MIGRATION.md
@@ -0,0 +1,277 @@
+# C++ to Rust Migration Guide
+
+This document outlines the migration from C++ to Rust in the `file_operations` module using Mozilla's Rust Android Gradle plugin.
+
+## Overview
+
+The migration replaces the C++ implementation in `src/main/c/rootoperations.c` with a Rust implementation while maintaining the same JNI interface for seamless integration with the existing Kotlin code.
+
+## What Was Migrated
+
+### Original C++ Code
+- **File**: `src/main/c/rootoperations.c`
+- **Function**: `Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isDirectory`
+- **Purpose**: Checks if a given path is a directory using the `stat()` system call
+- **Build System**: CMake
+
+### New Rust Code
+- **File**: `src/lib.rs`
+- **Function**: Same JNI function signature
+- **Purpose**: Identical functionality using Rust's `std::fs::metadata()`
+- **Build System**: Cargo with Mozilla's Rust Android Gradle plugin
+
+## Prerequisites
+
+1. **Rust Installation**: Install Rust from https://rustup.rs/
+2. **Android NDK**: Install via Android Studio → Tools → SDK Manager → SDK Tools → NDK
+3. **Environment Variables**: Set `ANDROID_HOME` or `ANDROID_NDK_ROOT`
+4. **Rust-compatible IDE**: Before Android Studio gets first-class Rust support, consider using [Visual Studio Code](https://code.visualstudio.com) with Rust extensions for coding.
+
+## Setup Instructions
+
+### 1. Automated Setup (Recommended)
+
+The project includes an automated setup script that detects your system configuration and generates the correct configuration files:
+
+```bash
+cd file_operations
+./setup_rust_android.sh
+```
+
+This script will:
+- **Auto-detect your operating system** (macOS, Linux, Windows)
+- **Find your Android SDK** path (from `ANDROID_HOME`, `ANDROID_SDK_ROOT`, or common locations)
+- **Detect the latest NDK version** installed
+- **Extract API level** from your `build.gradle`
+- **Install necessary Rust targets** for Android
+- **Generate `.cargo/config.toml`** with correct linker paths
+
+### 2. Manual Setup (If Needed)
+
+If the automated setup doesn't work, you can manually configure:
+
+1. **Install Android Rust targets:**
+ ```bash
+ rustup target add aarch64-linux-android
+ rustup target add armv7-linux-androideabi
+ rustup target add i686-linux-android
+ rustup target add x86_64-linux-android
+ ```
+
+2. **Create `.cargo/config.toml`** based on your system:
+ - Copy `.cargo/config.toml.template` to `.cargo/config.toml`
+ - Replace placeholders with your actual paths:
+ - `{{NDK_PATH}}`: Path to your NDK toolchain binaries
+ - `{{API_LEVEL}}`: Your minimum API level (e.g., 21)
+ - `{{EXE_SUFFIX}}`: `.exe` for Windows, empty for Unix systems
+
+### 3. System Requirements
+
+**Android SDK/NDK:**
+- Android SDK installed (via Android Studio or command-line tools)
+- NDK installed (via SDK Manager)
+- Set `ANDROID_HOME` environment variable
+
+**Supported Platforms:**
+- macOS (`darwin-x86_64`)
+- Linux (`linux-x86_64`)
+- Windows (`windows-x86_64`)
+
+### 4. Build Configuration
+
+The `build.gradle` file now includes:
+- Mozilla's Rust Android Gradle plugin
+- Cargo configuration for cross-compilation
+- Automatic building of Rust code during Android build
+
+## File Structure
+
+```
+file_operations/
+├── src/
+│ └── main/
+│ └── rust/
+│ ├── lib.rs # Main library file (module organizer)
+│ └── rootoperations.rs # Root operations functions
+├── .cargo/
+│ ├── config.toml # Auto-generated Cargo configuration for Android
+│ └── config.toml.template # Template for generating config.toml
+├── Cargo.toml # Rust project configuration
+├── setup_rust_android.sh # Automated setup script
+├── build.gradle # Updated with Rust plugin
+└── RUST_MIGRATION.md # This file
+```
+
+## Key Changes
+
+### 1. Build System
+- **Before**: CMake with `externalNativeBuild`
+- **After**: Cargo with Mozilla's Rust Android Gradle plugin
+
+### 2. Dependencies
+- **Added**: `jni`, `libc`, `android_logger`, `log` crates
+- **Removed**: CMake build configuration
+
+### 3. Function Implementation
+- **Before**: C function using `stat()` system call
+- **After**: Rust function using `std::fs::metadata()`
+
+### 4. Error Handling
+- **Before**: errno-based error handling
+- **After**: Rust's `Result` type with proper error handling
+
+### 5. Modular Structure
+- **Before**: Single C file with all functions
+- **After**: Organized module structure:
+ - `lib.rs`: Main library file that organizes and re-exports modules
+ - `rootoperations.rs`: Root-specific operations (migrated from C)
+
+## Testing
+
+The Rust implementation includes unit tests:
+```bash
+cd file_operations
+cargo test
+```
+
+## Building
+
+The Rust code is automatically built when you build the Android project:
+```bash
+./gradlew :file_operations:build
+```
+
+## Advantages of the Migration
+
+1. **Memory Safety**: Rust prevents memory leaks and buffer overflows
+2. **Better Error Handling**: Rust's type system catches errors at compile time
+3. **Cross-Platform**: Easier to port to other platforms
+4. **Modern Tooling**: Cargo package manager and ecosystem
+5. **Performance**: Comparable performance to C++ with better safety
+
+## Troubleshooting
+
+### Configuration Issues
+First, try re-running the automated setup script:
+```bash
+cd file_operations
+./setup_rust_android.sh
+```
+
+This will re-detect your system configuration and regenerate `.cargo/config.toml`.
+
+### NDK Path Issues
+If the automated setup fails to find your NDK, ensure your Android SDK is properly configured:
+```bash
+export ANDROID_HOME=/path/to/android/sdk
+# The script will automatically find the NDK in $ANDROID_HOME/ndk/[version]
+```
+
+### Linker Not Found
+If you see linker errors, verify your NDK installation:
+1. Check that NDK is installed via Android Studio → SDK Manager → SDK Tools → NDK
+2. The setup script will automatically use the latest NDK version found
+3. If needed, manually verify the generated `.cargo/config.toml` paths exist
+
+### Build Errors
+Clean and rebuild:
+```bash
+cd file_operations
+cargo clean
+cd ..
+./gradlew clean
+./gradlew :file_operations:build
+```
+
+### Cross-Platform Issues
+The setup script supports:
+- **macOS**: Automatically detects `darwin-x86_64` platform
+- **Linux**: Automatically detects `linux-x86_64` platform
+- **Windows**: Automatically detects `windows-x86_64` platform and adds `.exe` suffix
+
+If you encounter platform-specific issues, check the generated linker paths in `.cargo/config.toml`.
+
+## Extending the Codebase
+
+The modular structure makes it easy to add new functionality:
+
+### Adding a New Module
+
+1. **Create a new `.rs` file** in `src/main/rust/` (e.g., `network_ops.rs`)
+2. **Add the module declaration** in `lib.rs`:
+ ```rust
+ pub mod network_ops;
+ ```
+3. **Re-export functions** in `lib.rs` for easy access:
+ ```rust
+ pub use network_ops::{
+ download_file,
+ upload_file,
+ };
+ ```
+
+### Adding JNI Functions
+
+To add new JNI functions that can be called from Kotlin:
+
+1. **Add the function** in the appropriate module:
+ ```rust
+ #[no_mangle]
+ pub extern "system" fn Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_newFunction(
+ env: JNIEnv,
+ _class: JClass,
+ param: JString,
+ ) -> jboolean {
+ // Implementation
+ }
+ ```
+
+2. **Add the corresponding method** in `NativeOperations.kt`:
+ ```kotlin
+ @JvmStatic
+ external fun newFunction(param: String?): Boolean
+ ```
+
+### Example: Adding Compression Operations
+
+```rust
+// In src/main/rust/compression_ops.rs
+pub mod compression_ops {
+ use jni::objects::{JClass, JString};
+ use jni::JNIEnv;
+ use jni::sys::jboolean;
+
+ #[no_mangle]
+ pub extern "system" fn Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_compressFile(
+ env: JNIEnv,
+ _class: JClass,
+ source: JString,
+ destination: JString,
+ ) -> jboolean {
+ // Implementation
+ }
+}
+```
+
+## Future Enhancements
+
+1. **Add More Functions**: Migrate additional C++ functions to Rust
+2. **Async Operations**: Use Rust's async/await for non-blocking operations
+3. **Better Logging**: Enhanced logging with structured logs
+4. **Performance Monitoring**: Add metrics collection
+5. **Cross-Platform Support**: Extend to other platforms (iOS, Windows, etc.)
+6. **Error Types**: Create custom error types for better error handling
+7. **Benchmarking**: Add performance benchmarks for critical operations
+
+## Resources
+
+- [Mozilla Rust Android Gradle Plugin](https://github.com/mozilla/rust-android-gradle)
+- [JNI for Rust](https://docs.rs/jni/latest/jni/)
+- [Android NDK Documentation](https://developer.android.com/ndk)
+- [Rust Cross-Compilation](https://rust-lang.github.io/rustup/cross-compilation.html)
+
+## Support
+
+For questions or issues with the migration, please refer to:
+- [Mozilla Rust Android Gradle Issues](https://github.com/mozilla/rust-android-gradle/issues)
+- [Rust Android Development](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html)
\ No newline at end of file
diff --git a/file_operations/setup_rust_android.sh b/file_operations/setup_rust_android.sh
new file mode 100755
index 000000000..132c3b955
--- /dev/null
+++ b/file_operations/setup_rust_android.sh
@@ -0,0 +1,182 @@
+#!/bin/bash
+
+# Setup script for Rust Android development
+# This script:
+# 1. Installs necessary Rust targets for Android
+# 2. Auto-detects system configuration
+# 3. Generates .cargo/config.toml with correct linker paths
+
+set -e
+
+echo "🦀 Setting up Rust for Android development..."
+
+# Function to detect operating system
+detect_os() {
+ case "$(uname -s)" in
+ Darwin*) echo "darwin-x86_64" ;;
+ Linux*) echo "linux-x86_64" ;;
+ CYGWIN*|MINGW*|MSYS*) echo "windows-x86_64" ;;
+ *) echo "unknown" ;;
+ esac
+}
+
+# Function to find Android SDK path
+find_android_sdk() {
+ if [ -n "$ANDROID_HOME" ]; then
+ echo "$ANDROID_HOME"
+ elif [ -n "$ANDROID_SDK_ROOT" ]; then
+ echo "$ANDROID_SDK_ROOT"
+ elif [ -d "$HOME/Android/Sdk" ]; then
+ echo "$HOME/Android/Sdk"
+ elif [ -d "$HOME/Library/Android/sdk" ]; then
+ echo "$HOME/Library/Android/sdk"
+ else
+ echo ""
+ fi
+}
+
+# Function to find the latest NDK version
+find_ndk_version() {
+ local sdk_path="$1"
+ local ndk_dir="$sdk_path/ndk"
+
+ if [ -d "$ndk_dir" ]; then
+ # Find the latest version (highest version number)
+ ls -1 "$ndk_dir" | sort -V | tail -n 1
+ else
+ echo ""
+ fi
+}
+
+# Function to extract API level from build.gradle and version catalog
+extract_api_level() {
+ local build_gradle="build.gradle"
+ local version_catalog="../gradle/libs.versions.toml"
+
+ # First, check if build.gradle uses version catalog
+ if [ -f "$build_gradle" ] && grep -q "libs.versions.minSdk" "$build_gradle"; then
+ # Extract from version catalog
+ if [ -f "$version_catalog" ]; then
+ grep "^minSdk" "$version_catalog" | cut -d '"' -f 2
+ else
+ echo "21" # Default fallback
+ fi
+ elif [ -f "$build_gradle" ]; then
+ # Look for direct minSdkVersion in build.gradle
+ grep -E "minSdkVersion|minSdk" "$build_gradle" | head -n 1 | sed 's/.*[[:space:]]\([0-9]\+\).*/\1/'
+ else
+ echo "21" # Default fallback
+ fi
+}
+
+# Detect system configuration
+OS_PLATFORM=$(detect_os)
+echo "📱 Detected OS: $OS_PLATFORM"
+
+if [ "$OS_PLATFORM" = "unknown" ]; then
+ echo "❌ Unsupported operating system. Please configure manually."
+ exit 1
+fi
+
+# Find Android SDK
+ANDROID_SDK_PATH=$(find_android_sdk)
+if [ -z "$ANDROID_SDK_PATH" ]; then
+ echo "❌ Android SDK not found. Please set ANDROID_HOME or ANDROID_SDK_ROOT environment variable."
+ echo " Or install Android SDK to ~/Android/Sdk (Linux) or ~/Library/Android/sdk (macOS)"
+ exit 1
+fi
+
+echo "📁 Found Android SDK: $ANDROID_SDK_PATH"
+
+# Find NDK version
+NDK_VERSION=$(find_ndk_version "$ANDROID_SDK_PATH")
+if [ -z "$NDK_VERSION" ]; then
+ echo "❌ NDK not found in $ANDROID_SDK_PATH/ndk"
+ echo " Please install NDK through Android Studio SDK Manager"
+ exit 1
+fi
+
+echo "🔨 Found NDK version: $NDK_VERSION"
+
+# Extract API level
+API_LEVEL=$(extract_api_level)
+echo "📋 Using API level: $API_LEVEL"
+
+# Set executable suffix for Windows
+EXE_SUFFIX=""
+if [ "$OS_PLATFORM" = "windows-x86_64" ]; then
+ EXE_SUFFIX=".exe"
+fi
+
+# Construct NDK path
+NDK_PATH="$ANDROID_SDK_PATH/ndk/$NDK_VERSION/toolchains/llvm/prebuilt/$OS_PLATFORM/bin"
+
+# Verify NDK path exists
+if [ ! -d "$NDK_PATH" ]; then
+ echo "❌ NDK toolchain not found at: $NDK_PATH"
+ echo " Please check your NDK installation"
+ exit 1
+fi
+
+echo "🛠️ NDK toolchain path: $NDK_PATH"
+
+# Install Rust targets for Android
+echo "📦 Installing Rust targets for Android..."
+rustup target add aarch64-linux-android
+rustup target add armv7-linux-androideabi
+rustup target add i686-linux-android
+rustup target add x86_64-linux-android
+
+# Create .cargo directory if it doesn't exist
+mkdir -p .cargo
+
+# Generate config.toml from template
+echo "⚙️ Generating .cargo/config.toml..."
+if [ ! -f ".cargo/config.toml.template" ]; then
+ echo "❌ Template file .cargo/config.toml.template not found"
+ exit 1
+fi
+
+# Use sed to replace placeholders in template
+sed -e "s|{{NDK_PATH}}|$NDK_PATH|g" \
+ -e "s|{{API_LEVEL}}|$API_LEVEL|g" \
+ -e "s|{{EXE_SUFFIX}}|$EXE_SUFFIX|g" \
+ -e "s|{{PLATFORM}}|$OS_PLATFORM|g" \
+ -e "s|{{NDK_VERSION}}|$NDK_VERSION|g" \
+ -e "s|{{ANDROID_SDK_PATH}}|$ANDROID_SDK_PATH|g" \
+ .cargo/config.toml.template > .cargo/config.toml
+
+echo "✅ Successfully generated .cargo/config.toml"
+
+# Verify generated linkers exist
+echo "🔍 Verifying linkers..."
+LINKERS=(
+ "aarch64-linux-android${API_LEVEL}-clang${EXE_SUFFIX}"
+ "armv7a-linux-androideabi${API_LEVEL}-clang${EXE_SUFFIX}"
+ "i686-linux-android${API_LEVEL}-clang${EXE_SUFFIX}"
+ "x86_64-linux-android${API_LEVEL}-clang${EXE_SUFFIX}"
+)
+
+for linker in "${LINKERS[@]}"; do
+ if [ -f "$NDK_PATH/$linker" ]; then
+ echo " ✅ $linker"
+ else
+ echo " ❌ $linker (not found)"
+ fi
+done
+
+echo ""
+echo "🎉 Rust Android setup complete!"
+echo ""
+echo "📋 Configuration summary:"
+echo " - OS Platform: $OS_PLATFORM"
+echo " - Android SDK: $ANDROID_SDK_PATH"
+echo " - NDK Version: $NDK_VERSION"
+echo " - API Level: $API_LEVEL"
+echo " - Config file: .cargo/config.toml"
+echo ""
+echo "🚀 You can now build for Android using:"
+echo " cargo build --target aarch64-linux-android"
+echo " cargo build --target armv7-linux-androideabi"
+echo " cargo build --target i686-linux-android"
+echo " cargo build --target x86_64-linux-android"
\ No newline at end of file
diff --git a/file_operations/src/main/AndroidManifest.xml b/file_operations/src/main/AndroidManifest.xml
index 1f08914bd..f71066fed 100644
--- a/file_operations/src/main/AndroidManifest.xml
+++ b/file_operations/src/main/AndroidManifest.xml
@@ -1,5 +1,2 @@
-
-
- /
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/file_operations/src/main/c/CMakeLists.txt b/file_operations/src/main/c/CMakeLists.txt
deleted file mode 100644
index a6a2a47fc..000000000
--- a/file_operations/src/main/c/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-# For more information about using CMake with Android Studio, read the
-# documentation: https://d.android.com/studio/projects/add-native-code.html
-
-cmake_minimum_required(VERSION 3.10.2)
-
-project("rootoperations")
-
-add_library(rootoperations SHARED rootoperations.c)
-
-find_library(log-lib log)
-
-target_link_libraries(rootoperations ${log-lib})
-target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
\ No newline at end of file
diff --git a/file_operations/src/main/c/rootoperations.c b/file_operations/src/main/c/rootoperations.c
deleted file mode 100644
index 2fcf855db..000000000
--- a/file_operations/src/main/c/rootoperations.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-
-JNIEXPORT jboolean JNICALL Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isDirectory(
- JNIEnv * env,
- jobject thiz,
- jstring path
- ) {
- struct stat path_stat;
- const char * cPath = (*env)->GetStringUTFChars(env, path, NULL);
- int returnCode = stat(cPath, &path_stat);
- (*env)->ReleaseStringUTFChars(env, path, cPath);
-
- if(returnCode == -1) {
- switch (errno) {
- case ELOOP:
- return true;
- default:
- return false;
- }
- }
-
- //This follows links
- return S_ISDIR(path_stat.st_mode);
-}
\ No newline at end of file
diff --git a/file_operations/src/main/rust/README.md b/file_operations/src/main/rust/README.md
new file mode 100644
index 000000000..bf01726e9
--- /dev/null
+++ b/file_operations/src/main/rust/README.md
@@ -0,0 +1,216 @@
+# Rust File Operations Module
+
+This directory contains the Rust implementation of file operations for the Amaze File Manager, which
+was migrated from C/C++ to Rust for more modern, maintainable more safe code, with Rust's inherent
+type-safety and memory-safety features.
+
+Please refer to [RUST_MIGRATION.md](../doc/RUST_MIGRATION.md) for detailed information
+about the migration process, key changes, and advantages of using Rust.
+
+## Module Structure
+
+The code is organized into separate modules for better maintainability and extensibility:
+
+### `lib.rs` - Main Library File
+- **Purpose**: Organizes and re-exports functionality from various modules
+- **Content**: Module declarations and re-exports for easy access
+- **Note**: This is the entry point for the Rust library
+
+### `rootoperations.rs` - Root Operations
+- **Purpose**: Contains root-specific file operations (migrated from C++)
+- **Functions**:
+ - `Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isDirectory` - JNI function for directory checking
+ - `check_is_directory` - Helper function to check if a path is a directory
+ - `check_path_exists` - Helper function to check if a path exists
+ - `check_is_file` - Helper function to check if a path is a file
+ - `get_file_size` - Helper function to get file size
+
+## Usage
+
+### From Kotlin/Java
+The JNI functions are automatically exported and can be called from Kotlin:
+
+```kotlin
+// In NativeOperations.kt
+@JvmStatic
+external fun isDirectory(path: String?): Boolean
+
+// Usage
+val isDir = NativeOperations.isDirectory("/some/path")
+```
+
+### From Rust (Internal)
+Functions can be called directly within the Rust codebase:
+
+```rust
+use crate::rootoperations::check_is_directory;
+
+let is_dir = check_is_directory("/some/path")?;
+```
+
+### Through Re-exports
+Functions can be accessed through the main library:
+
+```rust
+use crate::check_is_directory;
+
+let is_dir = check_is_directory("/some/path")?;
+```
+
+## Adding New Functionality
+
+### 1. Create a New Module
+Create a new `.rs` file (e.g., `network_ops.rs`):
+
+```rust
+// network_ops.rs
+pub fn download_file(url: &str, destination: &str) -> Result<(), Box> {
+ // Implementation
+ Ok(())
+}
+```
+
+### 2. Add Module Declaration
+In `lib.rs`, add the module declaration:
+
+```rust
+pub mod network_ops;
+```
+
+### 3. Re-export Functions (Optional)
+In `lib.rs`, add re-exports for easy access:
+
+```rust
+pub use network_ops::{
+ download_file,
+ upload_file,
+};
+```
+
+### 4. Add JNI Functions (If Needed)
+If you need to call the function from Kotlin:
+
+```rust
+// In network_ops.rs
+#[no_mangle]
+pub extern "system" fn Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_downloadFile(
+ env: JNIEnv,
+ _class: JClass,
+ url: JString,
+ destination: JString,
+) -> jboolean {
+ // Convert JString to Rust String
+ let url_str: String = env.get_string(url).unwrap().into();
+ let dest_str: String = env.get_string(destination).unwrap().into();
+
+ // Call the actual function
+ match download_file(&url_str, &dest_str) {
+ Ok(_) => 1, // true
+ Err(_) => 0, // false
+ }
+}
+```
+
+Then add the corresponding method in `NativeOperations.kt`:
+
+```kotlin
+@JvmStatic
+external fun downloadFile(url: String?, destination: String?): Boolean
+```
+
+## Testing
+
+Each module includes its own tests. Run tests with:
+
+```bash
+cd file_operations
+cargo test
+```
+
+To test a specific module:
+
+```bash
+cargo test rootoperations::tests
+```
+
+## Best Practices
+
+1. **Separation of Concerns**: Keep related functions in the same module
+2. **Error Handling**: Use `Result` for functions that can fail
+3. **Documentation**: Add doc comments to all public functions
+4. **Testing**: Include unit tests for all functions
+5. **JNI Safety**: Always handle JNI string conversion errors
+6. **Logging**: Use the `log` crate for debugging information
+
+## Example: Complete Function Implementation
+
+```rust
+// In your_module.rs
+use jni::objects::{JClass, JString};
+use jni::JNIEnv;
+use jni::sys::jboolean;
+
+/// Check if a file is executable
+pub fn is_executable(path: &str) -> Result> {
+ let path = std::path::Path::new(path);
+ let metadata = path.metadata()?;
+
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::PermissionsExt;
+ Ok(metadata.permissions().mode() & 0o111 != 0)
+ }
+
+ #[cfg(not(unix))]
+ {
+ // On non-Unix systems, check if it's a file with executable extension
+ Ok(path.extension()
+ .and_then(|ext| ext.to_str())
+ .map(|ext| matches!(ext.to_lowercase().as_str(), "exe" | "bat" | "cmd"))
+ .unwrap_or(false))
+ }
+}
+
+/// JNI function to check if a file is executable
+#[no_mangle]
+pub extern "system" fn Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isExecutable(
+ env: JNIEnv,
+ _class: JClass,
+ path: JString,
+) -> jboolean {
+ let path_str = match env.get_string(path) {
+ Ok(java_str) => java_str,
+ Err(_) => {
+ log::error!("Failed to get string from JString");
+ return 0;
+ }
+ };
+
+ let path_string: String = path_str.into();
+
+ match is_executable(&path_string) {
+ Ok(is_exec) => if is_exec { 1 } else { 0 },
+ Err(e) => {
+ log::error!("Error checking if file is executable: {}", e);
+ 0
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_is_executable() {
+ // Test with a known executable (on Unix systems)
+ #[cfg(unix)]
+ assert!(is_executable("/bin/ls").unwrap_or(false));
+
+ // Test with a non-executable file
+ assert!(!is_executable("/etc/passwd").unwrap_or(true));
+ }
+}
+```
+
+This structure makes the codebase highly maintainable and easy to extend with new functionality while keeping everything organized and well-tested.
\ No newline at end of file
diff --git a/file_operations/src/main/rust/lib.rs b/file_operations/src/main/rust/lib.rs
new file mode 100644
index 000000000..d7d7fd8a5
--- /dev/null
+++ b/file_operations/src/main/rust/lib.rs
@@ -0,0 +1,29 @@
+// Main library file for the Rust file operations module
+// This file organizes and re-exports functionality from various modules
+
+// Module declarations
+pub mod rootoperations;
+
+// Re-export commonly used functions for easier access
+pub use rootoperations::{
+ check_is_directory,
+ check_path_exists,
+ check_is_file,
+ get_file_size,
+};
+
+// The JNI functions are automatically exported due to #[no_mangle] in their respective modules
+// No need to re-export them here as they're called directly by the JVM
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_module_integration() {
+ // Test that we can access rootoperations functions through re-exports
+ assert!(check_path_exists("/").unwrap_or(false));
+ assert!(check_is_directory("/").unwrap_or(false));
+ assert!(!check_is_file("/").unwrap_or(true));
+ }
+}
\ No newline at end of file
diff --git a/file_operations/src/main/rust/rootoperations.rs b/file_operations/src/main/rust/rootoperations.rs
new file mode 100644
index 000000000..d7bae5da5
--- /dev/null
+++ b/file_operations/src/main/rust/rootoperations.rs
@@ -0,0 +1,174 @@
+use jni::objects::{JClass, JString};
+use jni::JNIEnv;
+use jni::sys::jboolean;
+use std::path::Path;
+use std::sync::Once;
+
+#[cfg(target_os = "android")]
+use android_logger::Config;
+
+#[cfg(target_os = "android")]
+use log;
+
+// Per Copilot review suggested, use Once::new to make Android logging init only once
+static INIT: Once = Once::new();
+
+/// Initialize Android logging (optional, but useful for debugging)
+#[cfg(target_os = "android")]
+fn init_logging() {
+ INIT.call_once(|| {
+ android_logger::init_once(
+ Config::default()
+ .with_min_level(log::Level::Debug)
+ .with_tag("RustRootOperations")
+ );
+ });
+}
+
+/// Log error message (Android only)
+#[cfg(target_os = "android")]
+fn log_error(msg: &str) {
+ log::error!("{}", msg);
+}
+
+/// Log error message (non-Android platforms)
+#[cfg(not(target_os = "android"))]
+fn log_error(msg: &str) {
+ eprintln!("ERROR: {}", msg);
+}
+
+/// JNI function to check if a path is a directory
+/// This replaces the C function: Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isDirectory
+#[unsafe(no_mangle)]
+pub extern "system" fn Java_com_amaze_filemanager_fileoperations_filesystem_root_NativeOperations_isDirectory(
+ mut env: JNIEnv,
+ _class: JClass,
+ path: JString,
+) -> jboolean {
+ #[cfg(target_os = "android")]
+ init_logging();
+
+ // Convert the JString to a Rust string
+ let path_str = match env.get_string(&path) {
+ Ok(java_str) => java_str,
+ Err(_) => {
+ log_error("Failed to get string from JString");
+ return 0; // false
+ }
+ };
+
+ let path_string: String = path_str.into();
+
+ // Check if the path is a directory using Rust's standard library
+ match check_is_directory(&path_string) {
+ Ok(is_dir) => {
+ if is_dir { 1 } else { 0 } // true : false
+ }
+ Err(e) => {
+ log_error(&format!("Error checking if path is directory: {}", e));
+ 0 // false on error
+ }
+ }
+}
+
+/// Helper function to check if a path is a directory
+/// This replicates the logic from the original C code
+pub fn check_is_directory(path: &str) -> Result> {
+ let path = Path::new(path);
+
+ match path.metadata() {
+ Ok(metadata) => {
+ Ok(metadata.is_dir())
+ }
+ Err(e) => {
+ use std::io::ErrorKind;
+ match e.kind() {
+ ErrorKind::NotFound => Ok(false),
+ ErrorKind::PermissionDenied => Ok(false),
+ _ => {
+ // For other errors, we'll return false similar to the C code
+ // The original C code had special handling for ELOOP (too many symbolic links)
+ // which would return true, but Rust's std::fs handles this differently
+ Ok(false)
+ }
+ }
+ }
+ }
+}
+
+/// Helper function to check if a path exists
+/// This can be used for future extensions
+pub fn check_path_exists(path: &str) -> Result> {
+ let path = Path::new(path);
+ Ok(path.exists())
+}
+
+/// Helper function to check if a path is a file
+/// This can be used for future extensions
+pub fn check_is_file(path: &str) -> Result> {
+ let path = Path::new(path);
+
+ match path.metadata() {
+ Ok(metadata) => {
+ Ok(metadata.is_file())
+ }
+ Err(e) => {
+ use std::io::ErrorKind;
+ match e.kind() {
+ ErrorKind::NotFound => Ok(false),
+ ErrorKind::PermissionDenied => Ok(false),
+ _ => Ok(false)
+ }
+ }
+ }
+}
+
+/// Helper function to get file size
+/// This can be used for future extensions
+pub fn get_file_size(path: &str) -> Result> {
+ let path = Path::new(path);
+
+ match path.metadata() {
+ Ok(metadata) => {
+ Ok(metadata.len())
+ }
+ Err(e) => {
+ Err(Box::new(e))
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_check_is_directory() {
+ // Test with a known directory
+ assert!(check_is_directory("/tmp").unwrap_or(false));
+
+ // Test with a non-existent path
+ assert!(!check_is_directory("/this/path/does/not/exist").unwrap_or(true));
+
+ // Test with root directory
+ assert!(check_is_directory("/").unwrap_or(false));
+ }
+
+ #[test]
+ fn test_check_path_exists() {
+ // Test with root directory (should exist)
+ assert!(check_path_exists("/").unwrap_or(false));
+
+ // Test with non-existent path
+ assert!(!check_path_exists("/this/path/does/not/exist").unwrap_or(true));
+ }
+
+ #[test]
+ fn test_check_is_file() {
+ // Test with a directory (should return false)
+ assert!(!check_is_file("/").unwrap_or(true));
+
+ // Test with non-existent path
+ assert!(!check_is_file("/this/path/does/not/exist").unwrap_or(true));
+ }
+}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 9f17f76df..e475d17e4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -3,7 +3,7 @@ compileSdk = "34"
minSdk = "21"
targetSdk = "35"
kotlin = "1.9.25"
-ndk = "28.2.13676358"
+ndk = "28.2.13676358" #r28c
jacocoAndroid = "0.2.1"
gradle = "8.5.2"
@@ -35,7 +35,7 @@ androidXTestRunner = "1.6.2"
androidXTestExt = "1.2.1"
androidXArchCoreTest = "2.2.0"
androidXMultidex = "2.0.1"
-autoService = "1.0-rc4"
+autoService = "1.1.1"
kotlinxCoroutineTest = "1.7.3"
kotlinStdlibJdk8 = "1.9.20"
uiAutomator = "2.3.0"
@@ -73,11 +73,13 @@ mpAndroidChart = "v3.0.2"
concurrentTrees = "2.6.1"
aboutLibraries = "6.1.1"
amazeTrashBin = "1.0.10"
+rustAndroidGradle = "0.9.6"
[libraries]
gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
jacoco-android-plugin = { module = "com.mxalbert.gradle:jacoco-android", version.ref = "jacocoAndroid" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
+rust-android-gradle = { module = "org.mozilla.rust-android-gradle.rust-android:org.mozilla.rust-android-gradle.rust-android.gradle.plugin", version.ref = "rustAndroidGradle" }
androidX-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidXAppCompat" }
androidX-constraintLayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidXConstraintLayout" }