Refactor code for handling MagiskDB

This commit is contained in:
topjohnwu 2019-11-11 15:46:02 -05:00
parent 817cdf7113
commit 2aee0b0be0
12 changed files with 89 additions and 106 deletions

View File

@ -1,6 +1,6 @@
package com.topjohnwu.magisk.data.database package com.topjohnwu.magisk.data.database
import com.topjohnwu.magisk.data.database.base.* import com.topjohnwu.magisk.data.database.magiskdb.*
import com.topjohnwu.magisk.model.entity.MagiskLog import com.topjohnwu.magisk.model.entity.MagiskLog
import com.topjohnwu.magisk.model.entity.toLog import com.topjohnwu.magisk.model.entity.toLog
import com.topjohnwu.magisk.model.entity.toMap import com.topjohnwu.magisk.model.entity.toMap
@ -8,7 +8,7 @@ import java.util.concurrent.TimeUnit
class LogDao : BaseDao() { class LogDao : BaseDao() {
override val table = DatabaseDefinition.Table.LOG override val table = Table.LOG
fun deleteOutdated( fun deleteOutdated(
suTimeout: Long = TimeUnit.DAYS.toMillis(14) suTimeout: Long = TimeUnit.DAYS.toMillis(14)
@ -18,7 +18,7 @@ class LogDao : BaseDao() {
} }
}.ignoreElement() }.ignoreElement()
fun deleteAll() = query<Delete> {}.ignoreElement() fun deleteAll() = query<Delete>().ignoreElement()
fun fetchAll() = query<Select> { fun fetchAll() = query<Select> {
orderBy("time", Order.DESC) orderBy("time", Order.DESC)
@ -30,4 +30,4 @@ class LogDao : BaseDao() {
values(log.toMap()) values(log.toMap())
}.ignoreElement() }.ignoreElement()
} }

View File

@ -3,7 +3,10 @@ package com.topjohnwu.magisk.data.database
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.data.database.base.* import com.topjohnwu.magisk.data.database.magiskdb.Delete
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Replace
import com.topjohnwu.magisk.data.database.magiskdb.Select
import com.topjohnwu.magisk.extensions.now import com.topjohnwu.magisk.extensions.now
import com.topjohnwu.magisk.model.entity.MagiskPolicy import com.topjohnwu.magisk.model.entity.MagiskPolicy
import com.topjohnwu.magisk.model.entity.toMap import com.topjohnwu.magisk.model.entity.toMap
@ -16,7 +19,7 @@ class PolicyDao(
private val context: Context private val context: Context
) : BaseDao() { ) : BaseDao() {
override val table: String = DatabaseDefinition.Table.POLICY override val table: String = Table.POLICY
fun deleteOutdated( fun deleteOutdated(
nowSeconds: Long = TimeUnit.MILLISECONDS.toSeconds(now) nowSeconds: Long = TimeUnit.MILLISECONDS.toSeconds(now)
@ -72,4 +75,4 @@ class PolicyDao(
} }
} }
} }

View File

