MagiskHide is no more

This commit is contained in:
topjohnwu
2021-09-12 12:40:34 -07:00
parent fc6b02f607
commit 65b0ea792e
79 changed files with 433 additions and 486 deletions
@@ -60,7 +60,7 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
R.id.homeFragment,
R.id.modulesFragment,
R.id.superuserFragment,
R.id.hideFragment,
R.id.denyFragment,
R.id.logFragment -> true
else -> false
}
@@ -170,7 +170,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
private fun getScreen(name: String?): NavDirections? {
return when (name) {
Const.Nav.SUPERUSER -> MainDirections.actionSuperuserFragment()
Const.Nav.HIDE -> MainDirections.actionHideFragment()
Const.Nav.MODULES -> MainDirections.actionModuleFragment()
Const.Nav.SETTINGS -> HomeFragmentDirections.actionHomeFragmentToSettingsFragment()
else -> null
@@ -183,7 +182,7 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
R.id.modulesFragment -> MainDirections.actionModuleFragment()
R.id.superuserFragment -> MainDirections.actionSuperuserFragment()
R.id.logFragment -> MainDirections.actionLogFragment()
R.id.hideFragment -> MainDirections.actionHideFragment()
R.id.denyFragment -> MainDirections.actionDenylistFragment()
else -> null
}
}
@@ -1,4 +1,4 @@
package com.topjohnwu.magisk.ui.hide
package com.topjohnwu.magisk.ui.deny
import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.ktx.getLabel
import com.topjohnwu.magisk.ktx.isIsolated
import com.topjohnwu.magisk.ktx.useAppZygote
class CmdlineHiddenItem(line: String) {
class CmdlineListItem(line: String) {
val packageName: String
val process: String
@@ -27,19 +27,19 @@ class CmdlineHiddenItem(line: String) {
const val ISOLATED_MAGIC = "isolated"
@SuppressLint("InlinedApi")
class HideAppInfo(info: ApplicationInfo, pm: PackageManager, hideList: List<CmdlineHiddenItem>)
: ApplicationInfo(info), Comparable<HideAppInfo> {
class AppProcessInfo(info: ApplicationInfo, pm: PackageManager, denyList: List<CmdlineListItem>)
: ApplicationInfo(info), Comparable<AppProcessInfo> {
val label = info.getLabel(pm)
val iconImage: Drawable = info.loadIcon(pm)
val processes = fetchProcesses(pm, hideList)
val processes = fetchProcesses(pm, denyList)
override fun compareTo(other: HideAppInfo) = comparator.compare(this, other)
override fun compareTo(other: AppProcessInfo) = comparator.compare(this, other)
private fun fetchProcesses(
pm: PackageManager,
hideList: List<CmdlineHiddenItem>
): List<HideProcessInfo> {
denylist: List<CmdlineListItem>
): List<ProcessInfo> {
// Fetch full PackageInfo
val baseFlag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES
val packageInfo = try {
@@ -58,9 +58,9 @@ class HideAppInfo(info: ApplicationInfo, pm: PackageManager, hideList: List<Cmdl
}
}
val hidden = hideList.filter { it.packageName == packageName || it.packageName == ISOLATED_MAGIC }
fun createProcess(name: String, pkg: String = packageName): HideProcessInfo {
return HideProcessInfo(name, pkg, hidden.any { it.process == name && it.packageName == pkg })
val enabledList = denylist.filter { it.packageName == packageName || it.packageName == ISOLATED_MAGIC }
fun createProcess(name: String, pkg: String = packageName): ProcessInfo {
return ProcessInfo(name, pkg, enabledList.any { it.process == name && it.packageName == pkg })
}
var haveAppZygote = false
@@ -90,17 +90,17 @@ class HideAppInfo(info: ApplicationInfo, pm: PackageManager, hideList: List<Cmdl
}
companion object {
private val comparator = compareBy<HideAppInfo>(
{ it.label.toLowerCase(currentLocale) },
private val comparator = compareBy<AppProcessInfo>(
{ it.label.lowercase(currentLocale) },
{ it.packageName }
)
}
}
data class HideProcessInfo(
data class ProcessInfo(
val name: String,
val packageName: String,
var isHidden: Boolean
var isEnabled: Boolean
) {
val isIsolated get() = packageName == ISOLATED_MAGIC
val isAppZygote get() = name.endsWith("_zygote")
@@ -1,4 +1,4 @@
package com.topjohnwu.magisk.ui.hide
package com.topjohnwu.magisk.ui.deny
import android.content.Context
import android.os.Bundle
@@ -11,7 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding
import com.topjohnwu.magisk.di.viewModel
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
import com.topjohnwu.magisk.ktx.addVerticalPadding
@@ -19,34 +19,34 @@ import com.topjohnwu.magisk.ktx.fixEdgeEffect
import com.topjohnwu.magisk.ktx.hideKeyboard
import com.topjohnwu.magisk.utils.MotionRevealHelper
class HideFragment : BaseUIFragment<HideViewModel, FragmentHideMd2Binding>() {
class DenyListFragment : BaseUIFragment<DenyListViewModel, FragmentDenyMd2Binding>() {
override val layoutRes = R.layout.fragment_hide_md2
override val viewModel by viewModel<HideViewModel>()
override val layoutRes = R.layout.fragment_deny_md2
override val viewModel by viewModel<DenyListViewModel>()
private var isFilterVisible
get() = binding.hideFilter.isVisible
get() = binding.processFilter.isVisible
set(value) {
if (!value) hideKeyboard()
MotionRevealHelper.withViews(binding.hideFilter, binding.hideFilterToggle, value)
MotionRevealHelper.withViews(binding.processFilter, binding.filterToggle, value)
}
override fun onAttach(context: Context) {
super.onAttach(context)
activity.setTitle(R.string.magiskhide)
activity.setTitle(R.string.denylist)
setHasOptionsMenu(true)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.hideFilterToggle.setOnClickListener {
binding.filterToggle.setOnClickListener {
isFilterVisible = true
}
binding.hideFilterInclude.hideFilterDone.setOnClickListener {
binding.appFilterInclude.filterDone.setOnClickListener {
isFilterVisible = false
}
binding.hideContent.addOnScrollListener(object : RecyclerView.OnScrollListener() {
binding.appList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard()
}
@@ -55,23 +55,23 @@ class HideFragment : BaseUIFragment<HideViewModel, FragmentHideMd2Binding>() {
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.hideContent.addVerticalPadding(
binding.appList.addVerticalPadding(
l_50,
l1 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size)
)
binding.hideContent.addSimpleItemDecoration(
binding.appList.addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
binding.hideContent.fixEdgeEffect()
binding.appList.fixEdgeEffect()
val lama = binding.hideContent.layoutManager ?: return
val lama = binding.appList.layoutManager ?: return
lama.isAutoMeasureEnabled = false
}
override fun onPreBind(binding: FragmentHideMd2Binding) = Unit
override fun onPreBind(binding: FragmentDenyMd2Binding) = Unit
override fun onBackPressed(): Boolean {
if (isFilterVisible) {
@@ -89,10 +89,10 @@ class HideFragment : BaseUIFragment<HideViewModel, FragmentHideMd2Binding>() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_focus_up -> binding.hideContent
R.id.action_focus_up -> binding.appList
.takeIf { (it.layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() ?: 0 > 10 }
?.also { it.scrollToPosition(10) }
.let { binding.hideContent }
.let { binding.appList }
.also { it.post { it.smoothScrollToPosition(0) } }
}
return super.onOptionsItemSelected(item)
@@ -1,4 +1,4 @@
package com.topjohnwu.magisk.ui.hide
package com.topjohnwu.magisk.ui.deny
import android.view.View
import android.view.ViewGroup
@@ -13,13 +13,13 @@ import com.topjohnwu.magisk.ktx.startAnimations
import com.topjohnwu.superuser.Shell
import kotlin.math.roundToInt
class HideRvItem(
val info: HideAppInfo
) : ObservableDiffRvItem<HideRvItem>(), ComparableRv<HideRvItem> {
class DenyListRvItem(
val info: AppProcessInfo
) : ObservableDiffRvItem<DenyListRvItem>(), ComparableRv<DenyListRvItem> {
override val layoutRes get() = R.layout.item_hide_md2
val processes = info.processes.map { HideProcessRvItem(it) }
val processes = info.processes.map { ProcessRvItem(it) }
@get:Bindable
var isExpanded = false
@@ -31,25 +31,24 @@ class HideRvItem(
@get:Bindable
val checkedPercent get() = (itemsChecked.toFloat() / processes.size * 100).roundToInt()
private var state: Boolean? = false
set(value) = set(value, field, { field = it }, BR.hiddenState)
private var _state: Boolean? = false
set(value) = set(value, field, { field = it }, BR.state)
@get:Bindable
var hiddenState: Boolean?
get() = state
set(value) = set(value, state, { state = it }, BR.hiddenState) {
var state: Boolean?
get() = _state
set(value) = set(value, _state, { _state = it }, BR.state) {
if (value == true) {
processes
.filterNot { it.isHidden }
.filterNot { it.isEnabled }
.filter { isExpanded || it.defaultSelection }
} else {
processes
.filter { it.isHidden }
processes.filter { it.isEnabled }
}.forEach { it.toggle() }
}
init {
processes.forEach { it.addOnPropertyChangedCallback(BR.hidden) { recalculateChecked() } }
processes.forEach { it.addOnPropertyChangedCallback(BR.enabled) { recalculateChecked() } }
addOnPropertyChangedCallback(BR.expanded) { recalculateChecked() }
recalculateChecked()
}
@@ -60,8 +59,8 @@ class HideRvItem(
}
private fun recalculateChecked() {
itemsChecked = processes.count { it.isHidden }
state = if (isExpanded) {
itemsChecked = processes.count { it.isEnabled }
_state = if (isExpanded) {
when (itemsChecked) {
0 -> false
processes.size -> true
@@ -69,7 +68,7 @@ class HideRvItem(
}
} else {
val defaultProcesses = processes.filter { it.defaultSelection }
when (defaultProcesses.count { it.isHidden }) {
when (defaultProcesses.count { it.isEnabled }) {
0 -> false
defaultProcesses.size -> true
else -> null
@@ -77,10 +76,10 @@ class HideRvItem(
}
}
override fun compareTo(other: HideRvItem) = comparator.compare(this, other)
override fun compareTo(other: DenyListRvItem) = comparator.compare(this, other)
companion object {
private val comparator = compareBy<HideRvItem>(
private val comparator = compareBy<DenyListRvItem>(
{ it.itemsChecked == 0 },
{ it.info }
)
@@ -88,34 +87,34 @@ class HideRvItem(
}
class HideProcessRvItem(
val process: HideProcessInfo
) : ObservableDiffRvItem<HideProcessRvItem>() {
class ProcessRvItem(
val process: ProcessInfo
) : ObservableDiffRvItem<ProcessRvItem>() {
override val layoutRes get() = R.layout.item_hide_process_md2
val displayName = if (process.isIsolated) "(isolated) ${process.name}" else process.name
@get:Bindable
var isHidden
get() = process.isHidden
set(value) = set(value, process.isHidden, { process.isHidden = it }, BR.hidden) {
var isEnabled
get() = process.isEnabled
set(value) = set(value, process.isEnabled, { process.isEnabled = it }, BR.enabled) {
val arg = if (it) "add" else "rm"
val (name, pkg) = process
Shell.su("magiskhide $arg $pkg \'$name\'").submit()
Shell.su("magisk --denylist $arg $pkg \'$name\'").submit()
}
fun toggle() {
isHidden = !isHidden
isEnabled = !isEnabled
}
val defaultSelection get() =
process.isIsolated || process.isAppZygote || process.name == process.packageName
override fun contentSameAs(other: HideProcessRvItem) =
process.isHidden == other.process.isHidden
override fun contentSameAs(other: ProcessRvItem) =
process.isEnabled == other.process.isEnabled
override fun itemSameAs(other: HideProcessRvItem) =
override fun itemSameAs(other: ProcessRvItem) =
process.name == other.process.name && process.packageName == other.process.packageName
}
@@ -1,4 +1,4 @@
package com.topjohnwu.magisk.ui.hide
package com.topjohnwu.magisk.ui.deny
import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
@@ -20,7 +20,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class HideViewModel : BaseViewModel(), Queryable {
class DenyListViewModel : BaseViewModel(), Queryable {
override val queryDelay = 1000L
@@ -43,11 +43,11 @@ class HideViewModel : BaseViewModel(), Queryable {
submitQuery()
}
val items = filterableListOf<HideRvItem>()
val itemBinding = itemBindingOf<HideRvItem> {
val items = filterableListOf<DenyListRvItem>()
val itemBinding = itemBindingOf<DenyListRvItem> {
it.bindExtra(BR.viewModel, this)
}
val itemInternalBinding = itemBindingOf<HideProcessRvItem> {
val itemInternalBinding = itemBindingOf<ProcessRvItem> {
it.bindExtra(BR.viewModel, this)
}
@@ -60,14 +60,14 @@ class HideViewModel : BaseViewModel(), Queryable {
state = State.LOADING
val (apps, diff) = withContext(Dispatchers.Default) {
val pm = AppContext.packageManager
val hideList = Shell.su("magiskhide ls").exec().out.map { CmdlineHiddenItem(it) }
val hideList = Shell.su("magisk --denylist ls").exec().out.map { CmdlineListItem(it) }
val apps = pm.getInstalledApplications(MATCH_UNINSTALLED_PACKAGES)
.asSequence()
.filterNot { blacklist.contains(it.packageName) }
.map { HideAppInfo(it, pm, hideList) }
.map { AppProcessInfo(it, pm, hideList) }
.filter { it.processes.isNotEmpty() }
.filter { info -> info.enabled || info.processes.any { it.isHidden } }
.map { HideRvItem(it) }
.filter { info -> info.enabled || info.processes.any { it.isEnabled } }
.map { DenyListRvItem(it) }
.toList()
.sorted()
apps to items.calculateDiff(apps)
@@ -252,14 +252,14 @@ object Magisk : BaseSettingsItem.Section() {
override val title = R.string.magisk.asText()
}
object MagiskHide : BaseSettingsItem.Toggle() {
override val title = R.string.magiskhide.asText()
override val description = R.string.settings_magiskhide_summary.asText()
override var value = Config.magiskHide
object DenyList : BaseSettingsItem.Toggle() {
override val title = R.string.denylist.asText()
override val description = R.string.settings_denylist_summary.asText()
override var value = Info.env.denyListEnforced
set(value) = setV(value, field, { field = it }) {
val cmd = if (it) "enable" else "disable"
Shell.su("magiskhide $cmd").submit { cb ->
if (cb.isSuccess) Config.magiskHide = it
Shell.su("magisk --denylist $cmd").submit { cb ->
if (cb.isSuccess) Info.env.denyListEnforced = it
else field = !it
}
}
@@ -70,8 +70,11 @@ class SettingsViewModel(
if (Info.env.isActive) {
list.addAll(listOf(
Magisk,
MagiskHide, SystemlessHosts
SystemlessHosts
))
if (Const.Version.isCanary()) {
list.add(DenyList)
}
}
// Superuser