-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
852 additions
and
370 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package li.songe.gkd.data | ||
|
||
import kotlinx.coroutines.flow.MutableStateFlow | ||
|
||
data class UserInfo( | ||
val id: Int, | ||
val name: String, | ||
) | ||
|
||
val otherUserMapFlow = MutableStateFlow(emptyMap<Int, UserInfo>()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
app/src/main/kotlin/li/songe/gkd/shizuku/ActivityTaskManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package li.songe.gkd.shizuku | ||
|
||
import android.app.ActivityManager | ||
import android.app.IActivityTaskManager | ||
import android.view.Display | ||
import com.blankj.utilcode.util.LogUtils | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.SharingStarted | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.flow.combine | ||
import kotlinx.coroutines.flow.stateIn | ||
import kotlinx.coroutines.launch | ||
import li.songe.gkd.appScope | ||
import li.songe.gkd.data.DeviceInfo | ||
import li.songe.gkd.permission.shizukuOkState | ||
import li.songe.gkd.service.TopActivity | ||
import li.songe.gkd.util.storeFlow | ||
import li.songe.gkd.util.toast | ||
import rikka.shizuku.ShizukuBinderWrapper | ||
import rikka.shizuku.SystemServiceHelper | ||
import kotlin.reflect.full.declaredMemberFunctions | ||
import kotlin.reflect.typeOf | ||
|
||
/** | ||
* -1: invalid fc | ||
* 1: (int) -> List<Task> | ||
* 3: (int, boolean, boolean) -> List<Task> | ||
* 4: (int, boolean, boolean, int) -> List<Task> | ||
*/ | ||
private var getTasksFcType: Int? = null | ||
private fun IActivityTaskManager.compatGetTasks(maxNum: Int = 1): List<ActivityManager.RunningTaskInfo> { | ||
if (getTasksFcType == null) { | ||
val fcs = this::class.declaredMemberFunctions | ||
val parameters = fcs.find { d -> d.name == "getTasks" }?.parameters | ||
if (parameters != null) { | ||
if (parameters.size == 5 && parameters[1].type == typeOf<Int>() && parameters[2].type == typeOf<Boolean>() && parameters[3].type == typeOf<Boolean>() && parameters[4].type == typeOf<Int>()) { | ||
getTasksFcType = 4 | ||
} else if (parameters.size == 4 && parameters[1].type == typeOf<Int>() && parameters[2].type == typeOf<Boolean>() && parameters[3].type == typeOf<Boolean>()) { | ||
getTasksFcType = 3 | ||
} else if (parameters.size == 2 && parameters[1].type == typeOf<Int>()) { | ||
getTasksFcType = 1 | ||
} else { | ||
getTasksFcType = -1 | ||
LogUtils.d(DeviceInfo.instance) | ||
LogUtils.d(fcs) | ||
toast("Shizuku获取方法签名错误") | ||
} | ||
} | ||
} | ||
return try { | ||
// https://bugly.qq.com/v2/crash-reporting/crashes/d0ce46b353/106137?pid=1 | ||
// binder haven't been received | ||
when (getTasksFcType) { | ||
1 -> this.getTasks(maxNum) | ||
3 -> this.getTasks(maxNum, false, true) | ||
4 -> this.getTasks(maxNum, false, true, Display.DEFAULT_DISPLAY) | ||
else -> emptyList() | ||
} | ||
} catch (e: Throwable) { | ||
LogUtils.d(e) | ||
emptyList() | ||
} | ||
} | ||
|
||
// https://github.com/gkd-kit/gkd/issues/44 | ||
// fix java.lang.ClassNotFoundException:Didn't find class "android.app.IActivityTaskManager" on path: DexPathList | ||
interface SafeActivityTaskManager { | ||
fun compatGetTasks(maxNum: Int): List<ActivityManager.RunningTaskInfo> | ||
fun compatGetTasks(): List<ActivityManager.RunningTaskInfo> | ||
} | ||
|
||
private fun newActivityTaskManager(): SafeActivityTaskManager? { | ||
val service = SystemServiceHelper.getSystemService("activity_task") | ||
if (service == null) { | ||
LogUtils.d("shizuku 无法获取 activity_task") | ||
return null | ||
} | ||
val manager = service.let(::ShizukuBinderWrapper).let(IActivityTaskManager.Stub::asInterface) | ||
return object : SafeActivityTaskManager { | ||
override fun compatGetTasks(maxNum: Int) = manager.compatGetTasks(maxNum) | ||
override fun compatGetTasks() = manager.compatGetTasks() | ||
} | ||
} | ||
|
||
private val shizukuActivityUsedFlow by lazy { | ||
combine(shizukuOkState.stateFlow, storeFlow) { shizukuOk, store -> | ||
shizukuOk && store.enableShizukuActivity | ||
}.stateIn(appScope, SharingStarted.Eagerly, false) | ||
} | ||
|
||
private val activityTaskManagerFlow by lazy<StateFlow<SafeActivityTaskManager?>> { | ||
val stateFlow = MutableStateFlow<SafeActivityTaskManager?>(null) | ||
appScope.launch(Dispatchers.IO) { | ||
shizukuActivityUsedFlow.collect { | ||
stateFlow.value = if (it) newActivityTaskManager() else null | ||
} | ||
} | ||
stateFlow | ||
} | ||
|
||
fun shizukuCheckActivity(): Boolean { | ||
return (try { | ||
newActivityTaskManager()?.compatGetTasks(1)?.isNotEmpty() == true | ||
} catch (e: Throwable) { | ||
e.printStackTrace() | ||
false | ||
}) | ||
} | ||
|
||
fun safeGetTopActivity(): TopActivity? { | ||
if (!shizukuActivityUsedFlow.value) return null | ||
try { | ||
val taskManager = activityTaskManagerFlow.value ?: return null | ||
val top = taskManager.compatGetTasks(1).lastOrNull()?.topActivity ?: return null | ||
return TopActivity(appId = top.packageName, activityId = top.className) | ||
} catch (e: Throwable) { | ||
e.printStackTrace() | ||
return null | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
app/src/main/kotlin/li/songe/gkd/shizuku/PackageManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package li.songe.gkd.shizuku | ||
|
||
import android.content.IntentFilter | ||
import android.content.pm.IPackageManager | ||
import android.content.pm.PackageInfo | ||
import com.blankj.utilcode.util.LogUtils | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.SharingStarted | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.flow.combine | ||
import kotlinx.coroutines.flow.stateIn | ||
import kotlinx.coroutines.launch | ||
import li.songe.gkd.appScope | ||
import li.songe.gkd.permission.shizukuOkState | ||
import li.songe.gkd.util.storeFlow | ||
import rikka.shizuku.ShizukuBinderWrapper | ||
import rikka.shizuku.SystemServiceHelper | ||
import kotlin.reflect.full.declaredFunctions | ||
import kotlin.reflect.typeOf | ||
|
||
|
||
private var packageFlagsParamsLongType: Boolean? = null | ||
private fun IPackageManager.compatGetInstalledPackages( | ||
flags: Long, | ||
userId: Int | ||
): List<PackageInfo> { | ||
if (packageFlagsParamsLongType == null) { | ||
val method = this::class.declaredFunctions.find { it.name == "getInstalledPackages" }!! | ||
packageFlagsParamsLongType = method.parameters[1].type == typeOf<Long>() | ||
} | ||
return if (packageFlagsParamsLongType == true) { | ||
getInstalledPackages(flags, userId).list | ||
} else { | ||
getInstalledPackages(flags.toInt(), userId).list | ||
} | ||
} | ||
|
||
interface SafePackageManager { | ||
fun compatGetInstalledPackages(flags: Long, userId: Int): List<PackageInfo> | ||
fun getAllIntentFilters(packageName: String): List<IntentFilter> | ||
} | ||
|
||
fun newPackageManager(): SafePackageManager? { | ||
val service = SystemServiceHelper.getSystemService("package") | ||
if (service == null) { | ||
LogUtils.d("shizuku 无法获取 package") | ||
return null | ||
} | ||
val manager = service.let(::ShizukuBinderWrapper).let(IPackageManager.Stub::asInterface) | ||
return object : SafePackageManager { | ||
override fun compatGetInstalledPackages(flags: Long, userId: Int) = | ||
manager.compatGetInstalledPackages(flags, userId) | ||
|
||
override fun getAllIntentFilters(packageName: String) = | ||
manager.getAllIntentFilters(packageName).list | ||
} | ||
} | ||
|
||
val shizukuWorkProfileUsedFlow by lazy { | ||
combine(shizukuOkState.stateFlow, storeFlow) { shizukuOk, store -> | ||
shizukuOk && store.enableShizukuWorkProfile | ||
}.stateIn(appScope, SharingStarted.Eagerly, false) | ||
} | ||
|
||
val packageManagerFlow by lazy<StateFlow<SafePackageManager?>> { | ||
val stateFlow = MutableStateFlow<SafePackageManager?>(null) | ||
appScope.launch(Dispatchers.IO) { | ||
shizukuWorkProfileUsedFlow.collect { | ||
stateFlow.value = if (it) newPackageManager() else null | ||
} | ||
} | ||
stateFlow | ||
} |
Oops, something went wrong.