Fix or permit certain disk reads on UI thread
This commit is contained in:
parent
1d2c74bf2c
commit
0612f79195
6 changed files with 46 additions and 8 deletions
|
@ -79,7 +79,9 @@ class App : Application() {
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
migrateTokenFromMetadataToSettingsManager()
|
permitDiskReads {
|
||||||
|
migrateTokenFromMetadataToSettingsManager()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val settingsManager: SettingsManager by inject()
|
private val settingsManager: SettingsManager by inject()
|
||||||
|
@ -106,3 +108,21 @@ const val ANCESTRAL_RECORD_KEY = "@ancestral_record@"
|
||||||
const val GLOBAL_METADATA_KEY = "@meta@"
|
const val GLOBAL_METADATA_KEY = "@meta@"
|
||||||
|
|
||||||
fun isDebugBuild() = Build.TYPE == "userdebug"
|
fun isDebugBuild() = Build.TYPE == "userdebug"
|
||||||
|
|
||||||
|
fun <T> permitDiskReads(func: () -> T): T {
|
||||||
|
return if (isDebugBuild()) {
|
||||||
|
val oldThreadPolicy = StrictMode.getThreadPolicy()
|
||||||
|
StrictMode.setThreadPolicy(
|
||||||
|
StrictMode.ThreadPolicy.Builder(oldThreadPolicy)
|
||||||
|
.permitDiskReads()
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
func()
|
||||||
|
} finally {
|
||||||
|
StrictMode.setThreadPolicy(oldThreadPolicy)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
func()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import androidx.preference.TwoStatePreference
|
||||||
import com.stevesoltys.seedvault.R
|
import com.stevesoltys.seedvault.R
|
||||||
import com.stevesoltys.seedvault.UsbMonitor
|
import com.stevesoltys.seedvault.UsbMonitor
|
||||||
import com.stevesoltys.seedvault.isMassStorage
|
import com.stevesoltys.seedvault.isMassStorage
|
||||||
|
import com.stevesoltys.seedvault.permitDiskReads
|
||||||
import com.stevesoltys.seedvault.restore.RestoreActivity
|
import com.stevesoltys.seedvault.restore.RestoreActivity
|
||||||
import com.stevesoltys.seedvault.ui.toRelativeTime
|
import com.stevesoltys.seedvault.ui.toRelativeTime
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
@ -67,7 +68,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.settings, rootKey)
|
permitDiskReads {
|
||||||
|
setPreferencesFromResource(R.xml.settings, rootKey)
|
||||||
|
}
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
|
|
||||||
backup = findPreference("backup")!!
|
backup = findPreference("backup")!!
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.net.Uri
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.stevesoltys.seedvault.permitDiskReads
|
||||||
import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
|
import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
|
||||||
import java.util.concurrent.ConcurrentSkipListSet
|
import java.util.concurrent.ConcurrentSkipListSet
|
||||||
|
|
||||||
|
@ -25,7 +26,9 @@ private const val PREF_KEY_BACKUP_APP_BLACKLIST = "backupAppBlacklist"
|
||||||
|
|
||||||
class SettingsManager(context: Context) {
|
class SettingsManager(context: Context) {
|
||||||
|
|
||||||
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
private val prefs = permitDiskReads {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var token: Long? = null
|
private var token: Long? = null
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
|
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
|
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
|
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
|
||||||
|
import com.stevesoltys.seedvault.permitDiskReads
|
||||||
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED
|
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED
|
||||||
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED_NOT_ALLOWED
|
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED_NOT_ALLOWED
|
||||||
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED_NO_DATA
|
import com.stevesoltys.seedvault.restore.AppRestoreStatus.FAILED_NO_DATA
|
||||||
|
@ -36,7 +37,6 @@ import com.stevesoltys.seedvault.transport.requestBackup
|
||||||
import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel
|
import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel
|
||||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||||
import com.stevesoltys.seedvault.ui.notification.getAppName
|
import com.stevesoltys.seedvault.ui.notification.getAppName
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@ -67,7 +67,11 @@ internal class SettingsViewModel(
|
||||||
internal val appEditMode: LiveData<Boolean> = mAppEditMode
|
internal val appEditMode: LiveData<Boolean> = mAppEditMode
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
val scope = permitDiskReads {
|
||||||
|
// this shouldn't cause disk reads, but it still does
|
||||||
|
viewModelScope
|
||||||
|
}
|
||||||
|
scope.launch {
|
||||||
// ensures the lastBackupTime LiveData gets set
|
// ensures the lastBackupTime LiveData gets set
|
||||||
metadataManager.getLastBackupTime()
|
metadataManager.getLastBackupTime()
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,12 @@ import android.content.pm.PackageManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.stevesoltys.seedvault.transport.restore.ApkRestoreStatus.FAILED
|
import com.stevesoltys.seedvault.transport.restore.ApkRestoreStatus.FAILED
|
||||||
import com.stevesoltys.seedvault.transport.restore.ApkRestoreStatus.SUCCEEDED
|
import com.stevesoltys.seedvault.transport.restore.ApkRestoreStatus.SUCCEEDED
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
@ -101,8 +104,10 @@ internal class ApkInstaller(private val context: Context) {
|
||||||
}
|
}
|
||||||
Log.d(TAG, "Received result for $packageName: success=$success $statusMsg")
|
Log.d(TAG, "Received result for $packageName: success=$success $statusMsg")
|
||||||
|
|
||||||
// delete cached APK file
|
// delete cached APK file on I/O thread
|
||||||
cachedApk.delete()
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
cachedApk.delete()
|
||||||
|
}
|
||||||
|
|
||||||
// update status and offer result
|
// update status and offer result
|
||||||
val status = if (success) SUCCEEDED else FAILED
|
val status = if (success) SUCCEEDED else FAILED
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.stevesoltys.seedvault.R
|
import com.stevesoltys.seedvault.R
|
||||||
import com.stevesoltys.seedvault.isMassStorage
|
import com.stevesoltys.seedvault.isMassStorage
|
||||||
|
import com.stevesoltys.seedvault.permitDiskReads
|
||||||
import com.stevesoltys.seedvault.settings.BackupManagerSettings
|
import com.stevesoltys.seedvault.settings.BackupManagerSettings
|
||||||
import com.stevesoltys.seedvault.settings.FlashDrive
|
import com.stevesoltys.seedvault.settings.FlashDrive
|
||||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||||
|
@ -49,7 +50,9 @@ internal abstract class StorageViewModel(
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val storage = settingsManager.getStorage() ?: return false
|
val storage = settingsManager.getStorage() ?: return false
|
||||||
if (storage.isUsb) return true
|
if (storage.isUsb) return true
|
||||||
return storage.getDocumentFile(context).isDirectory
|
return permitDiskReads {
|
||||||
|
storage.getDocumentFile(context).isDirectory
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue