aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt')
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt63
1 files changed, 34 insertions, 29 deletions
diff --git a/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt b/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
index 31e4622..d9eb12d 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
@@ -2,11 +2,13 @@ package moe.yuuta.workmode.access
import android.annotation.SuppressLint
import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.IPackageManager
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.os.Bundle
+import android.os.Parcel
import android.os.PersistableBundle
-import android.os.Process
import android.os.UserHandle
import android.system.Os
import androidx.content.pm.PackageOZ
@@ -23,16 +25,14 @@ import java.util.concurrent.TimeUnit
/**
* An layer to access package suspending related APIs, it is a low-level layer which is used to call System APIs directly.
- *
- * TODO: Multi-user support
*/
-internal class AccessLayer(private val mContext: Context) {
+internal class AccessLayer(internal val mContext: Context) {
private val mPM: PackageManager = mContext.packageManager
@SuppressLint("PrivateApi")
fun setPackagesSuspended(packageNames: Array<String>, suspended: Boolean,
appExtras: PersistableBundle, launcherExtras: PersistableBundle,
- dialogMessage: String): Array<String> {
+ dialogMessage: String, userId: Int): Array<String> {
val countDownLatch = CountDownLatch(1)
Thread {
// Check installation source and write the result
@@ -71,42 +71,31 @@ internal class AccessLayer(private val mContext: Context) {
countDownLatch.await(2, TimeUnit.SECONDS)
- // ApplicationPackageManager ALWAYS uses context.getOpPackageName() as the argument "callingPackage"
+ // ApplicationPackageManager ALWAYS uses hostContext.getOpPackageName() as the argument "callingPackage"
// My callingPackage MUSTN'T equals to 'android'
// If we are using packageName of 'android', system will show disabled
// by admin dialog instead of suspended dialog
// F**k Google
- val func: Method = Class.forName("android.content.pm.IPackageManager")
- .getDeclaredMethod("setPackagesSuspendedAsUser",
- Array<String>::class.java,
- Boolean::class.java,
- PersistableBundle::class.java,
- PersistableBundle::class.java,
- String::class.java,
- String::class.java,
- Int::class.java)
-
// It's an unstable design
val iPM: Field = mPM::class.java.getDeclaredField("mPM")
iPM.isAccessible = true
-
- return func.invoke(iPM.get(mPM),
- packageNames,
+ val pm = iPM.get(mPM) as IPackageManager
+ return pm.setPackagesSuspendedAsUser(packageNames,
suspended,
appExtras,
launcherExtras,
dialogMessage,
BuildConfig.APPLICATION_ID,
- UserHandle.getUserHandleForUid(mPM.getPackageUid(mContext.packageName, 0)).hashCode()) as Array<String>
+ userId) as Array<String>
}
/**
* This method will SET your UID and you WON'T BE ABLE TO GO BACK.
* Create a new process and access it.
*/
- fun getSuspendedPackageAppExtras(packageName: String): PersistableBundle? {
+ fun getSuspendedPackageAppExtras(packageName: String, userId: Int): PersistableBundle? {
Os.setuid(mPM.getPackageUid(packageName, 0))
- // ApplicationPackageManager ALWAYS uses context.getOpPackageName() as the package name
+ // ApplicationPackageManager ALWAYS uses hostContext.getOpPackageName() as the package name
// F**k Google
val func: Method = Class.forName("android.content.pm.IPackageManager")
.getDeclaredMethod("getSuspendedPackageAppExtras",
@@ -119,16 +108,32 @@ internal class AccessLayer(private val mContext: Context) {
return func.invoke(iPM.get(mPM),
packageName,
- UserHandle.getUserHandleForUid(mPM.getPackageUid(packageName, 0)).hashCode()) as PersistableBundle?
+ userId) as PersistableBundle?
}
@Throws(PackageManager.NameNotFoundException::class)
- fun isPackageSuspended(packageName: String): Boolean {
- val func: Method = PackageManager::class.java.getDeclaredMethod("isPackageSuspended",
- String::class.java)
- return func.invoke(mPM, packageName) as Boolean
+ fun isPackageSuspended(packageName: String, userId: Int): Boolean {
+ val func: Method = PackageManager::class.java.getDeclaredMethod("isPackageSuspendedForUser",
+ String::class.java,
+ Int::class.java)
+ return func.invoke(mPM, packageName, userId) as Boolean
}
- fun getSuspendedPackageLauncherExtras(packageName: String): Bundle? =
- mContext.getSystemService(LauncherApps::class.java).getSuspendedPackageLauncherExtras(packageName, Process.myUserHandle())
+ fun getSuspendedPackageLauncherExtras(packageName: String, userId: Int): Bundle? =
+ mContext.getSystemService(LauncherApps::class.java).getSuspendedPackageLauncherExtras(packageName,
+ createUserHandleWithUserID(userId))
+
+ fun getInstalledApplicationsAsUser(flags: Int, userId: Int): List<ApplicationInfo> =
+ mPM.getInstalledApplicationsAsUser(flags, userId)
+
+ companion object {
+ fun createUserHandleWithUserID(userId: Int): UserHandle {
+ val parcel = Parcel.obtain()
+ parcel.writeInt(userId)
+ // I bet that it won't change a lot
+ val userHandle = UserHandle(parcel)
+ parcel.recycle()
+ return userHandle
+ }
+ }
} \ No newline at end of file