Move extensions to its own package

This commit is contained in:
topjohnwu
2019-07-28 02:10:22 -07:00
parent 42e7db8d13
commit d1ff7e0ffe
59 changed files with 91 additions and 77 deletions
@@ -18,6 +18,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView
import com.skoumal.teanity.extensions.subscribeK
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.replaceRandomWithSpecial
import com.topjohnwu.magisk.model.entity.state.IndeterminateState
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
@@ -9,6 +9,8 @@ import android.os.CancellationSignal
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.inject
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
@@ -9,6 +9,7 @@ import androidx.annotation.StringRes
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.inject
import com.topjohnwu.superuser.internal.InternalUtils
import io.reactivex.Single
import java.util.*
@@ -7,6 +7,8 @@ import android.net.Uri
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.rawResource
import com.topjohnwu.magisk.extensions.toShellCmd
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import com.topjohnwu.superuser.io.SuFile
@@ -9,6 +9,7 @@ import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.AppRepository
import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.extensions.inject
import com.topjohnwu.magisk.model.entity.MagiskPolicy
import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.entity.toLog
@@ -13,6 +13,7 @@ import android.widget.Toast
import androidx.work.*
import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.model.update.UpdateCheckService
import com.topjohnwu.net.Networking
import com.topjohnwu.superuser.Shell
@@ -1,113 +0,0 @@
package com.topjohnwu.magisk.utils
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ComponentInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.*
import android.database.Cursor
import android.net.Uri
import android.provider.OpenableColumns
import com.topjohnwu.magisk.App
import java.io.File
import java.io.FileNotFoundException
val packageName: String
get() {
val app: App by inject()
return app.packageName
}
val PackageInfo.processes
get() = activities?.processNames.orEmpty() +
services?.processNames.orEmpty() +
receivers?.processNames.orEmpty() +
providers?.processNames.orEmpty()
val Array<out ComponentInfo>.processNames get() = mapNotNull { it.processName }
val ApplicationInfo.packageInfo: PackageInfo?
get() {
val pm: PackageManager by inject()
return try {
val request = GET_ACTIVITIES or
GET_SERVICES or
GET_RECEIVERS or
GET_PROVIDERS
pm.getPackageInfo(packageName, request)
} catch (e1: Exception) {
try {
pm.activities(packageName).apply {
services = pm.services(packageName)
receivers = pm.receivers(packageName)
providers = pm.providers(packageName)
}
} catch (e2: Exception) {
null
}
}
}
val Uri.fileName: String
get() {
var name: String? = null
App.self.contentResolver.query(this, null, null, null, null)?.use { c ->
val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (nameIndex != -1) {
c.moveToFirst()
name = c.getString(nameIndex)
}
}
if (name == null && path != null) {
val idx = path!!.lastIndexOf('/')
name = path!!.substring(idx + 1)
}
return name.orEmpty()
}
fun PackageManager.activities(packageName: String) =
getPackageInfo(packageName, GET_ACTIVITIES)
fun PackageManager.services(packageName: String) =
getPackageInfo(packageName, GET_SERVICES).services
fun PackageManager.receivers(packageName: String) =
getPackageInfo(packageName, GET_RECEIVERS).receivers
fun PackageManager.providers(packageName: String) =
getPackageInfo(packageName, GET_PROVIDERS).providers
fun Context.rawResource(id: Int) = resources.openRawResource(id)
fun Context.readUri(uri: Uri) =
contentResolver.openInputStream(uri) ?: throw FileNotFoundException()
fun ApplicationInfo.findAppLabel(pm: PackageManager): String {
return pm.getApplicationLabel(this).toString().orEmpty()
}
fun Intent.startActivity(context: Context) = context.startActivity(this)
fun File.provide(context: Context = get()): Uri {
return FileProvider.getUriForFile(context, context.packageName + ".provider", this)
}
fun File.mv(destination: File) {
inputStream().writeTo(destination)
deleteRecursively()
}
fun String.toFile() = File(this)
fun Intent.chooser(title: String = "Pick an app") = Intent.createChooser(this, title)
fun Context.cachedFile(name: String) = File(cacheDir, name)
fun <Result> Cursor.toList(transformer: (Cursor) -> Result): List<Result> {
val out = mutableListOf<Result>()
while (moveToNext()) out.add(transformer(this))
return out
}
@@ -1,8 +0,0 @@
package com.topjohnwu.magisk.utils
import com.skoumal.teanity.util.KObservableField
fun KObservableField<Boolean>.toggle() {
value = !value
}
@@ -1,41 +0,0 @@
package com.topjohnwu.magisk.utils
import android.net.Uri
import androidx.core.net.toFile
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
var entry: ZipEntry? = nextEntry
while (entry != null) {
callback(entry)
entry = nextEntry
}
}
fun Uri.writeTo(file: File) = toFile().copyTo(file)
fun InputStream.writeTo(file: File) =
withStreams(this, file.outputStream()) { reader, writer -> reader.copyTo(writer) }
inline fun <In : InputStream, Out : OutputStream> withStreams(
inStream: In,
outStream: Out,
withBoth: (In, Out) -> Unit
) {
inStream.use { reader ->
outStream.use { writer ->
withBoth(reader, writer)
}
}
}
inline fun <T, R> List<T>.firstMap(mapper: (T) -> R?): R {
for (item: T in this) {
return mapper(item) ?: continue
}
throw NoSuchElementException("Collection contains no element matching the predicate.")
}
@@ -1,17 +0,0 @@
package com.topjohnwu.magisk.utils
import org.koin.core.context.GlobalContext
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
fun getKoin() = GlobalContext.get().koin
inline fun <reified T : Any> inject(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) = lazy { get<T>(qualifier, parameters) }
inline fun <reified T : Any> get(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): T = getKoin().get(qualifier, parameters)
@@ -1,84 +0,0 @@
package com.topjohnwu.magisk.utils
import androidx.collection.SparseArrayCompat
import androidx.databinding.ObservableList
import com.skoumal.teanity.extensions.subscribeK
import com.skoumal.teanity.util.DiffObservableList
import io.reactivex.disposables.Disposable
fun <T> MutableList<T>.update(newList: List<T>) {
clear()
addAll(newList)
}
fun List<String>.toShellCmd(): String {
val sb = StringBuilder()
for (s in this) {
if (s.contains(" ")) {
sb.append('"').append(s).append('"')
} else {
sb.append(s)
}
sb.append(' ')
}
sb.deleteCharAt(sb.length - 1)
return sb.toString()
}
fun <T1, T2> ObservableList<T1>.sendUpdatesTo(
target: DiffObservableList<T2>,
mapper: (List<T1>) -> List<T2>
) = addOnListChangedCallback(object :
ObservableList.OnListChangedCallback<ObservableList<T1>>() {
override fun onChanged(sender: ObservableList<T1>?) {
updateAsync(sender ?: return)
}
override fun onItemRangeRemoved(sender: ObservableList<T1>?, p0: Int, p1: Int) {
updateAsync(sender ?: return)
}
override fun onItemRangeMoved(sender: ObservableList<T1>?, p0: Int, p1: Int, p2: Int) {
updateAsync(sender ?: return)
}
override fun onItemRangeInserted(sender: ObservableList<T1>?, p0: Int, p1: Int) {
updateAsync(sender ?: return)
}
override fun onItemRangeChanged(sender: ObservableList<T1>?, p0: Int, p1: Int) {
updateAsync(sender ?: return)
}
private var updater: Disposable? = null
private fun updateAsync(sender: List<T1>) {
updater?.dispose()
updater = sender.toSingle()
.map { mapper(it) }
.map { it to target.calculateDiff(it) }
.subscribeK { target.update(it.first, it.second) }
}
})
fun <T1> ObservableList<T1>.copyNewInputInto(
target: MutableList<T1>
) = addOnListChangedCallback(object : ObservableList.OnListChangedCallback<ObservableList<T1>>() {
override fun onChanged(p0: ObservableList<T1>?) = Unit
override fun onItemRangeRemoved(p0: ObservableList<T1>?, p1: Int, p2: Int) = Unit
override fun onItemRangeMoved(p0: ObservableList<T1>?, p1: Int, p2: Int, p3: Int) = Unit
override fun onItemRangeChanged(p0: ObservableList<T1>?, p1: Int, p2: Int) = Unit
override fun onItemRangeInserted(
sender: ObservableList<T1>?,
positionStart: Int,
itemCount: Int
) {
val positionEnd = positionStart + itemCount
val addedValues = sender?.slice(positionStart until positionEnd).orEmpty()
target.addAll(addedValues)
}
})
operator fun <E> SparseArrayCompat<E>.set(key: Int, value: E) {
put(key, value)
}
@@ -1,9 +0,0 @@
package com.topjohnwu.magisk.utils
import io.reactivex.Single
import io.reactivex.functions.BiFunction
fun <T : Any> T.toSingle() = Single.just(this)
fun <T1, T2, R> zip(t1: Single<T1>, t2: Single<T2>, zipper: (T1, T2) -> R) =
Single.zip(t1, t2, BiFunction<T1, T2, R> { rt1, rt2 -> zipper(rt1, rt2) })
@@ -1,14 +0,0 @@
package com.topjohnwu.magisk.utils
import com.topjohnwu.magisk.Info
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.io.SuFileInputStream
import com.topjohnwu.superuser.io.SuFileOutputStream
import java.io.File
fun reboot(reason: String = if (Info.recovery) "recovery" else "") {
Shell.su("/system/bin/svc power reboot $reason || /system/bin/reboot $reason").submit()
}
fun File.suOutputStream() = SuFileOutputStream(this)
fun File.suInputStream() = SuFileInputStream(this)
@@ -1,27 +0,0 @@
package com.topjohnwu.magisk.utils
import android.content.res.Resources
val specialChars = arrayOf('!', '@', '#', '$', '%', '&', '?')
fun String.replaceRandomWithSpecial(): String {
var random: Char
do {
random = random()
} while (random == '.')
return replace(random, specialChars.random())
}
fun StringBuilder.appendIf(condition: Boolean, builder: StringBuilder.() -> Unit) =
if (condition) apply(builder) else this
fun Int.res(vararg args: Any): String {
val resources: Resources by inject()
return resources.getString(this, *args)
}
fun String.trimEmptyToNull(): String? = if (isBlank()) null else this
fun String.legalFilename() = replace(" ", "_").replace("'", "").replace("\"", "")
.replace("$", "").replace("`", "").replace("*", "").replace("/", "_")
.replace("#", "").replace("@", "").replace("\\", "_")
@@ -1,20 +0,0 @@
package com.topjohnwu.magisk.utils
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
val now get() = System.currentTimeMillis()
fun Long.toTime(format: DateFormat) = format.format(this).orEmpty()
fun String.toTime(format: DateFormat) = try {
format.parse(this)?.time ?: -1
} catch (e: ParseException) {
-1L
}
private val locale get() = LocaleManager.locale
val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss", locale) }
val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", locale) }
val timeFormatMedium by lazy { DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale) }
val timeFormatTime by lazy { SimpleDateFormat("h:mm a", LocaleManager.locale) }
@@ -1,14 +0,0 @@
package com.topjohnwu.magisk.utils
import android.view.View
import android.view.ViewTreeObserver
fun View.setOnViewReadyListener(callback: () -> Unit) = addOnGlobalLayoutListener(true, callback)
fun View.addOnGlobalLayoutListener(oneShot: Boolean = false, callback: () -> Unit) =
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (oneShot) viewTreeObserver.removeOnGlobalLayoutListener(this)
callback()
}
})