Separate core codebase into its own module

- Separate UI specific code and resources outside of the core
  application logic
- Allow most of the code to move forward and use KSP for annotation
  processing and isolate rotton code that is stuck with databinding
- Make full UI rewrite more feasible
This commit is contained in:
topjohnwu 2024-07-04 00:02:42 -07:00
parent f90c548f27
commit 3e38b8fed1
223 changed files with 344 additions and 318 deletions

10
app/.gitignore vendored
View File

@ -1,11 +1 @@
*.iml
.gradle
/local.properties
.idea/
/build
*.hprof
.externalNativeBuild/
*.apk
src/*/assets
src/*/jniLibs
src/*/resources

View File

@ -6,6 +6,8 @@ plugins {
id("androidx.navigation.safeargs.kotlin")
}
setupAppCommon()
kapt {
correctErrorTypes = true
useBuildCache = true
@ -13,9 +15,6 @@ kapt {
javacOptions {
option("-Xmaxerrs", 1000)
}
arguments {
arg("room.incremental", "true")
}
}
android {
@ -26,10 +25,6 @@ android {
vectorDrawables.useSupportLibrary = true
versionName = Config.version
versionCode = Config.versionCode
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
debugSymbolLevel = "FULL"
}
}
buildTypes {
@ -42,67 +37,16 @@ android {
buildFeatures {
dataBinding = true
aidl = true
}
packaging {
resources {
excludes += "/META-INF/*"
excludes += "/META-INF/versions/**"
excludes += "/org/bouncycastle/**"
excludes += "org/apache/commons/**"
excludes += "/kotlin/**"
excludes += "/kotlinx/**"
excludes += "/okhttp3/**"
excludes += "/*.txt"
excludes += "/*.bin"
excludes += "/*.json"
}
}
}
setupApp()
configurations.all {
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7")
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8")
}
dependencies {
implementation(project(":app:shared"))
implementation(project(":app:core"))
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
implementation("com.jakewharton.timber:timber:5.0.1")
implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1")
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0")
implementation("dev.rikka.rikkax.insets:insets:1.3.0")
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.2")
implementation("io.noties.markwon:core:4.6.2")
implementation("org.apache.commons:commons-compress:1.26.2")
val vLibsu = "6.0.0"
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
implementation("com.github.topjohnwu.libsu:service:${vLibsu}")
implementation("com.github.topjohnwu.libsu:nio:${vLibsu}")
val vRetrofit = "2.11.0"
implementation("com.squareup.retrofit2:retrofit:${vRetrofit}")
implementation("com.squareup.retrofit2:converter-moshi:${vRetrofit}")
implementation("com.squareup.retrofit2:converter-scalars:${vRetrofit}")
val vOkHttp = "4.12.0"
implementation("com.squareup.okhttp3:okhttp:${vOkHttp}")
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}")
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
val vMoshi = "1.15.1"
implementation("com.squareup.moshi:moshi:${vMoshi}")
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
val vRoom = "2.6.1"
implementation("androidx.room:room-runtime:${vRoom}")
implementation("androidx.room:room-ktx:${vRoom}")
kapt("androidx.room:room-compiler:${vRoom}")
val vNav = "2.7.7"
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
@ -110,12 +54,11 @@ dependencies {
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.fragment:fragment-ktx:1.8.0")
implementation("androidx.transition:transition:1.5.0")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.fragment:fragment-ktx:1.8.1")
// Make sure kapt runs with a proper kotlin-stdlib
kapt(kotlin("stdlib"))
}

4
app/core/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/build
src/*/assets
src/*/jniLibs
src/*/resources

73
app/core/build.gradle.kts Normal file
View File

