diff --git a/app/build.gradle b/app/build.gradle index 30de9017..118b6e7c 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -98,6 +98,7 @@ dependencies { implementation project(":domain") implementation project(":feature:auth") implementation project(":feature:diffusion") + implementation project(":feature:sdxl") implementation project(":feature:work") implementation project(":data") implementation project(":demo") @@ -110,6 +111,7 @@ dependencies { implementation ui.catppuccinSplashscreen implementation ui.catppuccinLegacy implementation androidx.workManager + implementation "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" } kapt { diff --git a/app/src/dev/AndroidManifest.xml b/app/src/dev/AndroidManifest.xml index 5e2a44ae..fc608372 100755 --- a/app/src/dev/AndroidManifest.xml +++ b/app/src/dev/AndroidManifest.xml @@ -14,6 +14,7 @@ + + + + + - + tools:node="remove"> + + diff --git a/app/src/main/java/com/shifthackz/aisdv1/app/AiStableDiffusionClientApp.kt b/app/src/main/java/com/shifthackz/aisdv1/app/AiStableDiffusionClientApp.kt index f298327a..d8aa1996 100755 --- a/app/src/main/java/com/shifthackz/aisdv1/app/AiStableDiffusionClientApp.kt +++ b/app/src/main/java/com/shifthackz/aisdv1/app/AiStableDiffusionClientApp.kt @@ -18,6 +18,7 @@ import com.shifthackz.aisdv1.core.validation.di.validatorsModule import com.shifthackz.aisdv1.data.di.dataModule import com.shifthackz.aisdv1.demo.di.demoModule import com.shifthackz.aisdv1.domain.di.domainModule +import com.shifthackz.aisdv1.feature.sdxl.TmuxStub import com.shifthackz.aisdv1.network.di.networkModule import com.shifthackz.aisdv1.presentation.di.presentationModule import com.shifthackz.aisdv1.storage.di.databaseModule @@ -38,6 +39,7 @@ class AiStableDiffusionClientApp : Application() { initializeLogging() initializeCursorSize() initializeWorkManager() + TmuxStub().stub1(this) } /** diff --git a/feature/sdxl/.gitignore b/feature/sdxl/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/sdxl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/sdxl/build.gradle b/feature/sdxl/build.gradle new file mode 100644 index 00000000..c6389b27 --- /dev/null +++ b/feature/sdxl/build.gradle @@ -0,0 +1,15 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +apply from: "$project.rootDir/gradle/common.gradle" + +android { + namespace 'com.shifthackz.aisdv1.feature.sdxl' +} + +dependencies { + implementation project(":core:common") + implementation "com.github.termux:termux-app:v0.118.0" +} diff --git a/feature/sdxl/consumer-rules.pro b/feature/sdxl/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/sdxl/proguard-rules.pro b/feature/sdxl/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/sdxl/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/sdxl/src/main/AndroidManifest.xml b/feature/sdxl/src/main/AndroidManifest.xml new file mode 100644 index 00000000..44008a43 --- /dev/null +++ b/feature/sdxl/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/PluginResultsService.kt b/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/PluginResultsService.kt new file mode 100644 index 00000000..caf7afde --- /dev/null +++ b/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/PluginResultsService.kt @@ -0,0 +1,58 @@ +package com.shifthackz.aisdv1.feature.sdxl + +import android.app.IntentService +import android.content.Intent +import android.util.Log +import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE + + +class PluginResultsService : IntentService(PLUGIN_SERVICE_LABEL) { + override fun onHandleIntent(intent: Intent?) { + if (intent == null) return + + Log.d(LOG_TAG, PLUGIN_SERVICE_LABEL + " received execution result") + + val resultBundle = intent.getBundleExtra(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE) + if (resultBundle == null) { + Log.e( + LOG_TAG, + "The intent does not contain the result bundle at the \"" + TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE + "\" key." + ) + return + } + + val executionId = intent.getIntExtra(EXTRA_EXECUTION_ID, 0) + + Log.d( + LOG_TAG, + """Execution id $executionId result: +stdout: +``` +${resultBundle.getString(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT, "")} +``` +stdout_original_length: `${resultBundle.getString(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT_ORIGINAL_LENGTH)}` +stderr: +``` +${resultBundle.getString(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDERR, "")} +``` +stderr_original_length: `${resultBundle.getString(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDERR_ORIGINAL_LENGTH)}` +exitCode: `${resultBundle.getInt(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_EXIT_CODE)}` +errCode: `${resultBundle.getInt(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_ERR)}` +errmsg: `${resultBundle.getString(TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_ERRMSG, "")}`""" + ) + } + + companion object { + const val EXTRA_EXECUTION_ID: String = "execution_id" + + private var EXECUTION_ID = 1000 + + const val PLUGIN_SERVICE_LABEL: String = "PluginResultsService" + + private const val LOG_TAG = "PluginResultsService" + + @get:Synchronized + val nextExecutionId: Int + get() = EXECUTION_ID++ + } +} \ No newline at end of file diff --git a/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/TmuxStub.kt b/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/TmuxStub.kt new file mode 100644 index 00000000..53abde79 --- /dev/null +++ b/feature/sdxl/src/main/java/com/shifthackz/aisdv1/feature/sdxl/TmuxStub.kt @@ -0,0 +1,108 @@ +package com.shifthackz.aisdv1.feature.sdxl + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import android.util.Log +import com.shifthackz.aisdv1.core.common.log.debugLog +import com.termux.shared.models.ExecutionCommand +import com.termux.shared.shell.TermuxShellEnvironmentClient +import com.termux.shared.shell.TermuxTask +import com.termux.shared.termux.TermuxConstants +import com.termux.shared.termux.TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE + + +class TmuxStub { + + fun stub1(context: Context) { + val LOG_TAG = "MainActivity" + + val intent = Intent() + intent.setClassName( + TermuxConstants.TERMUX_PACKAGE_NAME, + TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE_NAME + ) + intent.setAction(RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND) + intent.putExtra( + RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH, + "/data/data/com.termux/files/usr/bin/top" + ) + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_ARGUMENTS, arrayOf("-n", "2")) + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_WORKDIR, "/data/data/com.termux/files/home") + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_BACKGROUND, false) + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_SESSION_ACTION, "0") + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_COMMAND_LABEL, "top command") + intent.putExtra( + RUN_COMMAND_SERVICE.EXTRA_COMMAND_DESCRIPTION, + "Runs the top command to show processes using the most resources." + ) + + +// Create the intent for the IntentService class that should be sent the result by TermuxService + val pluginResultsServiceIntent = Intent( + context, + PluginResultsService::class.java + ) + + +// Generate a unique execution id for this execution command + val executionId: Int = PluginResultsService.nextExecutionId + + +// Optional put an extra that uniquely identifies the command internally for your app. +// This can be an Intent extra as well with more extras instead of just an int. + pluginResultsServiceIntent.putExtra(PluginResultsService.EXTRA_EXECUTION_ID, executionId) + + +// Create the PendingIntent that will be used by TermuxService to send result of +// commands back to the IntentService +// Note that the requestCode (currently executionId) must be unique for each pending +// intent, even if extras are different, otherwise only the result of only the first +// execution will be returned since pending intent will be cancelled by android +// after the first result has been sent back via the pending intent and termux +// will not be able to send more. + val pendingIntent = PendingIntent.getService( + context, executionId, + pluginResultsServiceIntent, + PendingIntent.FLAG_ONE_SHOT or (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0) + ) + intent.putExtra(RUN_COMMAND_SERVICE.EXTRA_PENDING_INTENT, pendingIntent) + + try { + // Send command intent for execution + Log.d(LOG_TAG, "Sending execution command with id $executionId") + context.startService(intent) + } catch (e: Exception) { + Log.e( + LOG_TAG, + "Failed to start execution command with id " + executionId + ": " + e.message + ) + } + } + + fun stub(context: Context) { + val command = "echo Hello, Tmux!" + + val exe = ExecutionCommand( + 5598, + TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/echo", +// arrayOf("\"hello\""), + null, + null, null, true, false) + + val task = TermuxTask.execute( + context, + exe, + null, + TermuxShellEnvironmentClient(), + true + ) + + val result = exe.resultData?.stdout.toString() + + debugLog("TMUX tas : $task") + debugLog("TMUX exe : $exe") + debugLog("TMUX OUT : $result") + } +} diff --git a/network/src/main/java/com/shifthackz/aisdv1/network/interceptor/LoggingInterceptor.kt b/network/src/main/java/com/shifthackz/aisdv1/network/interceptor/LoggingInterceptor.kt index e138632e..809d3da5 100644 --- a/network/src/main/java/com/shifthackz/aisdv1/network/interceptor/LoggingInterceptor.kt +++ b/network/src/main/java/com/shifthackz/aisdv1/network/interceptor/LoggingInterceptor.kt @@ -1,12 +1,11 @@ package com.shifthackz.aisdv1.network.interceptor -import com.shifthackz.aisdv1.core.common.log.debugLog import okhttp3.logging.HttpLoggingInterceptor internal class LoggingInterceptor { fun get() = HttpLoggingInterceptor { message -> - debugLog(HTTP_TAG, message) +// debugLog(HTTP_TAG, message) }.apply { level = HttpLoggingInterceptor.Level.HEADERS } diff --git a/settings.gradle b/settings.gradle index d78d583a..2d429620 100755 --- a/settings.gradle +++ b/settings.gradle @@ -29,6 +29,7 @@ def libraries = [ ':domain', ':feature:auth', ':feature:diffusion', + ':feature:sdxl', ':feature:work', ':network', ':presentation',