Separate core components

This commit is contained in:
topjohnwu
2020-01-13 22:01:46 +08:00
parent ba1a2fbce4
commit 707d7b3342
134 changed files with 742 additions and 693 deletions
@@ -1,78 +0,0 @@
package com.topjohnwu.magisk.data.database
import android.content.Context
import android.content.pm.PackageManager
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Delete
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.model.entity.MagiskPolicy
import com.topjohnwu.magisk.model.entity.toMap
import com.topjohnwu.magisk.model.entity.toPolicy
import timber.log.Timber
import java.util.concurrent.TimeUnit
class PolicyDao(
private val context: Context
) : BaseDao() {
override val table: String = Table.POLICY
fun deleteOutdated(
nowSeconds: Long = TimeUnit.MILLISECONDS.toSeconds(now)
) = query<Delete> {
condition {
greaterThan("until", "0")
and {
lessThan("until", nowSeconds.toString())
}
or {
lessThan("until", "0")
}
}
}.ignoreElement()
fun delete(packageName: String) = query<Delete> {
condition {
equals("package_name", packageName)
}
}.ignoreElement()
fun delete(uid: Int) = query<Delete> {
condition {
equals("uid", uid)
}
}.ignoreElement()
fun fetch(uid: Int) = query<Select> {
condition {
equals("uid", uid)
}
}.map { it.first().toPolicySafe() }
fun update(policy: MagiskPolicy) = query<Replace> {
values(policy.toMap())
}.ignoreElement()
fun fetchAll() = query<Select> {
condition {
equals("uid/100000", Const.USER_ID)
}
}.map { it.mapNotNull { it.toPolicySafe() } }
private fun Map<String, String>.toPolicySafe(): MagiskPolicy? {
return runCatching { toPolicy(context.packageManager) }.getOrElse {
Timber.e(it)
if (it is PackageManager.NameNotFoundException) {
val uid = getOrElse("uid") { null } ?: return null
delete(uid).subscribe()
}
null
}
}
}
@@ -4,7 +4,7 @@ package com.topjohnwu.magisk.data.database
import androidx.room.Dao
import androidx.room.Query
import com.topjohnwu.magisk.model.entity.module.Repo
import com.topjohnwu.magisk.core.model.module.Repo
interface RepoBase {
@@ -64,4 +64,4 @@ interface RepoByNameDao : RepoBase {
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
}
}
@@ -1,8 +1,8 @@
package com.topjohnwu.magisk.data.database
import androidx.room.*
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.model.entity.module.Repo
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.model.module.Repo
@Database(version = 6, entities = [Repo::class, RepoEtag::class])
abstract class RepoDatabase : RoomDatabase() {
@@ -1,25 +0,0 @@
package com.topjohnwu.magisk.data.database
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Delete
import com.topjohnwu.magisk.data.database.magiskdb.Replace
import com.topjohnwu.magisk.data.database.magiskdb.Select
class SettingsDao : BaseDao() {
override val table = Table.SETTINGS
fun delete(key: String) = query<Delete> {
condition { equals("key", key) }
}.ignoreElement()
fun put(key: String, value: Int) = query<Replace> {
values("key" to key, "value" to value)
}.ignoreElement()
fun fetch(key: String, default: Int = -1) = query<Select> {
fields("value")
condition { equals("key", key) }
}.map { it.firstOrNull()?.values?.firstOrNull()?.toIntOrNull() ?: default }
}
@@ -1,25 +0,0 @@
package com.topjohnwu.magisk.data.database
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
import com.topjohnwu.magisk.data.database.magiskdb.Delete
import com.topjohnwu.magisk.data.database.magiskdb.Replace
import com.topjohnwu.magisk.data.database.magiskdb.Select
class StringDao : BaseDao() {
override val table = Table.STRINGS
fun delete(key: String) = query<Delete> {
condition { equals("key", key) }
}.ignoreElement()
fun put(key: String, value: String) = query<Replace> {
values("key" to key, "value" to value)
}.ignoreElement()
fun fetch(key: String, default: String = "") = query<Select> {
fields("value")
condition { equals("key", key) }
}.map { it.firstOrNull()?.values?.firstOrNull() ?: default }
}
@@ -1,44 +0,0 @@
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()
@@ -1,137 +0,0 @@
package com.topjohnwu.magisk.data.database.magiskdb
import androidx.annotation.StringDef
class Query(private val _query: String) {
val query get() = "magisk --sqlite '$_query'"
interface Builder {
val requestType: String
var table: String
}
}
class Delete : Query.Builder {
override val requestType: String = "DELETE FROM"
override var table = ""
private var condition = ""
fun condition(builder: Condition.() -> Unit) {
condition = Condition().apply(builder).toString()
}
override fun toString(): String {
return listOf(requestType, table, condition).joinToString(" ")
}
}
class Select : Query.Builder {
override val requestType: String get() = "SELECT $fields FROM"
override lateinit var table: String
private var fields = "*"
private var condition = ""
private var orderField = ""
fun fields(vararg newFields: String) {
if (newFields.isEmpty()) {
fields = "*"
return
}
fields = newFields.joinToString(", ")
}
fun condition(builder: Condition.() -> Unit) {
condition = Condition().apply(builder).toString()
}
fun orderBy(field: String, @OrderStrict order: String) {
orderField = "ORDER BY $field $order"
}
override fun toString(): String {
return listOf(requestType, table, condition, orderField).joinToString(" ")
}
}
class Replace : Insert() {
override val requestType: String = "REPLACE INTO"
}
open class Insert : Query.Builder {
override val requestType: String = "INSERT INTO"
override lateinit var table: String
private val keys get() = _values.keys.joinToString(",")
private val values get() = _values.values.joinToString(",") {
when (it) {
is Boolean -> if (it) "1" else "0"
is Number -> it.toString()
else -> "\"$it\""
}
}
private var _values: Map<String, Any> = mapOf()
fun values(vararg pairs: Pair<String, Any>) {
_values = pairs.toMap()
}
fun values(values: Map<String, Any>) {
_values = values
}
override fun toString(): String {
return listOf(requestType, table, "($keys) VALUES($values)").joinToString(" ")
}
}
class Condition {
private val conditionWord = "WHERE %s"
private var condition: String = ""
fun equals(field: String, value: Any) {
condition = when (value) {
is String -> "$field=\"$value\""
else -> "$field=$value"
}
}
fun greaterThan(field: String, value: String) {
condition = "$field > $value"
}
fun lessThan(field: String, value: String) {
condition = "$field < $value"
}
fun greaterOrEqualTo(field: String, value: String) {
condition = "$field >= $value"
}
fun lessOrEqualTo(field: String, value: String) {
condition = "$field <= $value"
}
fun and(builder: Condition.() -> Unit) {
condition = "($condition AND ${Condition().apply(builder).condition})"
}
fun or(builder: Condition.() -> Unit) {
condition = "($condition OR ${Condition().apply(builder).condition})"
}
override fun toString(): String {
return conditionWord.format(condition)
}
}
object Order {
const val ASC = "ASC"
const val DESC = "DESC"
}
@StringDef(Order.ASC, Order.DESC)
@Retention(AnnotationRetention.SOURCE)
annotation class OrderStrict