aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt')
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt510
1 files changed, 300 insertions, 210 deletions
diff --git a/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt b/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
index 57ec307..5f50d67 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
@@ -1,42 +1,41 @@
package moe.yuuta.workmode.access
import android.annotation.SuppressLint
+import android.annotation.SystemApi
import android.app.usage.UsageStatsManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
-import android.os.*
+import android.content.pm.ApplicationInfo
+import android.os.Bundle
+import android.os.PersistableBundle
+import android.os.Process
+import android.os.UserHandle
import android.service.quicksettings.TileService
import androidx.content.pm.PackageOZ
import com.elvishew.xlog.Logger
import com.elvishew.xlog.XLog
+import eu.chainfire.librootjava.RootIPC
import eu.chainfire.librootjava.RootJava
import eu.chainfire.libsuperuser.Shell
import moe.yuuta.workmode.BuildConfig
+import moe.yuuta.workmode.IAccessor
import moe.yuuta.workmode.R
import moe.yuuta.workmode.Setup
import moe.yuuta.workmode.suspend.SuspendTile
-import moe.yuuta.workmode.suspend.SuspendedApp
import moe.yuuta.workmode.suspend.data.ListMode
+import moe.yuuta.workmode.suspend.data.PersistableSuspendedApp
import moe.yuuta.workmode.suspend.data.Status
-import moe.yuuta.workmode.utils.BundleUtils
-import moe.yuuta.workmode.utils.ByteArraySerializer
+import moe.yuuta.workmode.suspend.data.TransferableSuspendedApp
import moe.yuuta.workmode.utils.Utils
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
+import java.text.Collator
import java.util.stream.Collectors
class WorkModeAccessor {
companion object {
- const val ACTION_GET_APP_EXTRAS = "get_app_extras"
- const val ACTION_IS_SUSPENDED = "is_suspended"
- const val ACTION_GET_LAUNCHER_EXTRAS = "get_launcher_extras"
- const val ACTION_SET_SUSPENDED = "set_suspended"
- const val ACTION_DUMP = "dump"
- const val ACTION_GET_ALL_PACKAGES_SUSPENDED_BY_WORK_MODE = "get_all_packages_suspended_by_work_mode"
- const val ACTION_APPLY = "apply"
-
@JvmStatic
fun main(vararg args: String) {
RootJava.restoreOriginalLdLibraryPath()
@@ -45,230 +44,307 @@ class WorkModeAccessor {
}
private lateinit var logger: Logger
- private lateinit var mContext: Context
- private lateinit var pmAccess: AccessLayer
+ private lateinit var mSystemContext: Context
private lateinit var mLogPath: String
private fun go(args: Array<out String>) {
- mContext = RootJava.getPackageContext(BuildConfig.APPLICATION_ID)
- pmAccess = AccessLayer(mContext)
- mContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_PROGRESS)
- .putExtra(AccessorStarter.EXTRA_SHOW_PROGRESS, true))
- var parcel = Parcel.obtain()
- val argsByteArray = ByteArraySerializer.deserialize(args[0])
- val argsParcel = Parcel.obtain()
- argsParcel.unmarshall(argsByteArray, 0, argsByteArray.size)
- argsParcel.setDataPosition(0)
- mLogPath = argsParcel.readString() ?: "/data/adb"
+ mSystemContext = RootJava.getSystemContext()
+ mLogPath = args[0]
Setup.initLogs(mLogPath)
logger = XLog.tag("Accessor").build()
+ RootIPC(BuildConfig.APPLICATION_ID, BinderService(), 0x302, 2 * 1000, true)
+ System.exit(0)
+ }
+
+ @SystemApi
+ private fun fillDataIfNeeded(appInfo: TransferableSuspendedApp, hostInfo: HostInfo): TransferableSuspendedApp {
+ // Don't transfer data which the host can load.
+ appInfo.fillData(mSystemContext.packageManager, Utils.canSafelyLoadAppInfo(appInfo, hostInfo.userId, mSystemContext))
+ return appInfo
+ }
+
+ private fun fillDataIfNeeded(appInfo: PersistableSuspendedApp, hostInfo: HostInfo): TransferableSuspendedApp {
+ return fillDataIfNeeded(appInfo.copyToSimpleTransferableInfo(), hostInfo)
+ }
+
+ private fun preExecuteNotify(hostContext: Context) {
+ hostContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_PROGRESS)
+ .putExtra(AccessorStarter.EXTRA_SHOW_PROGRESS, true))
+ }
+
+ private fun postExecuteNotify(hostContext: Context) {
try {
- // Auto uninstall the app when any piracy checker triggered more than 20 times.
- val pmap = mutableMapOf<String, Int>()
- argsParcel.readMap(pmap, pmap::class.java.classLoader)
- for (key in pmap.keys) {
- if (pmap[key]!! > 20) {
- // Only self-uninstall if user usually use the app.
- val usageLevel = getAppStandbyBucket(BuildConfig.APPLICATION_ID, mContext)
- if (usageLevel != UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
- Runnable {
- Shell.SH.run("rm -rf ${PackageOZ.decode(mContext.getString(R.string.fol_id_orig), mContext)}")
- Shell.SH.run("${PackageOZ.decode("cG0gdW5pbnN0YWxsIC0tdXNlciA=", mContext)} " +
- "${Process.myUserHandle().hashCode()} " +
- BuildConfig.APPLICATION_ID)
- }.run()
- return
- } else {
- logger.d("uL = $usageLevel, skipping.")
- }
- }
- }
- // Read #Anti-Crack data
- val folder = File(PackageOZ.decode(mContext.getString(R.string.fol_id), mContext))
- val list = folder.listFiles()
- if (list != null && list.isNotEmpty()) {
- Runnable {
- parcel.writeInt(2)
- val file = list[0]
- // File name is the creaking method
- parcel.writeString(file.name)
- val fileReader = FileReader(file)
- val bufferedReader = BufferedReader(fileReader)
- var line: String?
- val builder = StringBuilder()
- while (true) {
- line = bufferedReader.readLine()
- if (line == null) break
- builder.append(line)
- }
- bufferedReader.close()
- file.delete()
- parcel.writeString(builder.toString())
- }.run()
- } else {
- // General successful flag: 1 = success; 0 = unsuccessful
- parcel.writeByte(1)
- }
- runGo(argsParcel, parcel)
- } catch (e: Throwable) {
- logger.e("Unexpected exception caused in accessor", e)
- parcel.recycle()
- // Re-mark it as unsuccessful
- parcel = Parcel.obtain()
- parcel.writeByte(0)
- parcel.writeSerializable(e)
- }
- try {
- TileService.requestListeningState(mContext, ComponentName(mContext, SuspendTile::class.java))
- mContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_STATE)
- .setPackage(BuildConfig.APPLICATION_ID))
+ TileService.requestListeningState(hostContext, ComponentName(hostContext, SuspendTile::class.java))
+ hostContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_STATE)
+ .setPackage(BuildConfig.APPLICATION_ID))
} catch (e: Throwable) {
logger.e("Unable to refresh tile", e)
}
- System.out.println(ByteArraySerializer.serialize(parcel.marshall()))
- parcel.recycle()
- mContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_PROGRESS)
- .putExtra(AccessorStarter.EXTRA_SHOW_PROGRESS, false))
- System.exit(0)
+ hostContext.sendBroadcast(Intent(AccessorStarter.ACTION_UPDATE_UI_PROGRESS)
+ .putExtra(AccessorStarter.EXTRA_SHOW_PROGRESS, false))
}
- private fun runGo(argsParcel: Parcel, parcel: Parcel) {
- when(argsParcel.readString()) {
- ACTION_GET_APP_EXTRAS -> {
- val bundle = pmAccess.getSuspendedPackageAppExtras(argsParcel.readString() ?: "android")
- parcel.writeBundle(if (bundle != null) Bundle(bundle) else Bundle.EMPTY)
- }
- ACTION_IS_SUSPENDED -> {
- val packageNames = argsParcel.createStringArray() ?: arrayOf("android")
- var allSuspended = true
- for (packageName in packageNames) {
- if (!pmAccess.isPackageSuspended(packageName)) allSuspended = false
+ // Read #Anti-Crack data
+ private fun readErrors(result: Bundle, hostContext: Context) {
+ val folder = File(PackageOZ.decode(hostContext.getString(R.string.fol_id), hostContext))
+ val list = folder.listFiles()
+ if (list != null && list.isNotEmpty()) {
+ Runnable {
+ result.putInt(AccessorStarter.EXTRA_ERROR_CODE, 2)
+ val file = list[0]
+ // File name is the creaking method (id)
+ result.putString(AccessorStarter.EXTRA_ERROR_STATUS, file.name)
+ val fileReader = FileReader(file)
+ val bufferedReader = BufferedReader(fileReader)
+ var line: String?
+ val builder = StringBuilder()
+ while (true) {
+ line = bufferedReader.readLine()
+ if (line == null) break
+ builder.append(line)
+ }
+ bufferedReader.close()
+ file.delete()
+ result.putString(AccessorStarter.EXTRA_ERROR_MSG, builder.toString())
+ }.run()
+ } else {
+ // Fake "code" flag, it won't be used.
+ result.putInt(AccessorStarter.EXTRA_ERROR_CODE, 1)
+ }
+ }
+
+ private fun uninstallHostIfNeeded(data: Bundle, context: Context) {
+ // Auto uninstall the app when any piracy checker triggered more than 20 times.
+ val pmap = data.getSerializable(AccessorStarter.EXTRA_DAT) as HashMap<String, Int>
+ for (key in pmap.keys) {
+ if (pmap[key]!! > 20) {
+ // Only self-uninstall if user usually use the app.
+ val usageLevel = getAppStandbyBucket(BuildConfig.APPLICATION_ID, context)
+ if (usageLevel != UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
+ Runnable {
+ Shell.SH.run("rm -rf ${PackageOZ.decode(context.getString(R.string.fol_id_orig), context)}")
+ Shell.SH.run("${PackageOZ.decode("cG0gdW5pbnN0YWxsIC0tdXNlciA=", context)} " +
+ "${Process.myUserHandle().hashCode()} " +
+ BuildConfig.APPLICATION_ID)
+ }.run()
+ return
+ } else {
+ logger.d("uL = $usageLevel, skipping.")
}
- parcel.writeByte(if (allSuspended) 1 else 0)
- }
- ACTION_GET_LAUNCHER_EXTRAS -> {
- parcel.writeBundle(pmAccess.getSuspendedPackageLauncherExtras(argsParcel.readString() ?: "android") ?: Bundle.EMPTY)
}
- ACTION_SET_SUSPENDED -> {
- val packageNames = argsParcel.createStringArray() ?: arrayOf("android")
- val suspended = argsParcel.readByte() == 1.toByte()
- logger.d("Running suspend: $suspended on ${packageNames.size} packages.")
- val appExtras = argsParcel.readBundle()
- val launcherExtras = argsParcel.readBundle()
- val dialogMessage = argsParcel.readString() ?: "WorkMode"
- argsParcel.recycle()
- parcel.writeStringArray(suspend(packageNames, suspended, appExtras, launcherExtras, dialogMessage))
+ }
+ }
+
+ private fun _getPackagesSuspendedByWorkMode(pmAccess: AccessLayerUtil, apps: List<TransferableSuspendedApp>): List<TransferableSuspendedApp> {
+ val result = apps
+ .stream()
+ .filter {
+ return@filter pmAccess.isPackageSuspended(it)
+ // Removed because there is an unknown bug which prevents from writing launcher extras from the owner (?)
+ // && SuspendedApp.deserializeBundle(pmAccess.getSuspendedPackageLauncherExtras(it)).isSuspendedByWorkMode
}
- ACTION_DUMP -> {
- val pkg = argsParcel.readString() ?: "android"
- parcel.writeByte(if (pmAccess.isPackageSuspended(pkg)) 1 else 0)
- parcel.writeBundle(ShellAccessorStarter(mLogPath).getSuspendedPackageAppExtras(pkg, false))
- parcel.writeBundle(pmAccess.getSuspendedPackageLauncherExtras(pkg) ?: Bundle.EMPTY)
+ .collect(Collectors.toList())
+ result.forEach {
+ logger.d("SuspendingA-A ${it.packageName} ${it.userId}")
+ }
+ return result
+ }
+
+ private fun _getInstalledApplicationsAcrossUser(pmAccess: AccessLayerUtil, hostInfo: HostInfo, flags: Int): MutableList<TransferableSuspendedApp> {
+ val originalApplicationInfo = mutableMapOf<TransferableSuspendedApp, ApplicationInfo>()
+ val packages = pmAccess.getInstalledApplicationsAnyUser(flags).stream()
+ .map {
+ val sus = fillDataIfNeeded(PersistableSuspendedApp(UserHandle.getUserHandleForUid(it.uid).hashCode(),
+ it.packageName), hostInfo)
+ originalApplicationInfo.put(sus, it)
+ return@map sus
}
- ACTION_GET_ALL_PACKAGES_SUSPENDED_BY_WORK_MODE -> {
- parcel.writeStringList(getPackagesSuspendedByWorkMode())
+ .collect(Collectors.toList())
+ val packagesWithUserIds = pmAccess.collectUserIDs(packages)
+ val finalList = mutableListOf<TransferableSuspendedApp>()
+ for (userId in packagesWithUserIds.keys) {
+ // Create a hostContext to "enter" the target user without overriding "getUserId()" or
+ // access hidden api a lot.
+ val appsInUser = pmAccess.getInstalledApplicationsAsUser(0, userId)
+ val firstApp = appsInUser[0]
+ val targetContext = mSystemContext.createPackageContextAsUser(firstApp.packageName,
+ 0,
+ AccessLayer.createUserHandleWithUserID(userId))
+ finalList.addAll(packagesWithUserIds[userId]!!.stream()
+ .filter(Utils.buildGeneralSuspendedAppInfoFilter(targetContext))
+ .collect(Collectors.toList()))
+ }
+ val sCollator = Collator.getInstance()
+ val result = finalList.stream()
+ .sorted { aa, ab ->
+ var sa: CharSequence? = if (aa.label == null)
+ originalApplicationInfo[aa]!!.loadLabel(mSystemContext.packageManager)
+ else aa.label
+ if (sa == null) {
+ sa = aa.packageName
+ }
+ var sb: CharSequence? = if (ab.label == null)
+ originalApplicationInfo[ab]!!.loadLabel(mSystemContext.packageManager)
+ else ab.label
+ if (sb == null) {
+ sb = ab.packageName
+ }
+
+ return@sorted sCollator.compare(sa.toString(), sb.toString())
}
- ACTION_APPLY -> {
- apply(argsParcel)
+ .collect(Collectors.toList())
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
+ }
+
+ private inner class BinderService : IAccessor.Stub() {
+ override fun isSuspended(packages: MutableList<TransferableSuspendedApp>): Boolean {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ var allSuspended = true
+ for (packageInfo in packages) {
+ if (!pmAccess.isPackageSuspended(packageInfo)) allSuspended = false
}
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return allSuspended
}
- }
- private fun suspend(packageNames: Array<String>, suspended: Boolean,
- appExtras: Bundle, launcherExtras: Bundle,
- dialogMessage: String): Array<String> =
- pmAccess.setPackagesSuspended(
- packageNames,
- suspended,
- BundleUtils.toPersistableBundle(appExtras),
- BundleUtils.toPersistableBundle(launcherExtras),
- dialogMessage
- )
+ override fun getSuspendedPackageAppExtras(packageInfo: TransferableSuspendedApp): Bundle {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ val bundle = pmAccess.getSuspendedPackageAppExtras(packageInfo)
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return if (bundle != null) Bundle(bundle) else Bundle.EMPTY
+ }
- private fun getPackagesSuspendedByWorkMode(): List<String> =
- mContext.packageManager.getInstalledApplications(0)
- .stream()
- .filter(Utils.buildGeneralApplicationInfoFilter(mContext))
- .filter {
- return@filter pmAccess.isPackageSuspended(it.packageName) &&
- SuspendedApp.deserializeBundle(pmAccess.getSuspendedPackageLauncherExtras(it.packageName)).isSuspendedByWorkMode
- }
- .map {
- return@map it.packageName
- }
- .collect(Collectors.toList())
+ override fun getSuspendedPackageLauncherExtras(packageInfo: TransferableSuspendedApp): Bundle {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ val result = pmAccess.getSuspendedPackageLauncherExtras(packageInfo) ?: Bundle.EMPTY
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
+ }
+
+ override fun dump(packageInfo: TransferableSuspendedApp): DumpResult {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ logger.d("Installed applications (all users, debug): ${pmAccess.getInstalledApplicationsAnyUser(0)}")
+ val result = DumpResult(pmAccess.isPackageSuspended(packageInfo),
+ pmAccess.getSuspendedPackageLauncherExtras(packageInfo) ?: Bundle.EMPTY)
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
+ }
+
+ override fun setPackagesSuspended(
+ packages: MutableList<TransferableSuspendedApp>,
+ suspended: Boolean,
+ appExtras: PersistableBundle,
+ launcherExtras: PersistableBundle,
+ dialogMessage: String
+ ): Bundle {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ logger.d("Running suspend: $suspended on ${packages.size} packages.")
+ val result = Bundle()
+ result.putStringArray(AccessorStarter.EXTRA_DATA,
+ pmAccess.suspend(packages, suspended, appExtras, launcherExtras, dialogMessage))
+ readErrors(result, hostContext = hostInfo.hostContext)
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
+ }
- private fun apply(args: Parcel) {
- // Compare system's list and ours.
- // Blacklist:
- // System suspended -> {
- // in our list -> ON - don't care; OFF - unsuspend
- // not in our list -> unsuspend
- // }
- // System not suspended -> {
- // in our list -> ON - suspend; OFF - don't care
- // not in our list -> don't care
- // }
- // Whitelist:
- // System suspended -> {
- // in our whitelist -> unsuspend
- // not in our whitelist -> ON - don't care; OFF - unsuspend
- // }
- // System not suspended -> {
- // in our whitelist -> don't care
- // not in our whitelist -> ON - suspend; OFF - don't care
- // }
+ override fun apply(data: Bundle, ourList: Array<out TransferableSuspendedApp>, rawListMode: Int, rawStatus: Int): Bundle {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val pmAccess = AccessLayerUtil(AccessLayer(hostInfo.hostContext))
+ uninstallHostIfNeeded(data, hostInfo.hostContext)
+ val result = Bundle()
+ // Compare system's list and ours.
+ // Blacklist:
+ // System suspended -> {
+ // in our list -> ON - don't care; OFF - unsuspend
+ // not in our list -> unsuspend
+ // }
+ // System not suspended -> {
+ // in our list -> ON - suspend; OFF - don't care
+ // not in our list -> don't care
+ // }
+ // Whitelist:
+ // System suspended -> {
+ // in our whitelist -> unsuspend
+ // not in our whitelist -> ON - don't care; OFF - unsuspend
+ // }
+ // System not suspended -> {
+ // in our whitelist -> don't care
+ // not in our whitelist -> ON - suspend; OFF - don't care
+ // }
- // This is the plan for Off->On or On->On situations. If we are heading
- // Off, we just ignore all tasks which is going to suspend an app. Because
- // we need to restore.
+ // This is the plan for Off->On or On->On situations. If we are heading
+ // Off, we just ignore all tasks which is going to suspend an app. Because
+ // we need to restore.
- // We use these two lists to determine whatever an app is suspended
- // It it is suspended but not appears in systemSuspendedList, we know that
- // it is suspended by other apps, like D**ital Wellbeing, we can just override it.
- val systemSuspendedList = getPackagesSuspendedByWorkMode()
- val systemAllAppList = mContext.packageManager.getInstalledApplications(0)
+ // We use these two lists to determine whatever an app is suspended
+ // It it is suspended but not appears in systemSuspendedList, we know that
+ // it is suspended by other apps, like D**ital Wellbeing, we can just override it.
+ val systemAllAppList = _getInstalledApplicationsAcrossUser(pmAccess, hostInfo, 0)
+ val systemSuspendedList = _getPackagesSuspendedByWorkMode(pmAccess, systemAllAppList)
+ val listMode = when (rawListMode) {
+ 1 -> ListMode.BLACKLIST
+ 2 -> ListMode.WHITELIST
+ else -> throw IllegalArgumentException("Unexpected list mode")
+ }
+ val status = when (rawStatus) {
+ 1 -> Status.ON
+ 2 -> Status.OFF
+ else -> throw IllegalArgumentException("Unexpected status")
+ }
+
+ systemSuspendedList
.stream()
- .filter(Utils.buildGeneralApplicationInfoFilter(mContext))
- .map { return@map it.packageName }
- .collect(Collectors.toList())
- val ourList = args.createStringArrayList()
- val listMode = when (args.readInt()) {
- 1 -> ListMode.BLACKLIST
- 2 -> ListMode.WHITELIST
- else -> throw IllegalArgumentException("Unexpected list mode")
- }
- val status = when (args.readInt()) {
- 1 -> Status.ON
- 2 -> Status.OFF
- else -> throw IllegalArgumentException("Unexpected status")
- }
+ .forEach {
+ logger.d("SYS ${it.packageName} ${it.userId}")
+ }
- val tasks = systemAllAppList.stream()
+ val tasks = systemAllAppList.stream()
// Filter "don't care" situations, do not map them here.
.filter {
- val systemSuspended = systemSuspendedList.contains(it)
- val inOurList = ourList.contains(it)
+ val systemSuspended = systemSuspendedList.any { a ->
+ return@any a.essentiallyEqual(it)
+ }
+ val inOurList = ourList.any { a ->
+ return@any a.essentiallyEqual(it)
+ }
when (listMode) {
ListMode.BLACKLIST -> {
if (systemSuspended) {
if (inOurList) {
if (status == Status.ON) {
+ logger.d("Ignoring $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of A")
return@filter false
} else {
+ logger.d("Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B")
return@filter true
}
} else {
if (status == Status.ON) {
+ logger.d("Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of C")
return@filter true
} else {
+ logger.d("Ignoring $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of D")
return@filter false
}
}
} else {
if (status == Status.ON) {
+ logger.d("Ignoring/Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of E ($inOurList)")
return@filter inOurList
} else {
+ logger.d("Ignoring $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of F")
return@filter false
}
}
@@ -276,18 +352,23 @@ class WorkModeAccessor {
ListMode.WHITELIST -> {
if (systemSuspended) {
if (inOurList) {
+ logger.d("Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B1")
return@filter true
} else {
if (status == Status.ON) {
+ logger.d("Ignoring $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B2")
return@filter false
} else {
+ logger.d("Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B3")
return@filter true
}
}
} else {
if (status == Status.ON) {
+ logger.d("Ignoring/Including $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B4 (${!inOurList})")
return@filter !inOurList
} else {
+ logger.d("Ignoring $systemSuspended $inOurList ${it.packageName} (${it.userId}) because of B5")
return@filter false
}
}
@@ -296,7 +377,9 @@ class WorkModeAccessor {
}
// Now, map them and determine that whatever a package should be suspended or un-suspended.
.map {
- val systemSuspended = systemSuspendedList.contains(it)
+ val systemSuspended = systemSuspendedList.any { a ->
+ return@any a.essentiallyEqual(it)
+ }
when (listMode) {
ListMode.BLACKLIST -> {
if (systemSuspended) {
@@ -322,46 +405,53 @@ class WorkModeAccessor {
}
// Collect them, we will execute later.
.collect(Collectors.toList())
- // Suspend first
- if (status == Status.ON) {
- val suspendList = tasks.stream()
+ // Suspend first
+ if (status == Status.ON) {
+ val suspendList = tasks.stream()
.filter {
return@filter it.suspend
}
.map {
- return@map it.packageName
+ return@map it.packageInfo
}
.collect(Collectors.toList())
- if (suspendList.size > 0) {
- suspend(suspendList.toTypedArray(),
+ logger.d("Applying settings: suspend $suspendList")
+ if (suspendList.size > 0) {
+ pmAccess.suspend(suspendList,
true)
+ }
}
- }
- // Then unsuspand
- val unsuspendList = tasks.stream()
+ // Then unsuspand
+ val unsuspendList = tasks.stream()
.filter {
return@filter !it.suspend
}
.map {
- return@map it.packageName
+ return@map it.packageInfo
}
.collect(Collectors.toList())
- if (unsuspendList.size > 0) {
- suspend(unsuspendList.toTypedArray(),
+ logger.d("Applying settings: unsuspend $unsuspendList")
+ if (unsuspendList.size > 0) {
+ pmAccess.suspend(unsuspendList,
false)
+ }
+ readErrors(result, hostContext = hostInfo.hostContext)
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
}
- }
- private fun suspend(packageNames: Array<String>, suspended: Boolean): Array<String> =
- pmAccess.setPackagesSuspended(packageNames,
- suspended,
- PersistableBundle(),
- SuspendedApp.getDefault().serializeBundle(), // We use LauncherExtras because they are easy to read
- mContext.getString(R.string.suspended_message))
+ override fun getInstalledApplicationsAcrossUser(flags: Int): MutableList<TransferableSuspendedApp> {
+ val hostInfo = HostInfo.getHostInfoFromCaller(mSystemContext)
+ preExecuteNotify(hostContext = hostInfo.hostContext)
+ val result = _getInstalledApplicationsAcrossUser(AccessLayerUtil(AccessLayer(hostInfo.hostContext)), hostInfo, flags)
+ postExecuteNotify(hostContext = hostInfo.hostContext)
+ return result
+ }
+ }
}
private data class SuspendTask(
- val packageName: String,
+ val packageInfo: TransferableSuspendedApp,
val suspend: Boolean
)