@ -1,10 +1,13 @@
package com.topjohnwu.magisk.data.database package com.topjohnwu.magisk.data.database
import com.topjohnwu.magisk.data.database.base.* import com.topjohnwu.magisk.data.database.magiskdb.Delete
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Replace
import com.topjohnwu.magisk.data.database.magiskdb.Select
class SettingsDao : BaseDao() { class SettingsDao : BaseDao() {
override val table = DatabaseDefinition.Table.SETTINGS override val table = Table.SETTINGS
fun delete(key: String) = query<Delete> { fun delete(key: String) = query<Delete> {
condition { equals("key", key) } condition { equals("key", key) }
@ -19,4 +22,4 @@ class SettingsDao : BaseDao() {
condition { equals("key", key) } condition { equals("key", key) }
}.map { it.firstOrNull()?.values?.firstOrNull()?.toIntOrNull() ?: default } }.map { it.firstOrNull()?.values?.firstOrNull()?.toIntOrNull() ?: default }
} }

View File

@ -1,10 +1,13 @@
package com.topjohnwu.magisk.data.database package com.topjohnwu.magisk.data.database
import com.topjohnwu.magisk.data.database.base.* import com.topjohnwu.magisk.data.database.magiskdb.Delete
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Replace
import com.topjohnwu.magisk.data.database.magiskdb.Select
class StringDao : BaseDao() { class StringDao : BaseDao() {
override val table = DatabaseDefinition.Table.STRINGS override val table = Table.STRINGS
fun delete(key: String) = query<Delete> { fun delete(key: String) = query<Delete> {
condition { equals("key", key) } condition { equals("key", key) }
@ -19,4 +22,4 @@ class StringDao : BaseDao() {
condition { equals("key", key) } condition { equals("key", key) }
}.map { it.firstOrNull()?.values?.firstOrNull() ?: default } }.map { it.firstOrNull()?.values?.firstOrNull() ?: default }
} }

View File

@ -1,15 +0,0 @@
package com.topjohnwu.magisk.data.database.base
abstract class BaseDao {
abstract val table: String
inline fun <reified Builder : MagiskQueryBuilder> query(builder: Builder.() -> Unit) =
Builder::class.java.newInstance()
.apply { table = this@BaseDao.table }
.apply(builder)
.toString()
.let { MagiskQuery(it) }
.query()
}

View File

@ -1,30 +0,0 @@
package com.topjohnwu.magisk.data.database.base
import androidx.annotation.AnyThread
import com.topjohnwu.superuser.Shell
import io.reactivex.Single
object DatabaseDefinition {
object Table {
const val POLICY = "policies"
const val LOG = "logs"
const val SETTINGS = "settings"
const val STRINGS = "strings"
}
}
@AnyThread
fun MagiskQuery.query() = query.su()
fun String.suRaw() = Single.fromCallable { Shell.su(this).exec().out }
fun String.su() = suRaw().map { it.toMap() }
fun List<String>.toMap() = map { it.split(Regex("\\|")) }
.map { it.toMapInternal() }
private fun List<String>.toMapInternal() = map { it.split("=", limit = 2) }
.filter { it.size == 2 }
.map { Pair(it[0], it[1]) }
.toMap()

View File

@ -1,5 +0,0 @@
package com.topjohnwu.magisk.data.database.base
inline class MagiskQuery(private val _query: String) {
val query get() = "magisk --sqlite '$_query'"
}

View File

@ -0,0 +1,44 @@
package com.topjohnwu.magisk.data.database.magiskdb
import androidx.annotation.StringDef
import com.topjohnwu.superuser.Shell
import io.reactivex.Single
abstract class BaseDao {
object Table {
const val POLICY = "policies"
const val LOG = "logs"
const val SETTINGS = "settings"
const val STRINGS = "strings"
}
@StringDef(Table.POLICY, Table.LOG, Table.SETTINGS, Table.STRINGS)
@Retention(AnnotationRetention.SOURCE)
annotation class TableStrict
@TableStrict
abstract val table: String
inline fun <reified Builder : Query.Builder> query(builder: Builder.() -> Unit = {}) =
Builder::class.java.newInstance()
.apply { table = this@BaseDao.table }
.apply(builder)
.toString()
.let { Query(it) }
.query()
}
fun Query.query() = query.su()
private fun String.suRaw() = Single.fromCallable { Shell.su(this).exec().out }
private fun String.su() = suRaw().map { it.toMap() }
private fun List<String>.toMap() = map { it.split(Regex("\\|")) }
.map { it.toMapInternal() }
private fun List<String>.toMapInternal() = map { it.split("=", limit = 2) }
.filter { it.size == 2 }
.map { Pair(it[0], it[1]) }
.toMap()

View File

@ -1,27 +1,17 @@
package com.topjohnwu.magisk.data.database.base package com.topjohnwu.magisk.data.database.magiskdb
import androidx.annotation.StringDef import androidx.annotation.StringDef
import com.topjohnwu.magisk.data.database.base.Order.Companion.ASC
import com.topjohnwu.magisk.data.database.base.Order.Companion.DESC
interface MagiskQueryBuilder { class Query(private val _query: String) {
val query get() = "magisk --sqlite '$_query'"
val requestType: String interface Builder {
var table: String val requestType: String
var table: String
companion object {
inline operator fun <reified Builder : MagiskQueryBuilder> invoke(builder: Builder.() -> Unit): MagiskQuery =
Builder::class.java.newInstance()
.apply(builder)
.toString()
.let {
MagiskQuery(it)
}
} }
} }
class Delete : MagiskQueryBuilder { class Delete : Query.Builder {
override val requestType: String = "DELETE FROM" override val requestType: String = "DELETE FROM"
override var table = "" override var table = ""
@ -36,7 +26,7 @@ class Delete : MagiskQueryBuilder {
} }
} }
class Select : MagiskQueryBuilder { class Select : Query.Builder {
override val requestType: String get() = "SELECT $fields FROM" override val requestType: String get() = "SELECT $fields FROM"
override lateinit var table: String override lateinit var table: String
@ -69,7 +59,7 @@ class Replace : Insert() {
override val requestType: String = "REPLACE INTO" override val requestType: String = "REPLACE INTO"
} }
open class Insert : MagiskQueryBuilder { open class Insert : Query.Builder {
override val requestType: String = "INSERT INTO" override val requestType: String = "INSERT INTO"
override lateinit var table: String override lateinit var table: String
@ -137,19 +127,11 @@ class Condition {
} }
} }
class Order { object Order {
const val ASC = "ASC"
@set:OrderStrict const val DESC = "DESC"
var order = DESC
var field = ""
companion object {
const val ASC = "ASC"
const val DESC = "DESC"
}
} }
@StringDef(ASC, DESC) @StringDef(Order.ASC, Order.DESC)
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class OrderStrict annotation class OrderStrict

View File

@ -2,11 +2,11 @@ package com.topjohnwu.magisk.data.repository
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.data.database.LogDao import com.topjohnwu.magisk.data.database.LogDao
import com.topjohnwu.magisk.data.database.base.suRaw
import com.topjohnwu.magisk.extensions.toSingle import com.topjohnwu.magisk.extensions.toSingle
import com.topjohnwu.magisk.model.entity.MagiskLog import com.topjohnwu.magisk.model.entity.MagiskLog
import com.topjohnwu.magisk.model.entity.WrappedMagiskLog import com.topjohnwu.magisk.model.entity.WrappedMagiskLog
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import io.reactivex.Single
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -18,8 +18,9 @@ class LogRepository(
.map { it.sortByDescending { it.date.time }; it } .map { it.sortByDescending { it.date.time }; it }
.map { it.wrap() } .map { it.wrap() }
fun fetchMagiskLogs() = "tail -n 5000 ${Const.MAGISK_LOG}".suRaw() fun fetchMagiskLogs() = Single.fromCallable {
.filter { it.isNotEmpty() } Shell.su("tail -n 5000 ${Const.MAGISK_LOG}").exec().out
}.filter { it.isNotEmpty() }
fun clearLogs() = logDao.deleteAll() fun clearLogs() = logDao.deleteAll()
fun clearOutdated() = logDao.deleteOutdated() fun clearOutdated() = logDao.deleteOutdated()
@ -37,4 +38,4 @@ class LogRepository(
} }
} }