@ -0,0 +1,73 @@
plugins {
id("com.android.library")
kotlin("android")
kotlin("plugin.parcelize")
id("com.google.devtools.ksp")
}
setupCoreLib()
ksp {
arg("room.generateKotlin", "true")
}
android {
namespace = "com.topjohnwu.magisk.core"
defaultConfig {
vectorDrawables.useSupportLibrary = true
buildConfigField("String", "APP_PACKAGE_NAME", "\"com.topjohnwu.magisk\"")
buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}")
buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"")
buildConfigField("int", "STUB_VERSION", Config.stubVersion)
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
debugSymbolLevel = "FULL"
}
}
buildFeatures {
aidl = true
buildConfig = true
}
}
dependencies {
api(project(":app:shared"))
api("com.jakewharton.timber:timber:5.0.1")
api("io.noties.markwon:core:4.6.2")
implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1")
implementation("org.apache.commons:commons-compress:1.26.2")
val vLibsu = "6.0.0"
api("com.github.topjohnwu.libsu:core:${vLibsu}")
api("com.github.topjohnwu.libsu:service:${vLibsu}")
api("com.github.topjohnwu.libsu:nio:${vLibsu}")
val vRetrofit = "2.11.0"
implementation("com.squareup.retrofit2:retrofit:${vRetrofit}")
implementation("com.squareup.retrofit2:converter-moshi:${vRetrofit}")
implementation("com.squareup.retrofit2:converter-scalars:${vRetrofit}")
val vOkHttp = "4.12.0"
implementation("com.squareup.okhttp3:okhttp:${vOkHttp}")
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}")
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
val vMoshi = "1.15.1"
implementation("com.squareup.moshi:moshi:${vMoshi}")
ksp("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
val vRoom = "2.6.1"
implementation("androidx.room:room-runtime:${vRoom}")
implementation("androidx.room:room-ktx:${vRoom}")
ksp("androidx.room:room-compiler:${vRoom}")
api("androidx.appcompat:appcompat:1.7.0")
api("com.google.android.material:material:1.12.0")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.collection:collection-ktx:1.4.0")
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
implementation("androidx.lifecycle:lifecycle-process:2.8.3")
}

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<permission
android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
android:protectionLevel="signature"
tools:node="remove" />
<uses-permission
android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
tools:node="remove" />
<application
android:name=".App"
android:icon="@drawable/ic_launcher"
android:multiArch="true"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"
tools:remove="android:appComponentFactory">
<receiver
android:name=".Receiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED" />
<action android:name="android.intent.action.UID_REMOVED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<service
android:name=".Service"
android:exported="false"
android:enabled="@bool/enable_fg_service"
android:foregroundServiceType="dataSync" />
<service
android:name=".JobService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<provider
android:name=".Provider"
android:authorities="${applicationId}.provider"
android:directBootAware="true"
android:exported="false"
android:grantUriPermissions="true" />
<!-- We don't invalidate Room -->
<service
android:name="androidx.room.MultiInstanceInvalidationService"
tools:node="remove" />
<!-- We handle initialization ourselves -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
<!-- We handle profile installation ourselves -->
<receiver
android:name="androidx.profileinstaller.ProfileInstallReceiver"
tools:node="remove" />
</application>
</manifest>

View File

