Compare commits
12 Commits
master
...
update-pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95088734da | ||
|
|
6681d57d2a | ||
|
|
3d4c815c91 | ||
|
|
1eeccc6be9 | ||
|
|
1abf5b9dd1 | ||
|
|
788d8a8d4f | ||
|
|
c1d9d59783 | ||
|
|
2cefbdbf7b | ||
|
|
a6e43c60fc | ||
|
|
5a8f50b8d1 | ||
|
|
43690520f4 | ||
|
|
7b11483734 |
@ -24,7 +24,7 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode vcode
|
||||
versionName "2.6.2"
|
||||
versionName "2.6.4"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
@ -198,7 +198,7 @@ ext.architectures = ["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]
|
||||
ext.libDir = "$project.projectDir/src/main/jniLibs"
|
||||
|
||||
task downloadAssets(type: Download) {
|
||||
def assetVersion = "v1.0.3"
|
||||
def assetVersion = "v1.1.7"
|
||||
def baseUrl = "https://github.com/CypherpunkArmory/UserLAnd-Assets-Support/releases/download/$assetVersion"
|
||||
for (arch in architectures) {
|
||||
src "$baseUrl/$arch-assets.zip"
|
||||
@ -209,9 +209,7 @@ task downloadAssets(type: Download) {
|
||||
task fetchAssets(dependsOn: downloadAssets) {
|
||||
doLast {
|
||||
for (arch in architectures) {
|
||||
delete {
|
||||
"$buildDir/$arch"
|
||||
}
|
||||
delete "$buildDir/$arch"
|
||||
copy {
|
||||
from zipTree("$buildDir/$arch-assets.zip")
|
||||
into "$buildDir/$arch"
|
||||
@ -222,6 +220,7 @@ task fetchAssets(dependsOn: downloadAssets) {
|
||||
// Lib files must start with 'lib' and end with '.so.'
|
||||
rename '(.*)', 'lib_$1.so'
|
||||
}
|
||||
new File("$libDir/$arch","lib_arch.so").text = "$arch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ import kotlinx.coroutines.launch
|
||||
import tech.ula.model.entities.App
|
||||
import tech.ula.model.entities.ServiceType
|
||||
import tech.ula.model.entities.Session
|
||||
import tech.ula.model.remote.GithubApiClient
|
||||
import tech.ula.model.repositories.AssetRepository
|
||||
import tech.ula.model.repositories.UlaDatabase
|
||||
import tech.ula.model.state.* // ktlint-disable no-wildcard-imports
|
||||
@ -117,7 +118,8 @@ class MainActivity : AppCompatActivity(), SessionListFragment.SessionSelection,
|
||||
val ulaDatabase = UlaDatabase.getInstance(this)
|
||||
|
||||
val assetPreferences = AssetPreferences(this)
|
||||
val assetRepository = AssetRepository(filesDir.path, assetPreferences)
|
||||
val githubApiClient = GithubApiClient(ulaFiles)
|
||||
val assetRepository = AssetRepository(filesDir.path, assetPreferences, githubApiClient)
|
||||
|
||||
val filesystemManager = FilesystemManager(ulaFiles, busyboxExecutor)
|
||||
val storageCalculator = StorageCalculator(StatFs(filesDir.path))
|
||||
@ -126,7 +128,7 @@ class MainActivity : AppCompatActivity(), SessionListFragment.SessionSelection,
|
||||
val downloadManagerWrapper = DownloadManagerWrapper(downloadManager)
|
||||
val assetDownloader = AssetDownloader(assetPreferences, downloadManagerWrapper, ulaFiles)
|
||||
|
||||
val appsStartupFsm = AppsStartupFsm(ulaDatabase, filesystemManager)
|
||||
val appsStartupFsm = AppsStartupFsm(ulaDatabase, filesystemManager, ulaFiles)
|
||||
val sessionStartupFsm = SessionStartupFsm(ulaDatabase, assetRepository, filesystemManager, assetDownloader, storageCalculator)
|
||||
ViewModelProviders.of(this, MainActivityViewModelFactory(appsStartupFsm, sessionStartupFsm))
|
||||
.get(MainActivityViewModel::class.java)
|
||||
|
||||
@ -7,9 +7,9 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import tech.ula.utils.DeviceArchitecture
|
||||
import tech.ula.utils.Logger
|
||||
import tech.ula.utils.SentryLogger
|
||||
import tech.ula.utils.UlaFiles
|
||||
import java.io.IOException
|
||||
import java.net.UnknownHostException
|
||||
|
||||
@ -20,7 +20,7 @@ class UrlProvider {
|
||||
}
|
||||
|
||||
class GithubApiClient(
|
||||
private val deviceArchitecture: DeviceArchitecture = DeviceArchitecture(),
|
||||
private val ulaFiles: UlaFiles,
|
||||
private val urlProvider: UrlProvider = UrlProvider(),
|
||||
private val logger: Logger = SentryLogger()
|
||||
) {
|
||||
@ -39,7 +39,7 @@ class GithubApiClient(
|
||||
suspend fun getAssetsListDownloadUrl(repo: String): String = withContext(Dispatchers.IO) {
|
||||
val result = latestResults[repo] ?: queryLatestRelease(repo)
|
||||
|
||||
return@withContext result.assets.find { it.name == "${deviceArchitecture.getArchType()}-assets.txt" }!!.downloadUrl
|
||||
return@withContext result.assets.find { it.name == "${ulaFiles.getArchType()}-assets.txt" }!!.downloadUrl
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@ -52,7 +52,7 @@ class GithubApiClient(
|
||||
@Throws(IOException::class)
|
||||
suspend fun getAssetEndpoint(assetType: String, repo: String): String = withContext(Dispatchers.IO) {
|
||||
val result = latestResults[repo] ?: queryLatestRelease(repo)
|
||||
val assetName = "${deviceArchitecture.getArchType()}-$assetType"
|
||||
val assetName = "${ulaFiles.getArchType()}-$assetType"
|
||||
|
||||
return@withContext result.assets.find { it.name == assetName }!!.downloadUrl
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ data class DownloadMetadata(
|
||||
class AssetRepository(
|
||||
private val applicationFilesDirPath: String,
|
||||
private val assetPreferences: AssetPreferences,
|
||||
private val githubApiClient: GithubApiClient = GithubApiClient(),
|
||||
private val githubApiClient: GithubApiClient,
|
||||
private val httpStream: HttpStream = HttpStream(),
|
||||
private val logger: Logger = SentryLogger()
|
||||
) {
|
||||
|
||||
@ -16,7 +16,7 @@ import tech.ula.utils.* // ktlint-disable no-wildcard-imports
|
||||
class AppsStartupFsm(
|
||||
ulaDatabase: UlaDatabase,
|
||||
private val filesystemManager: FilesystemManager,
|
||||
private val deviceArchitecture: DeviceArchitecture = DeviceArchitecture(),
|
||||
private val ulaFiles: UlaFiles,
|
||||
private val logger: Logger = SentryLogger()
|
||||
) {
|
||||
|
||||
@ -123,7 +123,7 @@ class AppsStartupFsm(
|
||||
val potentialAppFilesystem = filesystemDao.findAppsFilesystemByType(app.filesystemRequired)
|
||||
|
||||
if (potentialAppFilesystem.isEmpty()) {
|
||||
val deviceArchitecture = deviceArchitecture.getArchType()
|
||||
val deviceArchitecture = ulaFiles.getArchType()
|
||||
val fsToInsert = Filesystem(0, name = "apps", archType = deviceArchitecture,
|
||||
distributionType = app.filesystemRequired, isAppsFilesystem = true)
|
||||
filesystemDao.insertFilesystem(fsToInsert)
|
||||
|
||||
@ -24,9 +24,9 @@ import kotlinx.android.synthetic.main.frag_filesystem_edit.*
|
||||
import tech.ula.MainActivity
|
||||
import tech.ula.R
|
||||
import tech.ula.model.repositories.UlaDatabase
|
||||
import tech.ula.utils.DeviceArchitecture
|
||||
import tech.ula.utils.PermissionHandler
|
||||
import tech.ula.utils.CredentialValidator
|
||||
import tech.ula.utils.UlaFiles
|
||||
import tech.ula.utils.preferences.AppsPreferences
|
||||
import tech.ula.viewmodel.FilesystemImportStatus
|
||||
import tech.ula.viewmodel.ImportSuccess
|
||||
@ -232,12 +232,8 @@ class FilesystemEditFragment : Fragment() {
|
||||
filesystemEditViewModel.updateFilesystem(filesystem)
|
||||
navController.popBackStack()
|
||||
} else {
|
||||
try {
|
||||
filesystem.archType = DeviceArchitecture().getArchType()
|
||||
} catch (err: Exception) {
|
||||
Toast.makeText(activityContext, R.string.no_supported_architecture, Toast.LENGTH_LONG).show()
|
||||
return true
|
||||
}
|
||||
val ulaFiles = UlaFiles(activityContext, activityContext.applicationInfo.nativeLibraryDir)
|
||||
filesystem.archType = ulaFiles.getArchType()
|
||||
if (filesystem.isCreatedFromBackup) {
|
||||
filesystemEditViewModel.insertFilesystemFromBackup(activityContext.contentResolver, filesystem, activityContext.filesDir)
|
||||
} else {
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
package tech.ula.utils
|
||||
|
||||
import android.os.Build
|
||||
|
||||
class DeviceArchitecture {
|
||||
fun getArchType(): String {
|
||||
val supportedABIS = this.getSupportedAbis()
|
||||
.map {
|
||||
translateABI(it)
|
||||
}
|
||||
.filter {
|
||||
isSupported(it)
|
||||
}
|
||||
return if (supportedABIS.size == 1 && supportedABIS[0] == "") {
|
||||
val exception = IllegalStateException("No supported ABI!")
|
||||
SentryLogger().addExceptionBreadcrumb(exception)
|
||||
throw exception
|
||||
} else {
|
||||
supportedABIS[0]
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSupportedAbis(): Array<String> {
|
||||
return Build.SUPPORTED_ABIS
|
||||
}
|
||||
|
||||
private fun isSupported(abi: String): Boolean {
|
||||
val supportedABIs = listOf("arm64", "arm", "x86_64", "x86")
|
||||
return supportedABIs.contains(abi)
|
||||
}
|
||||
|
||||
private fun translateABI(abi: String): String {
|
||||
return when (abi) {
|
||||
"arm64-v8a" -> "arm64"
|
||||
"armeabi-v7a" -> "arm"
|
||||
"x86_64" -> "x86_64"
|
||||
"x86" -> "x86"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,6 +71,21 @@ class UlaFiles(
|
||||
symlinker.createSymlink(libFile.path, linkFile.path)
|
||||
}
|
||||
}
|
||||
|
||||
fun getArchType(): String {
|
||||
val usedABI = File(libDir, "lib_arch.so").readText()
|
||||
return translateABI(usedABI)
|
||||
}
|
||||
|
||||
private fun translateABI(abi: String): String {
|
||||
return when (abi) {
|
||||
"arm64-v8a" -> "arm64"
|
||||
"armeabi-v7a" -> "arm"
|
||||
"x86_64" -> "x86_64"
|
||||
"x86" -> "x86"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Symlinker {
|
||||
|
||||
@ -179,7 +179,6 @@
|
||||
<string name="session_unique_name_required">الجلسات تتطلب اسمًا فريدًا!</string>
|
||||
<string name="filesystem_unique_name_required">تتطلب أنظمة الملفات اسمًا فريدًا!</string>
|
||||
<string name="single_session_supported">UserLAnd يدعم حاليا فقط جلسة واحدة نشطة!</string>
|
||||
<string name="no_supported_architecture">لا يدعم UserLAnd بنية الأجهزة حاليًا.</string>
|
||||
<string name="debug_log_deleted">سجل تصحيح حذف أو غير موجود!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -173,7 +173,6 @@
|
||||
<string name="session_unique_name_required">¡Las sesiones requieren un nombre único!</string>
|
||||
<string name="filesystem_unique_name_required">¡Los sistemas de archivos requieren un nombre único!</string>
|
||||
<string name="single_session_supported">¡UserLAnd por ahora sólo soporta una sesión activa!</string>
|
||||
<string name="no_supported_architecture">UserLAnd por ahora no soporta la arquitectura de tu dispositivo.</string>
|
||||
<string name="debug_log_deleted">¡El archivo de registro de depuración fue eliminado o es inexistente!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -123,7 +123,6 @@
|
||||
<string name="session_unique_name_required">نام نشستها باید یکتا باشد!</string>
|
||||
<string name="filesystem_unique_name_required">نام فایلسیستمها باید یکتا باشد!</string>
|
||||
<string name="single_session_supported">یوزرلند در حال حاضر تنها از یک نشست فعال پشتیبانی میکند!</string>
|
||||
<string name="no_supported_architecture">یوزرلند در حال حاضر از معماری دستگاه شما پیشتیبانی نمیکند.</string>
|
||||
<string name="debug_log_deleted">لاگ دیباگ یا پاک شده و یا وجود ندارد!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -123,7 +123,6 @@
|
||||
<string name="session_unique_name_required">Les Sessions ont besoin d\'un nom unique !</string>
|
||||
<string name="filesystem_unique_name_required">Les Systèmes de fichiers ont besoin d\'un nom unique !</string>
|
||||
<string name="single_session_supported">Actuellement UserLAnd ne prend en charge qu’une seule session active !</string>
|
||||
<string name="no_supported_architecture">L’architecture de votre dispositif n’est pas actuellement prise en charge par UserLAnd.</string>
|
||||
<string name="debug_log_deleted">Le journal de débogage a été supprimé ou n’existe pas !</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -123,7 +123,6 @@
|
||||
<string name="session_unique_name_required">他のセッションと同じ名前は使用できません。</string>
|
||||
<string name="filesystem_unique_name_required">他のファイルシステムと同じ名前は使用できません。</string>
|
||||
<string name="single_session_supported">UserLAnd は今の所1個しかセッションを立ち上げられません!</string>
|
||||
<string name="no_supported_architecture">UserLAnd は現在、ご使用の端末のアーキテクチャに対応していません。</string>
|
||||
<string name="debug_log_deleted">デバッグ情報のログが削除されたか、存在していません!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -200,7 +200,6 @@
|
||||
<string name="session_unique_name_required">Sessões exigem um nome único!</string>
|
||||
<string name="filesystem_unique_name_required">Sistemas de Arquivos exigem um nome único!</string>
|
||||
<string name="single_session_supported">UserLAnd atualmente suporta apenas uma única sessão ativa!</string>
|
||||
<string name="no_supported_architecture">O UserLAnd não suporta atualmente a arquitetura de seus dispositivo.</string>
|
||||
<string name="debug_log_deleted">Log de depuração excluído ou não existe!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -165,7 +165,6 @@
|
||||
<string name="session_unique_name_required">Сессии должны иметь различные имена!</string>
|
||||
<string name="filesystem_unique_name_required">Файловые системы должны иметь различные имена!</string>
|
||||
<string name="single_session_supported">На текущий момент UserLAnd поддерживает лишь единственную активную сессию!</string>
|
||||
<string name="no_supported_architecture">На текущий момент UserLAnd не поддерживает архитектуру вашего устройства.</string>
|
||||
<string name="debug_log_deleted">Журнал отладки удалён или не существует!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -92,7 +92,6 @@
|
||||
<string name="session_unique_name_required">此会话需要一个特殊的名字!</string>
|
||||
<string name="filesystem_unique_name_required">文件系统需要一个特殊的名字!</string>
|
||||
<string name="single_session_supported">UserLAnd目前仅支持一个会话!</string>
|
||||
<string name="no_supported_architecture">UserLAnd目前无法支持您的设备.</string>
|
||||
<string name="debug_log_deleted">除错日志已被删除或者不存在!</string>
|
||||
<string name="desc_arrow">图像:箭头指示会话与文件系统之间的关系</string>
|
||||
<string name="desc_filesystem_type">图像:分发图标</string>
|
||||
|
||||
@ -193,7 +193,6 @@
|
||||
<string name="session_unique_name_required">工作階段必須有獨一無二的名稱!</string>
|
||||
<string name="filesystem_unique_name_required">檔案系統必須有獨一無二的名稱!</string>
|
||||
<string name="single_session_supported">UserLAnd 目前僅支援單一個作用中的工作階段!</string>
|
||||
<string name="no_supported_architecture">UserLAnd 目前並不支援您的裝置架構。</string>
|
||||
<string name="debug_log_deleted">除錯紀錄檔已被刪除或不存在!</string>
|
||||
|
||||
<!-- Content descriptions -->
|
||||
|
||||
@ -226,7 +226,6 @@
|
||||
<string name="session_unique_name_required">Sessions require a unique name!</string>
|
||||
<string name="filesystem_unique_name_required">Filesystems require a unique name!</string>
|
||||
<string name="single_session_supported">UserLAnd currently only supports a single active session!</string>
|
||||
<string name="no_supported_architecture">UserLAnd does not currently support your devices architecture.</string>
|
||||
<string name="debug_log_export_success">Debug log exported successfully!</string>
|
||||
<string name="debug_log_export_failure">Exporting debug log failed!</string>
|
||||
<string name="debug_log_deleted">Debug log deleted!</string>
|
||||
|
||||
@ -16,7 +16,7 @@ import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import tech.ula.utils.Logger
|
||||
import tech.ula.utils.DeviceArchitecture
|
||||
import tech.ula.utils.UlaFiles
|
||||
import java.io.IOException
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
@ -24,7 +24,7 @@ class GithubApiClientTest {
|
||||
|
||||
@get:Rule val server = MockWebServer()
|
||||
|
||||
@Mock lateinit var mockDeviceArchitecture: DeviceArchitecture
|
||||
@Mock lateinit var mockUlaFiles: UlaFiles
|
||||
|
||||
@Mock lateinit var mockUrlProvider: UrlProvider
|
||||
|
||||
@ -76,9 +76,9 @@ class GithubApiClientTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
whenever(mockDeviceArchitecture.getArchType()).thenReturn(testArch)
|
||||
whenever(mockUlaFiles.getArchType()).thenReturn(testArch)
|
||||
|
||||
githubApiClient = GithubApiClient(mockDeviceArchitecture, mockUrlProvider, mockLogger)
|
||||
githubApiClient = GithubApiClient(mockUlaFiles, mockUrlProvider, mockLogger)
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@ -42,7 +42,7 @@ class AppsStartupFsmTest {
|
||||
|
||||
@Mock lateinit var mockFilesystemManager: FilesystemManager
|
||||
|
||||
@Mock lateinit var mockDeviceArchitecture: DeviceArchitecture
|
||||
@Mock lateinit var mockUlaFiles: UlaFiles
|
||||
|
||||
@Mock lateinit var mockLogger: Logger
|
||||
|
||||
@ -97,7 +97,7 @@ class AppsStartupFsmTest {
|
||||
whenever(mockUlaDatabase.filesystemDao()).thenReturn(mockFilesystemDao)
|
||||
whenever(mockUlaDatabase.sessionDao()).thenReturn(mockSessionDao)
|
||||
|
||||
appsFsm = AppsStartupFsm(mockUlaDatabase, mockFilesystemManager, mockDeviceArchitecture, mockLogger)
|
||||
appsFsm = AppsStartupFsm(mockUlaDatabase, mockFilesystemManager, mockUlaFiles, mockLogger)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -165,7 +165,7 @@ class AppsStartupFsmTest {
|
||||
|
||||
whenever(mockSessionDao.findAppsSession(app.name))
|
||||
.thenReturn(listOf(appSession))
|
||||
whenever(mockDeviceArchitecture.getArchType())
|
||||
whenever(mockUlaFiles.getArchType())
|
||||
.thenReturn("")
|
||||
whenever(mockFilesystemDao.findAppsFilesystemByType(app.filesystemRequired))
|
||||
.thenReturn(listOf())
|
||||
@ -219,7 +219,7 @@ class AppsStartupFsmTest {
|
||||
appsFsm.setState(WaitingForAppSelection)
|
||||
appsFsm.getState().observeForever(mockStateObserver)
|
||||
|
||||
whenever(mockDeviceArchitecture.getArchType())
|
||||
whenever(mockUlaFiles.getArchType())
|
||||
.thenReturn("")
|
||||
whenever(mockFilesystemDao.findAppsFilesystemByType(app.filesystemRequired))
|
||||
.thenReturn(listOf())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user