View File

@ -3,7 +3,6 @@ package com.topjohnwu.magisk.data.repository
import android.content.pm.PackageManager import android.content.pm.PackageManager
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Info import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.data.database.base.su
import com.topjohnwu.magisk.data.network.GithubRawServices import com.topjohnwu.magisk.data.network.GithubRawServices
import com.topjohnwu.magisk.extensions.getLabel import com.topjohnwu.magisk.extensions.getLabel
import com.topjohnwu.magisk.extensions.packageName import com.topjohnwu.magisk.extensions.packageName
@ -57,7 +56,7 @@ class MagiskRepository(
.toList() .toList()
fun toggleHide(isEnabled: Boolean, packageName: String, process: String) = fun toggleHide(isEnabled: Boolean, packageName: String, process: String) =
"magiskhide --%s %s %s".format(isEnabled.state, packageName, process).su().ignoreElement() Shell.su("magiskhide --${isEnabled.state} $packageName $process").submit()
private val Boolean.state get() = if (this) "add" else "rm" private val Boolean.state get() = if (this) "add" else "rm"

View File

@ -90,9 +90,7 @@ class HideViewModel(
.toList() .toList()
.map { it to items.calculateDiff(it) } .map { it to items.calculateDiff(it) }
private fun toggleItem(item: HideProcessRvItem) = magiskRepo private fun toggleItem(item: HideProcessRvItem) =
.toggleHide(item.isHidden.value, item.packageName, item.process) magiskRepo.toggleHide(item.isHidden.value, item.packageName, item.process)
.subscribeK()
.add()
} }