Skip to content

Commit

Permalink
merge upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
whp98 committed Jul 18, 2023
2 parents 8187974 + e98f8a4 commit 81876f8
Show file tree
Hide file tree
Showing 25 changed files with 492 additions and 106 deletions.
7 changes: 4 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ android {
}

dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.biometric:biometric:1.1.0")
Expand All @@ -77,8 +77,9 @@ dependencies {
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.work:work-runtime-ktx:2.8.0")
implementation("com.google.android.material:material:1.8.0")
implementation("dev.rikka.shizuku:api:13.1.1")
implementation("dev.rikka.shizuku:provider:13.1.1")
implementation("dev.rikka.shizuku:api:13.1.4")
implementation("dev.rikka.shizuku:provider:13.1.4")
implementation("io.github.iamr0s:Dhizuku-API:2.4")
implementation("me.zhanghai.android.appiconloader:appiconloader:1.5.0")
implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3")
implementation("com.belerweb:pinyin4j:2.5.1")
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/kotlin/com/aistra/hail/HailApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.core.content.ContextCompat
import com.aistra.hail.app.AppManager
import com.aistra.hail.app.HailData
import com.aistra.hail.services.AutoFreezeService
import com.aistra.hail.utils.HDhizuku
import com.google.android.material.color.DynamicColors

class HailApp : Application() {
Expand All @@ -16,6 +17,7 @@ class HailApp : Application() {
app = this
DynamicColors.applyToActivitiesIfAvailable(app)
// DirtyDataUpdater.update(app)
if (HailData.workingMode.startsWith(HailData.DHIZUKU)) HDhizuku.init()
}

fun setAutoFreezeService(enabled: Boolean? = null) {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/com/aistra/hail/app/AppInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AppInfo(
val applicationInfo: ApplicationInfo? get() = HPackages.getApplicationInfoOrNull(packageName)
val name get() = applicationInfo?.loadLabel(app.packageManager) ?: packageName

var state: Int = getCurrentState()
var state: Int = STATE_UNKNOWN
fun getCurrentState(): Int = when {
applicationInfo == null -> STATE_UNKNOWN
AppManager.isAppFrozen(packageName) -> STATE_FROZEN
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/kotlin/com/aistra/hail/app/AppManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.aistra.hail.app

import android.content.Intent
import com.aistra.hail.BuildConfig
import com.aistra.hail.utils.HDhizuku
import com.aistra.hail.utils.HPackages
import com.aistra.hail.utils.HPolicy
import com.aistra.hail.utils.HShell
Expand All @@ -14,13 +15,15 @@ object AppManager {
val lockScreen: Boolean
get() = when {
HailData.workingMode.startsWith(HailData.OWNER) -> HPolicy.lockScreen
HailData.workingMode.startsWith(HailData.DHIZUKU) -> HDhizuku.lockScreen
HailData.workingMode.startsWith(HailData.SU) -> HShell.lockScreen
HailData.workingMode.startsWith(HailData.SHIZUKU) -> HShizuku.lockScreen
else -> false
}

fun isAppFrozen(packageName: String): Boolean = when {
HailData.workingMode == HailData.MODE_OWNER_HIDE -> HPolicy.isAppHidden(packageName)
HailData.workingMode == HailData.MODE_DHIZUKU_HIDE -> HDhizuku.isAppHidden(packageName)
HailData.workingMode == HailData.MODE_SHIZUKU_HIDE -> HShizuku.isAppHidden(packageName)
HailData.workingMode.endsWith(HailData.SUSPEND) -> HPackages.isAppSuspended(packageName)
else -> HPackages.isAppDisabled(packageName)
Expand All @@ -30,6 +33,8 @@ object AppManager {
packageName != BuildConfig.APPLICATION_ID && when (HailData.workingMode) {
HailData.MODE_OWNER_HIDE -> HPolicy.setAppHidden(packageName, frozen)
HailData.MODE_OWNER_SUSPEND -> HPolicy.setAppSuspended(packageName, frozen)
HailData.MODE_DHIZUKU_HIDE -> HDhizuku.setAppHidden(packageName, frozen)
HailData.MODE_DHIZUKU_SUSPEND -> HDhizuku.setAppSuspended(packageName, frozen)
HailData.MODE_SU_DISABLE -> HShell.setAppDisabled(packageName, frozen)
HailData.MODE_SU_SUSPEND -> HShell.setAppSuspended(packageName, frozen)
HailData.MODE_SHIZUKU_DISABLE -> HShizuku.setAppDisabled(packageName, frozen)
Expand All @@ -44,10 +49,17 @@ object AppManager {
packageName
)
) return true

HailData.workingMode.startsWith(HailData.DHIZUKU) -> if (HDhizuku.uninstallApp(
packageName
)
) return true

HailData.workingMode.startsWith(HailData.SU) -> if (HShell.uninstallApp(
packageName
)
) return true

HailData.workingMode.startsWith(HailData.SHIZUKU) -> if (HShizuku.uninstallApp(
packageName
)
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/kotlin/com/aistra/hail/app/HailData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ object HailData {
const val WORKING_MODE = "working_mode"
const val MODE_DEFAULT = "default"
const val OWNER = "owner_"
const val DHIZUKU = "dhizuku_"
const val SU = "su_"
const val SHIZUKU = "shizuku_"
private const val DISABLE = "disable"
private const val HIDE = "hide"
const val SUSPEND = "suspend"
const val MODE_OWNER_HIDE = OWNER + HIDE
const val MODE_OWNER_SUSPEND = OWNER + SUSPEND
const val MODE_DHIZUKU_HIDE = DHIZUKU + HIDE
const val MODE_DHIZUKU_SUSPEND = DHIZUKU + SUSPEND
const val MODE_SU_DISABLE = SU + DISABLE
const val MODE_SU_SUSPEND = SU + SUSPEND
const val MODE_SHIZUKU_DISABLE = SHIZUKU + DISABLE
Expand Down
11 changes: 3 additions & 8 deletions app/src/main/kotlin/com/aistra/hail/ui/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,9 @@ class MainActivity : AppCompatActivity(), NavController.OnDestinationChangedList

override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
when (errorCode) {
BiometricPrompt.ERROR_NO_BIOMETRICS, BiometricPrompt.ERROR_HW_NOT_PRESENT -> unlock()
BiometricPrompt.ERROR_NEGATIVE_BUTTON, BiometricPrompt.ERROR_USER_CANCELED -> finishAndRemoveTask()
else -> {
HUI.showToast(errString)
finishAndRemoveTask()
}
}
HUI.showToast(errString)
if (errorCode == BiometricPrompt.ERROR_NO_BIOMETRICS) unlock()
else finishAndRemoveTask()
}

override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.aistra.hail.ui.settings
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.SystemClock
import android.provider.Settings
import android.view.*
import android.widget.FrameLayout
Expand All @@ -13,6 +12,7 @@ import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.aistra.hail.HailApp.Companion.app
Expand All @@ -23,11 +23,18 @@ import com.aistra.hail.app.HailData
import com.aistra.hail.databinding.DialogInputBinding
import com.aistra.hail.utils.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rosan.dhizuku.api.Dhizuku
import com.rosan.dhizuku.api.DhizukuRequestPermissionListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.trySendBlocking
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import rikka.shizuku.Shizuku


class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener,
MenuProvider {
override fun onCreateView(
Expand Down Expand Up @@ -116,6 +123,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
HailApi.getIntentForTag(HailApi.ACTION_FREEZE_TAG, tag)
)
}.setNegativeButton(android.R.string.cancel, null).show()

1 -> MaterialAlertDialogBuilder(requireActivity()).setTitle(R.string.action_unfreeze_tag)
.setItems(HailData.tags.map { it.first }.toTypedArray()) { _, index ->
val tag = HailData.tags[index].first
Expand All @@ -128,6 +136,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
HailApi.getIntentForTag(HailApi.ACTION_UNFREEZE_TAG, tag)
)
}.setNegativeButton(android.R.string.cancel, null).show()

2 -> HShortcuts.addPinShortcut(
AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_round_frozen_shortcut
Expand All @@ -136,6 +145,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
getString(R.string.action_freeze_all),
Intent(HailApi.ACTION_FREEZE_ALL)
)

3 -> HShortcuts.addPinShortcut(
AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_round_unfrozen_shortcut
Expand All @@ -144,6 +154,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
getString(R.string.action_unfreeze_all),
Intent(HailApi.ACTION_UNFREEZE_ALL)
)

4 -> HShortcuts.addPinShortcut(
AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_round_frozen_shortcut
Expand All @@ -152,6 +163,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
getString(R.string.action_freeze_non_whitelisted),
Intent(HailApi.ACTION_FREEZE_NON_WHITELISTED)
)

5 -> HShortcuts.addPinShortcut(
AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_outline_lock_shortcut
Expand All @@ -160,6 +172,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
getString(R.string.action_lock),
Intent(HailApi.ACTION_LOCK)
)

6 -> HShortcuts.addPinShortcut(
AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_outline_lock_shortcut
Expand All @@ -183,10 +196,41 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
.show()
return false
}

mode.startsWith(HailData.DHIZUKU) -> return runCatching {
Dhizuku.init(app)
when {
Dhizuku.isPermissionGranted() -> true
else -> {
lifecycleScope.launch {
val result = callbackFlow {
Dhizuku.requestPermission(object :
DhizukuRequestPermissionListener() {
override fun onRequestPermission(grantResult: Int) {
trySendBlocking(grantResult == PackageManager.PERMISSION_GRANTED)
}
})
awaitClose()
}.first()
if (result && preference is ListPreference) {
preference.value = mode
if (HTarget.O) HDhizuku.setDelegatedScopes()
}
}
false
}
}
}.getOrElse {
HLog.e(it)
HUI.showToast(R.string.permission_denied)
false
}

mode.startsWith(HailData.SU) -> if (!HShell.checkSU) {
HUI.showToast(R.string.permission_denied)
return false
}

mode.startsWith(HailData.SHIZUKU) -> return runCatching {
when {
Shizuku.isPreV11() -> throw IllegalStateException("unsupported shizuku version")
Expand All @@ -195,12 +239,25 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
HUI.showToast(R.string.permission_denied)
false
}

else -> {
Shizuku.requestPermission(0)
while (Shizuku.checkSelfPermission() != PackageManager.PERMISSION_GRANTED) {
SystemClock.sleep(1000)
lifecycleScope.launch {
val result = callbackFlow {
val shizukuRequestCode = 0
val listener =
Shizuku.OnRequestPermissionResultListener { requestCode, grantResult ->
if (requestCode != shizukuRequestCode) return@OnRequestPermissionResultListener
trySendBlocking(grantResult == PackageManager.PERMISSION_GRANTED)
}
Shizuku.addRequestPermissionResultListener(listener)
Shizuku.requestPermission(shizukuRequestCode)
awaitClose {
Shizuku.removeRequestPermissionResultListener(listener)
}
}.first()
if (result && preference is ListPreference) preference.value = mode
}
true
false
}
}
}.getOrElse {
Expand Down Expand Up @@ -246,6 +303,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
}
}.setNegativeButton(android.R.string.cancel, null).show()
}

R.id.action_help -> HUI.openLink(HailData.URL_README)
}
return false
Expand Down
92 changes: 92 additions & 0 deletions app/src/main/kotlin/com/aistra/hail/utils/HDhizuku.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.aistra.hail.utils

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import com.aistra.hail.HailApp.Companion.app
import com.rosan.dhizuku.api.Dhizuku
import com.rosan.dhizuku.shared.DhizukuVariables
import org.lsposed.hiddenapibypass.HiddenApiBypass

object HDhizuku {
private val dpm = app.getSystemService<DevicePolicyManager>()!!

fun init() {
if (Dhizuku.init(app) && Dhizuku.isPermissionGranted() && HTarget.O) setDelegatedScopes()
}

@RequiresApi(Build.VERSION_CODES.O)
fun setDelegatedScopes() {
if (!Dhizuku.getDelegatedScopes().contains(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS))
Dhizuku.setDelegatedScopes(arrayOf(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS))
}

val lockScreen: Boolean
get() = runCatching {
dpm.lockNow()
true
}.getOrDefault(false)

fun isAppHidden(packageName: String): Boolean = runCatching {
HTarget.O && dpm::class.java.getMethod(
"isApplicationHidden", ComponentName::class.java, String::class.java
).invoke(dpm, null, packageName) as Boolean
}.getOrDefault(false)

fun setAppHidden(packageName: String, hidden: Boolean): Boolean = runCatching {
HTarget.O && dpm::class.java.getMethod(
"setApplicationHidden",
ComponentName::class.java,
String::class.java,
Boolean::class.java
).invoke(dpm, null, packageName, hidden) as Boolean
}.getOrDefault(false)

fun setAppSuspended(packageName: String, suspended: Boolean): Boolean = runCatching {
HTarget.O && (dpm::class.java.getMethod(
"setPackagesSuspended",
ComponentName::class.java,
Array<String>::class.java,
Boolean::class.java
).invoke(dpm, null, arrayOf(packageName), suspended) as Array<*>).isEmpty()
}.getOrDefault(false)

@SuppressLint("PrivateApi")
fun uninstallApp(packageName: String): Boolean = runCatching {
val installer = app.packageManager.packageInstaller
if (HTarget.P) HiddenApiBypass.setHiddenApiExemptions("")
val mPackageName = installer::class.java.getDeclaredField("mInstallerPackageName")
mPackageName.isAccessible = true
if (mPackageName.get(installer) != DhizukuVariables.PACKAGE_NAME) {
mPackageName.set(installer, DhizukuVariables.PACKAGE_NAME)
val mInstaller = installer::class.java.getDeclaredField("mInstaller")
mInstaller.isAccessible = true
val origin = mInstaller.get(installer)
val proxy = Class.forName("android.content.pm.IPackageInstaller\$Stub")
.getMethod("asInterface", IBinder::class.java)
.invoke(
null,
Dhizuku.binderWrapper(
origin::class.java.getMethod("asBinder").invoke(origin) as IBinder
)
)
mInstaller.set(installer, proxy)
}
installer.uninstall(
packageName,
PendingIntent.getActivity(
app,
0,
Intent(),
PendingIntent.FLAG_IMMUTABLE
).intentSender
)
true
}.getOrDefault(false)
}
4 changes: 4 additions & 0 deletions app/src/main/res/raw/licenses
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Kotlin (Apache 2.0): https://kotlinlang.org

Material Components for Android (Apache 2.0): https://github.com/material-components/material-components-android

Dhizuku (GPL 3.0): https://github.com/iamr0s/Dhizuku

Dhizuku-API (MIT): https://github.com/iamr0s/Dhizuku-API

Shizuku (Apache 2.0): https://github.com/RikkaApps/Shizuku

Shizuku-API (MIT): https://github.com/RikkaApps/Shizuku-API
Expand Down
Loading

0 comments on commit 81876f8

Please sign in to comment.