@ -7,8 +7,8 @@ import android.content.res.Configuration
import android.os.Bundle
import android.system.Os
import androidx.profileinstaller.ProfileInstaller
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.base.UntrackedActivity
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.utils.NetworkObserver
import com.topjohnwu.magisk.core.utils.ProcessLifecycle
@ -16,7 +16,6 @@ import com.topjohnwu.magisk.core.utils.RootUtils
import com.topjohnwu.magisk.core.utils.ShellInit
import com.topjohnwu.magisk.core.utils.refreshLocale
import com.topjohnwu.magisk.core.utils.setConfig
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.UiThreadHandler
@ -116,12 +115,12 @@ object ActivityTracker : Application.ActivityLifecycleCallbacks {
private var ref = WeakReference<Activity>(null)
override fun onActivityResumed(activity: Activity) {
if (activity is SuRequestActivity) return
if (activity is UntrackedActivity) return
ref = WeakReference(activity)
}
override fun onActivityPaused(activity: Activity) {
if (activity is SuRequestActivity) return
if (activity is UntrackedActivity) return
ref.clear()
}

View File

@ -3,14 +3,12 @@ package com.topjohnwu.magisk.core
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.repository.DBConfig
import com.topjohnwu.magisk.core.repository.PreferenceConfig
import com.topjohnwu.magisk.core.utils.refreshLocale
import com.topjohnwu.magisk.ui.theme.Theme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
@ -118,7 +116,7 @@ object Config : PreferenceConfig, DBConfig {
var safetyNotice by preference(Key.SAFETY, true)
var darkTheme by preference(Key.DARK_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
var themeOrdinal by preference(Key.THEME_ORDINAL, Theme.Piplup.ordinal)
var themeOrdinal by preference(Key.THEME_ORDINAL, 0)
private var checkUpdatePrefs by preference(Key.CHECK_UPDATES, true)
private var localePrefs by preference(Key.LOCALE, "")

View File

@ -2,7 +2,6 @@ package com.topjohnwu.magisk.core
import android.os.Build
import android.os.Process
import com.topjohnwu.magisk.BuildConfig
@Suppress("DEPRECATION")
object Const {
@ -21,7 +20,7 @@ object Const {
// Misc
val USER_ID = Process.myUid() / 100000
val APP_IS_CANARY get() = Version.isCanary(BuildConfig.VERSION_CODE)
val APP_IS_CANARY get() = Version.isCanary(BuildConfig.APP_VERSION_CODE)
object Version {
const val MIN_VERSION = "v22.0"
@ -44,7 +43,7 @@ object Const {
const val SOURCE_CODE_URL = "https://github.com/topjohnwu/Magisk"
val CHANGELOG_URL = if (APP_IS_CANARY) Info.remote.magisk.note
else "https://topjohnwu.github.io/Magisk/releases/${BuildConfig.VERSION_CODE}.md"
else "https://topjohnwu.github.io/Magisk/releases/${BuildConfig.APP_VERSION_CODE}.md"
const val GITHUB_RAW_URL = "https://raw.githubusercontent.com/"
const val GITHUB_API_URL = "https://api.github.com/"

View File

@ -10,7 +10,6 @@ import android.content.res.AssetManager
import android.content.res.Configuration
import android.content.res.Resources
import android.util.DisplayMetrics
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.ktx.unwrap

View File

@ -8,7 +8,6 @@ import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.content.Context
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.core.base.BaseJobService
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.DownloadEngine
@ -77,7 +76,7 @@ class JobService : BaseJobService() {
GlobalScope.launch(Dispatchers.IO) {
ServiceLocator.networkService.fetchUpdate()?.let {
Info.remote = it
if (Info.env.isActive && BuildConfig.VERSION_CODE < it.magisk.versionCode)
if (Info.env.isActive && BuildConfig.APP_VERSION_CODE < it.magisk.versionCode)
Notifications.updateAvailable()
jobFinished(params, false)
}

View File

@ -16,7 +16,7 @@ import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts.GetContent
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
import androidx.appcompat.app.AppCompatActivity
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.reflectField
import com.topjohnwu.magisk.core.ktx.toast
@ -30,6 +30,8 @@ interface ContentResultCallback: ActivityResultCallback<Uri>, Parcelable {
override fun onActivityResult(result: Uri)
}
interface UntrackedActivity
abstract class BaseActivity : AppCompatActivity() {
private var permissionCallback: ((Boolean) -> Unit)? = null

View File

@ -2,8 +2,8 @@ package com.topjohnwu.magisk.core.di
import android.content.Context
import com.squareup.moshi.Moshi
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.ProviderInstaller
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.utils.currentLocale
@ -67,7 +67,7 @@ fun createOkHttpClient(context: Context): OkHttpClient {
builder.addInterceptor { chain ->
val request = chain.request().newBuilder()
request.header("User-Agent", "Magisk/${BuildConfig.VERSION_CODE}")
request.header("User-Agent", "Magisk/${BuildConfig.APP_VERSION_CODE}")
request.header("Accept-Language", currentLocale.toLanguageTag())
chain.proceed(request.build())
}

View File

@ -15,11 +15,11 @@ import androidx.collection.isNotEmpty
import androidx.core.content.getSystemService
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.ActivityTracker
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.cmp
import com.topjohnwu.magisk.core.di.ServiceLocator

View File

@ -11,7 +11,6 @@ import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.model.MagiskJson
import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.Notifications
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@ -42,8 +41,10 @@ sealed class Subject : Parcelable {
MediaStoreUtils.getFile(title).uri
}
override fun pendingIntent(context: Context) =
FlashFragment.installIntent(context, file)
@IgnoredOnParcel
var piCreator: ((Context, Uri) -> PendingIntent)? = null
override fun pendingIntent(context: Context) = piCreator?.invoke(context, file)
}
@Parcelize

View File

@ -3,9 +3,9 @@ package com.topjohnwu.magisk.core.su
import android.content.Context
import android.os.Bundle
import android.widget.Toast
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.getLabel
import com.topjohnwu.magisk.core.ktx.getPackageInfo

View File

@ -3,7 +3,7 @@ package com.topjohnwu.magisk.core.su
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.ktx.getPackageInfo
@ -34,8 +34,8 @@ class SuRequestHandler(
return false
// Never allow com.topjohnwu.magisk (could be malware)
if (pkgInfo.packageName == BuildConfig.APPLICATION_ID) {
Shell.cmd("(pm uninstall ${BuildConfig.APPLICATION_ID} >/dev/null 2>&1)&").exec()
if (pkgInfo.packageName == BuildConfig.APP_PACKAGE_NAME) {
Shell.cmd("(pm uninstall ${BuildConfig.APP_PACKAGE_NAME} >/dev/null 2>&1)&").exec()
return false
}

View File

@ -5,12 +5,12 @@ import android.content.Context
import android.content.Intent
import android.widget.Toast
import androidx.annotation.WorkerThread
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Provider
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.await
import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.toast
@ -135,8 +135,8 @@ object HideAPK {
if (!xml.patchStrings {
for (i in it.indices) {
val s = it[i]
if (s.contains(APPLICATION_ID)) {
it[i] = s.replace(APPLICATION_ID, pkg)
if (s.contains(APP_PACKAGE_NAME)) {
it[i] = s.replace(APP_PACKAGE_NAME, pkg)
} else if (s.contains(PLACEHOLDER)) {
it[i] = generator.next()
} else if (s == origLabel) {
@ -236,12 +236,12 @@ object HideAPK {
activity.toast(R.string.failure, Toast.LENGTH_LONG)
}
val apk = StubApk.current(activity)
val session = APKInstall.startSession(activity, APPLICATION_ID, onFailure) {
launchApp(activity, APPLICATION_ID)
val session = APKInstall.startSession(activity, APP_PACKAGE_NAME, onFailure) {
launchApp(activity, APP_PACKAGE_NAME)
dialog.dismiss()
}
Config.suManager = ""
val cmd = "adb_pm_install $apk $APPLICATION_ID"
val cmd = "adb_pm_install $apk $APP_PACKAGE_NAME"
if (Shell.cmd(cmd).await().isSuccess) return
val success = withContext(Dispatchers.IO) {
try {

View File

@ -9,13 +9,13 @@ import android.system.OsConstants.O_WRONLY
import android.widget.Toast
import androidx.annotation.WorkerThread
import androidx.core.os.postDelayed
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.AppApkPath
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.copyAll
@ -75,7 +75,7 @@ abstract class MagiskInstallImpl protected constructor(
val alpha = "abcdefghijklmnopqrstuvwxyz"
val alphaNum = "$alpha${alpha.uppercase(Locale.ROOT)}0123456789"
val random = SecureRandom()
StringBuilder("magisk_patched-${BuildConfig.VERSION_CODE}_").run {
StringBuilder("magisk_patched-${BuildConfig.APP_VERSION_CODE}_").run {
for (i in 1..5) {
append(alphaNum[random.nextInt(alphaNum.length)])
}
@ -112,7 +112,7 @@ abstract class MagiskInstallImpl protected constructor(
private suspend fun extractFiles(): Boolean {
console.add("- Device platform: ${Const.CPU_ABI}")
console.add("- Installing: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
console.add("- Installing: ${BuildConfig.APP_VERSION_NAME} (${BuildConfig.APP_VERSION_CODE})")
installDir = localFS.getFile(context.filesDir.parent, "install")
installDir.deleteRecursively()

View File

@ -5,9 +5,9 @@ package com.topjohnwu.magisk.core.utils
import android.annotation.SuppressLint
import android.content.res.Configuration
import android.content.res.Resources
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.ActivityTracker
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.createNewResources
import com.topjohnwu.magisk.core.di.AppContext
import kotlinx.coroutines.Dispatchers

View File

@ -9,7 +9,7 @@ import android.os.Build
import android.os.Build.VERSION.SDK_INT
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toIcon
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject

View File

@ -11,9 +11,9 @@ import androidx.core.content.getSystemService
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.getBitmap

Some files were not shown because too many files have changed in this diff Show More