mirror of
https://github.com/Ishan09811/pine.git
synced 2025-04-24 08:55:10 +00:00
Implement GpuDriver import option (#66)
This commit is contained in:
parent
d165984c89
commit
f9fc9fa5ed
@ -193,6 +193,14 @@ dependencies {
|
|||||||
implementation 'info.debatty:java-string-similarity:2.0.0'
|
implementation 'info.debatty:java-string-similarity:2.0.0'
|
||||||
implementation 'com.github.KikiManjaro:colorpicker:v1.1.12'
|
implementation 'com.github.KikiManjaro:colorpicker:v1.1.12'
|
||||||
implementation 'com.github.android:renderscript-intrinsics-replacement-toolkit:344be3f'
|
implementation 'com.github.android:renderscript-intrinsics-replacement-toolkit:344be3f'
|
||||||
|
|
||||||
|
/* Network */
|
||||||
|
implementation 'io.ktor:ktor-client-core:3.0.3'
|
||||||
|
implementation 'io.ktor:ktor-client-cio:3.0.3'
|
||||||
|
implementation 'io.ktor:ktor-client-json:3.0.3'
|
||||||
|
implementation 'io.ktor:ktor-serialization-kotlinx-json:3.0.3'
|
||||||
|
implementation 'io.ktor:ktor-client-content-negotiation:3.0.3'
|
||||||
|
implementation 'io.ktor:ktor-client-logging:3.0.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
|
@ -25,6 +25,7 @@ import emu.skyline.input.StickId.Right
|
|||||||
import emu.skyline.utils.SwitchColors
|
import emu.skyline.utils.SwitchColors
|
||||||
import emu.skyline.utils.add
|
import emu.skyline.utils.add
|
||||||
import emu.skyline.utils.multiply
|
import emu.skyline.utils.multiply
|
||||||
|
import emu.skyline.SkylineApplication
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
open class CircularButton(
|
open class CircularButton(
|
||||||
@ -33,7 +34,7 @@ open class CircularButton(
|
|||||||
defaultRelativeX : Float,
|
defaultRelativeX : Float,
|
||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeRadiusToX : Float,
|
defaultRelativeRadiusToX : Float,
|
||||||
drawableId : Int = R.drawable.ic_button,
|
drawableId : Int = SkylineApplication.context.resources.getIdentifier("ic_button", "drawable", SkylineApplication.context.packageName),
|
||||||
defaultEnabled : Boolean = true
|
defaultEnabled : Boolean = true
|
||||||
) : OnScreenButton(
|
) : OnScreenButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
@ -65,9 +66,9 @@ open class JoystickButton(
|
|||||||
defaultRelativeX,
|
defaultRelativeX,
|
||||||
defaultRelativeY,
|
defaultRelativeY,
|
||||||
defaultRelativeRadiusToX,
|
defaultRelativeRadiusToX,
|
||||||
R.drawable.ic_button
|
SkylineApplication.context.resources.getIdentifier("ic_button", "drawable", SkylineApplication.context.packageName)
|
||||||
) {
|
) {
|
||||||
private val innerButton = CircularButton(onScreenControllerView, buttonId, config.relativeX, config.relativeY, defaultRelativeRadiusToX * 0.75f, R.drawable.ic_stick)
|
private val innerButton = CircularButton(onScreenControllerView, buttonId, config.relativeX, config.relativeY, defaultRelativeRadiusToX * 0.75f, SkylineApplication.context.resources.getIdentifier("ic_stick", "drawable", SkylineApplication.context.packageName))
|
||||||
|
|
||||||
open var recenterSticks = false
|
open var recenterSticks = false
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -275,7 +276,7 @@ open class RectangularButton(
|
|||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeWidth : Float,
|
defaultRelativeWidth : Float,
|
||||||
defaultRelativeHeight : Float,
|
defaultRelativeHeight : Float,
|
||||||
drawableId : Int = R.drawable.ic_rectangular_button,
|
drawableId : Int = SkylineApplication.context.resources.getIdentifier("ic_rectangular_button", "drawable", SkylineApplication.context.packageName),
|
||||||
defaultEnabled : Boolean = true
|
defaultEnabled : Boolean = true
|
||||||
) : OnScreenButton(
|
) : OnScreenButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
@ -305,9 +306,9 @@ class TriggerButton(
|
|||||||
defaultRelativeWidth,
|
defaultRelativeWidth,
|
||||||
defaultRelativeHeight,
|
defaultRelativeHeight,
|
||||||
when (buttonId) {
|
when (buttonId) {
|
||||||
ZL -> R.drawable.ic_trigger_button_left
|
ZL -> SkylineApplication.context.resources.getIdentifier("ic_trigger_button_left", "drawable", SkylineApplication.context.packageName)
|
||||||
|
|
||||||
ZR -> R.drawable.ic_trigger_button_right
|
ZR -> SkylineApplication.context.resources.getIdentifier("ic_trigger_button_right", "drawable", SkylineApplication.context.packageName)
|
||||||
|
|
||||||
else -> error("Unsupported trigger button")
|
else -> error("Unsupported trigger button")
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,19 @@ import android.content.Intent
|
|||||||
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
|
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.adapter.GenericListItem
|
import emu.skyline.adapter.GenericListItem
|
||||||
@ -28,17 +31,24 @@ import emu.skyline.adapter.SpacingItemDecoration
|
|||||||
import emu.skyline.data.BaseAppItem
|
import emu.skyline.data.BaseAppItem
|
||||||
import emu.skyline.data.AppItemTag
|
import emu.skyline.data.AppItemTag
|
||||||
import emu.skyline.databinding.GpuDriverActivityBinding
|
import emu.skyline.databinding.GpuDriverActivityBinding
|
||||||
|
import emu.skyline.databinding.DialogKeyboardBinding
|
||||||
import emu.skyline.settings.EmulationSettings
|
import emu.skyline.settings.EmulationSettings
|
||||||
import emu.skyline.utils.GpuDriverHelper
|
import emu.skyline.utils.GpuDriverHelper
|
||||||
import emu.skyline.utils.GpuDriverInstallResult
|
import emu.skyline.utils.GpuDriverInstallResult
|
||||||
import emu.skyline.utils.WindowInsetsHelper
|
import emu.skyline.utils.WindowInsetsHelper
|
||||||
import emu.skyline.utils.serializable
|
import emu.skyline.utils.serializable
|
||||||
|
import emu.skyline.utils.DriversFetcher
|
||||||
|
import emu.skyline.utils.DriversFetcher.DownloadResult
|
||||||
import emu.skyline.di.getSettings
|
import emu.skyline.di.getSettings
|
||||||
import emu.skyline.SkylineApplication
|
import emu.skyline.SkylineApplication
|
||||||
|
import emu.skyline.getPublicFilesDir
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This activity is used to manage the installed gpu drivers and select one to use.
|
* This activity is used to manage the installed gpu drivers and select one to use.
|
||||||
@ -189,11 +199,28 @@ class GpuDriverActivity : AppCompatActivity() {
|
|||||||
binding.driverList.addItemDecoration(SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.grid_padding)))
|
binding.driverList.addItemDecoration(SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.grid_padding)))
|
||||||
|
|
||||||
binding.addDriverButton.setOnClickListener {
|
binding.addDriverButton.setOnClickListener {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
val items = arrayOf(getString(R.string.driver_import), getString(R.string.install))
|
||||||
addFlags(FLAG_GRANT_READ_URI_PERMISSION)
|
var checkedItem = 0
|
||||||
type = "application/zip"
|
var selectedItem: String? = items[0]
|
||||||
}
|
|
||||||
installCallback.launch(intent)
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(R.string.choose)
|
||||||
|
.setSingleChoiceItems(items, checkedItem) { dialog, which ->
|
||||||
|
selectedItem = items[which]
|
||||||
|
}
|
||||||
|
.setPositiveButton(android.R.string.ok) { dialog, _ ->
|
||||||
|
if (selectedItem == getString(R.string.install)) {
|
||||||
|
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||||
|
addFlags(FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
type = "application/zip"
|
||||||
|
}
|
||||||
|
installCallback.launch(intent)
|
||||||
|
} else {
|
||||||
|
handleGpuDriverImport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
populateAdapter()
|
populateAdapter()
|
||||||
@ -207,6 +234,72 @@ class GpuDriverActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleGpuDriverImport() {
|
||||||
|
val inflater = LayoutInflater.from(this)
|
||||||
|
val inputBinding = DialogKeyboardBinding.inflate(inflater)
|
||||||
|
var textInputValue: String = getString(R.string.default_driver_repo_url)
|
||||||
|
|
||||||
|
inputBinding.editTextInput.setText(textInputValue)
|
||||||
|
inputBinding.editTextInput.doOnTextChanged { text, _, _, _ ->
|
||||||
|
textInputValue = text.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setView(inputBinding.root)
|
||||||
|
.setTitle(R.string.enter_repo_url)
|
||||||
|
.setPositiveButton(R.string.fetch) { _, _ ->
|
||||||
|
if (textInputValue.isNotEmpty()) {
|
||||||
|
fetchAndShowDrivers(textInputValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel) {_, _ -> }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchAndShowDrivers(repoUrl: String) {
|
||||||
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
val releases = DriversFetcher.fetchReleases(repoUrl)
|
||||||
|
if (releases.isEmpty()) {
|
||||||
|
Snackbar.make(binding.root, "Failed to fetch ${repoUrl}: validation failed or check your internet connection", Snackbar.LENGTH_SHORT).show()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
val releaseNames = releases.map { it.first }
|
||||||
|
val releaseUrls = releases.map { it.second }
|
||||||
|
var chosenUrl: String? = releaseUrls[0]
|
||||||
|
var chosenName: String? = releaseNames[0]
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder(this@GpuDriverActivity)
|
||||||
|
.setTitle(R.string.drivers)
|
||||||
|
.setSingleChoiceItems(releaseNames.toTypedArray(), 0) { _, which ->
|
||||||
|
chosenUrl = releaseUrls[which]
|
||||||
|
chosenName = releaseNames[which]
|
||||||
|
}
|
||||||
|
.setPositiveButton(R.string.driver_import) { _, _ ->
|
||||||
|
downloadDriver(chosenUrl!!, chosenName!!)
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun downloadDriver(chosenUrl: String, chosenName: String) {
|
||||||
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
|
var driverFile = File("${SkylineApplication.instance.getPublicFilesDir().canonicalPath}/${chosenName}.zip")
|
||||||
|
if (!driverFile.exists()) driverFile.createNewFile()
|
||||||
|
val result = DriversFetcher.downloadAsset(chosenUrl!!, driverFile)
|
||||||
|
when (result) {
|
||||||
|
is DownloadResult.Success -> {
|
||||||
|
val result = GpuDriverHelper.installDriver(this@GpuDriverActivity, FileInputStream(driverFile))
|
||||||
|
Snackbar.make(binding.root, resolveInstallResultString(result), Snackbar.LENGTH_LONG).show()
|
||||||
|
if (result == GpuDriverInstallResult.Success) populateAdapter()
|
||||||
|
driverFile.delete()
|
||||||
|
}
|
||||||
|
is DownloadResult.Error -> Snackbar.make(binding.root, "Failed to import ${chosenName}: ${result.message}", Snackbar.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun resolveInstallResultString(result : GpuDriverInstallResult) = when (result) {
|
private fun resolveInstallResultString(result : GpuDriverInstallResult) = when (result) {
|
||||||
GpuDriverInstallResult.Success -> getString(R.string.gpu_driver_install_success)
|
GpuDriverInstallResult.Success -> getString(R.string.gpu_driver_install_success)
|
||||||
GpuDriverInstallResult.InvalidArchive -> getString(R.string.gpu_driver_install_invalid_archive)
|
GpuDriverInstallResult.InvalidArchive -> getString(R.string.gpu_driver_install_invalid_archive)
|
||||||
|
105
app/src/main/java/emu/skyline/utils/DriversFetcher.kt
Normal file
105
app/src/main/java/emu/skyline/utils/DriversFetcher.kt
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package emu.skyline.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.call.*
|
||||||
|
import io.ktor.client.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.client.plugins.logging.*
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.statement.*
|
||||||
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
import io.ktor.utils.io.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object DriversFetcher {
|
||||||
|
private val httpClient = HttpClient {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json(Json { ignoreUnknownKeys = true })
|
||||||
|
}
|
||||||
|
install(Logging) {
|
||||||
|
level = LogLevel.BODY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GitHubRelease(
|
||||||
|
val name: String,
|
||||||
|
val assets: List<Asset> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Asset(val browser_download_url: String)
|
||||||
|
|
||||||
|
suspend fun fetchReleases(repoUrl: String): List<Pair<String, String?>> {
|
||||||
|
val repoPath = repoUrl.removePrefix("https://github.com/")
|
||||||
|
val validationUrl = "https://api.github.com/repos/$repoPath/contents/.adrenoDrivers"
|
||||||
|
val apiUrl = "https://api.github.com/repos/$repoPath/releases"
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val isValid = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
httpClient.get(validationUrl).status.value == 200
|
||||||
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
Log.d("DriversFetcher", "Provided driver repo url is not valid.")
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val releases: List<GitHubRelease> = withContext(Dispatchers.IO) {
|
||||||
|
httpClient.get(apiUrl).body()
|
||||||
|
}
|
||||||
|
releases.map { release ->
|
||||||
|
val assetUrl = release.assets.firstOrNull()?.browser_download_url
|
||||||
|
release.name to assetUrl
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("DriversFetcher", "Error fetching releases: ${e.message}", e)
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun downloadAsset(assetUrl: String, destinationFile: File): DownloadResult {
|
||||||
|
return try {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val response: HttpResponse = httpClient.get(assetUrl)
|
||||||
|
FileOutputStream(destinationFile)?.use { outputStream ->
|
||||||
|
writeResponseToStream(response, outputStream)
|
||||||
|
} ?: return@withContext DownloadResult.Error("Failed to open ${destinationFile.absolutePath.toString()}")
|
||||||
|
}
|
||||||
|
DownloadResult.Success
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("DriversFetcher", "Error downloading file: ${e.message}", e)
|
||||||
|
DownloadResult.Error(e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun writeResponseToStream(response: HttpResponse, outputStream: OutputStream) {
|
||||||
|
val channel = response.bodyAsChannel()
|
||||||
|
val buffer = ByteArray(8192) // 8KB buffer size
|
||||||
|
|
||||||
|
while (!channel.isClosedForRead) {
|
||||||
|
val bytesRead = channel.readAvailable(buffer)
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputStream.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DownloadResult {
|
||||||
|
object Success : DownloadResult()
|
||||||
|
data class Error(val message: String?) : DownloadResult()
|
||||||
|
}
|
||||||
|
}
|
24
app/src/main/res/layout/dialog_keyboard.xml
Normal file
24
app/src/main/res/layout/dialog_keyboard.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.textfield.TextInputLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/edit_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/edit_text_input"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:textAlignment="viewStart" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
@ -201,6 +201,12 @@
|
|||||||
<string name="system_driver">System Driver</string>
|
<string name="system_driver">System Driver</string>
|
||||||
<string name="system_driver_desc">The GPU driver provided by your system</string>
|
<string name="system_driver_desc">The GPU driver provided by your system</string>
|
||||||
<string name="install">Install</string>
|
<string name="install">Install</string>
|
||||||
|
<string name="driver_import">Import</string>
|
||||||
|
<string name="choose">Choose</string>
|
||||||
|
<string name="drivers">Drivers</string>
|
||||||
|
<string name="enter_repo_url">Enter repo url</string>
|
||||||
|
<string name="default_driver_repo_url">https://github.com/K11MCH1/AdrenoToolsDrivers</string>
|
||||||
|
<string name="fetch">Fetch</string>
|
||||||
<string name="gpu_driver_install_inprogress">Installing the GPU driver…</string>
|
<string name="gpu_driver_install_inprogress">Installing the GPU driver…</string>
|
||||||
<string name="gpu_driver_install_success">GPU driver installed successfully</string>
|
<string name="gpu_driver_install_success">GPU driver installed successfully</string>
|
||||||
<string name="gpu_driver_install_invalid_archive">Failed to unzip the provided driver package</string>
|
<string name="gpu_driver_install_invalid_archive">Failed to unzip the provided driver package</string>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlin_version = '1.9.22'
|
kotlin_version = '2.0.10'
|
||||||
hilt_version = '2.50'
|
hilt_version = '2.50'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user