mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-22 20:24:03 -04:00
#1663 Improve FileSystem detection - read from mount and fallback to file writing
This commit is contained in:
parent
5d33f47cce
commit
077908080e
@ -22,7 +22,11 @@ import android.content.Context
|
|||||||
import android.location.LocationManager
|
import android.location.LocationManager
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import org.kiwix.kiwixmobile.di.KiwixScope
|
import org.kiwix.kiwixmobile.di.KiwixScope
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileWritingFileSystemChecker
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.MountFileSystemChecker
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object KiwixModule {
|
object KiwixModule {
|
||||||
@ -31,4 +35,13 @@ object KiwixModule {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
internal fun provideLocationManager(context: Context): LocationManager =
|
internal fun provideLocationManager(context: Context): LocationManager =
|
||||||
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@KiwixScope
|
||||||
|
@JvmStatic
|
||||||
|
internal fun provideFat32Checker(sharedPreferenceUtil: SharedPreferenceUtil): Fat32Checker =
|
||||||
|
Fat32Checker(
|
||||||
|
sharedPreferenceUtil,
|
||||||
|
listOf(MountFileSystemChecker(), FileWritingFileSystemChecker())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package org.kiwix.kiwixmobile.zim_manager
|
package org.kiwix.kiwixmobile.zim_manager
|
||||||
|
|
||||||
import android.os.FileObserver
|
import android.os.FileObserver
|
||||||
import android.util.Log
|
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.functions.BiFunction
|
import io.reactivex.functions.BiFunction
|
||||||
import io.reactivex.processors.BehaviorProcessor
|
import io.reactivex.processors.BehaviorProcessor
|
||||||
@ -28,11 +27,15 @@ import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CanWrite4G
|
|||||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CannotWrite4GbFile
|
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CannotWrite4GbFile
|
||||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.NotEnoughSpaceFor4GbFile
|
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.NotEnoughSpaceFor4GbFile
|
||||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.Unknown
|
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.Unknown
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CANNOT_WRITE_4GB
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CAN_WRITE_4GB
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.INCONCLUSIVE
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.RandomAccessFile
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class Fat32Checker @Inject constructor(sharedPreferenceUtil: SharedPreferenceUtil) {
|
class Fat32Checker constructor(
|
||||||
|
sharedPreferenceUtil: SharedPreferenceUtil,
|
||||||
|
private val fileSystemCheckers: List<FileSystemChecker>
|
||||||
|
) {
|
||||||
val fileSystemStates: BehaviorProcessor<FileSystemState> = BehaviorProcessor.create()
|
val fileSystemStates: BehaviorProcessor<FileSystemState> = BehaviorProcessor.create()
|
||||||
private var fileObserver: FileObserver? = null
|
private var fileObserver: FileObserver? = null
|
||||||
private val requestCheckSystemFileType = BehaviorProcessor.createDefault(Unit)
|
private val requestCheckSystemFileType = BehaviorProcessor.createDefault(Unit)
|
||||||
@ -59,10 +62,7 @@ class Fat32Checker @Inject constructor(sharedPreferenceUtil: SharedPreferenceUti
|
|||||||
|
|
||||||
private fun fileObserver(it: String?): FileObserver {
|
private fun fileObserver(it: String?): FileObserver {
|
||||||
return object : FileObserver(it, MOVED_FROM or DELETE) {
|
return object : FileObserver(it, MOVED_FROM or DELETE) {
|
||||||
override fun onEvent(
|
override fun onEvent(event: Int, path: String?) {
|
||||||
event: Int,
|
|
||||||
path: String?
|
|
||||||
) {
|
|
||||||
requestCheckSystemFileType.onNext(Unit)
|
requestCheckSystemFileType.onNext(Unit)
|
||||||
}
|
}
|
||||||
}.apply { startWatching() }
|
}.apply { startWatching() }
|
||||||
@ -77,20 +77,16 @@ class Fat32Checker @Inject constructor(sharedPreferenceUtil: SharedPreferenceUti
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun canCreate4GbFile(storage: String): Boolean {
|
private fun canCreate4GbFile(storage: String): Boolean {
|
||||||
val path = "$storage/large_file_test.txt"
|
fileSystemCheckers.forEach {
|
||||||
File(path).deleteIfExists()
|
when (it.checkFilesystemSupports4GbFiles(storage)) {
|
||||||
try {
|
CAN_WRITE_4GB -> return@canCreate4GbFile true
|
||||||
RandomAccessFile(path, "rw").use {
|
CANNOT_WRITE_4GB -> return@canCreate4GbFile false
|
||||||
it.setLength(FOUR_GIGABYTES_IN_BYTES)
|
INCONCLUSIVE -> {
|
||||||
return@canCreate4GbFile true
|
/*do nothing*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Log.d("Fat32Checker", e.message)
|
|
||||||
return false
|
|
||||||
} finally {
|
|
||||||
File(path).deleteIfExists()
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -105,7 +101,3 @@ class Fat32Checker @Inject constructor(sharedPreferenceUtil: SharedPreferenceUti
|
|||||||
object Unknown : FileSystemState()
|
object Unknown : FileSystemState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun File.deleteIfExists() {
|
|
||||||
if (exists()) delete()
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.zim_manager
|
||||||
|
|
||||||
|
interface FileSystemChecker {
|
||||||
|
fun checkFilesystemSupports4GbFiles(path: String): FileSystemCapability
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FileSystemCapability {
|
||||||
|
CAN_WRITE_4GB,
|
||||||
|
CANNOT_WRITE_4GB,
|
||||||
|
INCONCLUSIVE
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.zim_manager
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CANNOT_WRITE_4GB
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CAN_WRITE_4GB
|
||||||
|
import java.io.File
|
||||||
|
import java.io.RandomAccessFile
|
||||||
|
|
||||||
|
class FileWritingFileSystemChecker : FileSystemChecker {
|
||||||
|
override fun checkFilesystemSupports4GbFiles(path: String): FileSystemCapability {
|
||||||
|
with(File("$path/large_file_test.txt")) {
|
||||||
|
deleteIfExists()
|
||||||
|
try {
|
||||||
|
RandomAccessFile(this.path, "rw").use {
|
||||||
|
it.setLength(Fat32Checker.FOUR_GIGABYTES_IN_BYTES)
|
||||||
|
return@checkFilesystemSupports4GbFiles CAN_WRITE_4GB
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Log.d("Fat32Checker", e.message)
|
||||||
|
return@checkFilesystemSupports4GbFiles CANNOT_WRITE_4GB
|
||||||
|
} finally {
|
||||||
|
deleteIfExists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun File.deleteIfExists() {
|
||||||
|
if (exists()) delete()
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.zim_manager
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CANNOT_WRITE_4GB
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.CAN_WRITE_4GB
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.FileSystemCapability.INCONCLUSIVE
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class MountFileSystemChecker : FileSystemChecker {
|
||||||
|
override fun checkFilesystemSupports4GbFiles(path: String) =
|
||||||
|
recursivelyDetermineFilesystem(mountPoints(), path)
|
||||||
|
|
||||||
|
private fun recursivelyDetermineFilesystem(
|
||||||
|
mountPoints: List<MountInfo>,
|
||||||
|
path: String
|
||||||
|
): FileSystemCapability =
|
||||||
|
mountPoints.maxBy { it.matchCount(path) }
|
||||||
|
?.takeIf { it.matchCount(path) > 0 }
|
||||||
|
?.let {
|
||||||
|
when {
|
||||||
|
it.isVirtual -> recursivelyDetermineFilesystem(mountPoints, it.device)
|
||||||
|
it.supports4GBFiles -> CAN_WRITE_4GB
|
||||||
|
it.doesNotSupport4GBFiles -> CANNOT_WRITE_4GB
|
||||||
|
else -> INCONCLUSIVE
|
||||||
|
}
|
||||||
|
} ?: INCONCLUSIVE
|
||||||
|
|
||||||
|
private fun mountPoints() =
|
||||||
|
File("proc/mounts")
|
||||||
|
.takeIf(File::exists)
|
||||||
|
?.readLines()
|
||||||
|
?.map { MountInfo(it.split(" ")) }
|
||||||
|
?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MountInfo(val device: String, val mountPoint: String, val fileSystem: String) {
|
||||||
|
constructor(split: List<String>) : this(split[0], split[1], split[2])
|
||||||
|
|
||||||
|
fun matchCount(storage: String) = storage.split("/")
|
||||||
|
.zip(mountPoint.split("/"))
|
||||||
|
.fold(0, { acc, pair ->
|
||||||
|
if (pair.first == pair.second) acc + 1
|
||||||
|
else acc
|
||||||
|
})
|
||||||
|
|
||||||
|
val isVirtual = VIRTUAL_FILE_SYSTEMS.contains(fileSystem)
|
||||||
|
val supports4GBFiles = SUPPORTS_4GB_FILE_SYSTEMS.contains(fileSystem)
|
||||||
|
val doesNotSupport4GBFiles = DOES_NOT_SUPPORT_4GB_FILE_SYSTEMS.contains(fileSystem)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val VIRTUAL_FILE_SYSTEMS = listOf("fuse", "sdcardfs", "tmpfs")
|
||||||
|
private val SUPPORTS_4GB_FILE_SYSTEMS = listOf("ext4", "exfat")
|
||||||
|
private val DOES_NOT_SUPPORT_4GB_FILE_SYSTEMS = listOf("fat32")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user