aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt')
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt297
1 files changed, 130 insertions, 167 deletions
diff --git a/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt b/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
index 18f19d0..ac198d9 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
@@ -1,231 +1,194 @@
package moe.yuuta.workmode.access
+import android.content.ComponentName
import android.content.Context
import android.os.Bundle
-import android.os.Parcel
import android.os.PersistableBundle
+import android.service.quicksettings.TileService
+import androidx.annotation.WorkerThread
import com.elvishew.xlog.Logger
import com.elvishew.xlog.XLog
+import eu.chainfire.librootjava.RootIPCReceiver
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.getLogsPath
+import moe.yuuta.workmode.suspend.SuspendTile
import moe.yuuta.workmode.suspend.data.ListMode
import moe.yuuta.workmode.suspend.data.Status
import moe.yuuta.workmode.suspend.data.SuspendedStorage
-import moe.yuuta.workmode.utils.ByteArraySerializer
+import moe.yuuta.workmode.suspend.data.TransferableSuspendedApp
+import java.util.function.Function
import java.util.stream.Collectors
/**
* The high-level API accessor, as known as the launcher (starter) of the accessor, wraps
* the necessary start steps to launch it and deserialize the result.
*/
-open class AccessorStarter(private val mContext: Context, private val mLogPath: String) {
- private val logger: Logger = XLog.tag("AccessorStarter").build()
-
+open class AccessorStarter(private val mContext: Context, private val mService: IAccessor, private val mListener: RootIPCReceiver<IAccessor>) {
companion object {
+ private val logger: Logger = XLog.tag("AccessorStarter").build()
+
const val ACTION_UPDATE_UI_STATE = "moe.yuuta.workmode.access.ACTION_UPDATE_UI_STATE"
const val ACTION_UPDATE_UI_PROGRESS = "moe.yuuta.workmode.access.ACTION_UPDATE_UI_PROGRESS"
const val EXTRA_SHOW_PROGRESS = "moe.yuuta.workmode.access.EXTRA_SHOW_PROGRESS"
- }
- private fun launchRootProcess(root: Boolean, vararg args: String): MutableList<String> {
- val command = RootJava.getLaunchScript(mContext,
+ // #Anti-Crack
+ internal const val EXTRA_ERROR_CODE = "moe.yuuta.workmode.access.EXTRA_ERROR_CODE"
+ internal const val EXTRA_ERROR_MSG = "moe.yuuta.workmode.access.EXTRA_ERROR_MSG"
+ internal const val EXTRA_ERROR_STATUS = "moe.yuuta.workmode.access.EXTRA_ERROR_STATUS"
+ internal const val EXTRA_DATA = "moe.yuuta.workmode.access.EXTRA_DATA"
+ internal const val EXTRA_DAT = "moe.yuuta.workmode.access.EXTRA_DAT"
+
+ private fun launchRootProcess(context: Context, root: Boolean, vararg args: String): MutableList<String> {
+ val command = RootJava.getLaunchScript(context,
WorkModeAccessor::class.java,
null,
null,
args,
BuildConfig.APPLICATION_ID + ":accessor")
- return if (root) {
- Shell.SU.run(command)
- } else {
- Shell.SH.run(command)
+ return if (root) {
+ Shell.SU.run(command)
+ } else {
+ Shell.SH.run(command)
+ }
}
- }
- fun getSuspendedPackageAppExtras(packageName: String, root: Boolean): Bundle? {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
- argumentParcel.writeString(WorkModeAccessor.ACTION_GET_APP_EXTRAS)
- argumentParcel.writeString(packageName)
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val bundle = result.readBundle()
- result.recycle()
- return bundle
- } finally {
- argumentParcel.recycle()
- }
- }
+ /**
+ * Create a connected Starter object.
+ */
+ @WorkerThread
+ fun <T> start(context: Context, root: Boolean, thenRun: Function<AccessorStarter, T>): T {
+ var res: T? = null
+ var err: Throwable? = null
+ object : RootIPCReceiver<IAccessor>(context, 0x302) {
+ override fun onConnect(ipc: IAccessor?) {
+ logger.d("Connected to the system")
+ val starter = AccessorStarter(context, ipc!!, this)
+ try {
+ res = thenRun.apply(starter)
+ } catch (e: Throwable) {
+ logger.d("Cannot perform the action", e)
+ err = e
+ }
+ starter.release()
+ }
- fun getSuspendedPackageLauncherExtras(packageName: String, root: Boolean): Bundle? {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_GET_LAUNCHER_EXTRAS)
- argumentParcel.writeString(packageName)
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val bundle = result.readBundle()
- result.recycle()
- return bundle
- } finally {
- argumentParcel.recycle()
+ override fun onDisconnect(ipc: IAccessor?) {
+ logger.d("Disconnected from the system")
+ }
+ }
+ logger.d("Starting root process.....")
+ launchRootProcess(context, root, getLogsPath(context).absolutePath)
+ // Wait until it exits.
+ // We assume that the server must return a non-null result or an exception.
+ if (err != null)
+ throw err as Throwable
+ return res!!
}
}
- fun isPackageSuspended(packageNames: Array<out String>, root: Boolean): Boolean {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_IS_SUSPENDED)
- argumentParcel.writeStringArray(packageNames)
- val marshalledResult = launchRootProcess(root,
- WorkModeAccessor.ACTION_IS_SUSPENDED,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
-
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val isSuspended = result.readByte() == 1.toByte()
- result.recycle()
- return isSuspended
- } finally {
- argumentParcel.recycle()
- }
- }
+ fun getSuspendedPackageAppExtras(packageInfo: TransferableSuspendedApp): Bundle? =
+ mService.getSuspendedPackageAppExtras(packageInfo)
- fun dump(packageName: String, root: Boolean): DumpResult {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_DUMP)
- argumentParcel.writeString(packageName)
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val data = DumpResult(
- result.readByte() == 1.toByte(),
- result.readBundle(),
- result.readBundle()
- )
- result.recycle()
- return data
- } finally {
- argumentParcel.recycle()
- }
+ fun getSuspendedPackageLauncherExtras(packageInfo: TransferableSuspendedApp): Bundle? =
+ mService.getSuspendedPackageLauncherExtras(packageInfo)
+
+ fun isPackageSuspended(packages: List<TransferableSuspendedApp>): Boolean {
+ return mService.isSuspended(packages)
}
- fun setPackagesSuspended(packageNames: Array<String>, suspended: Boolean,
+ fun dump(packageInfo: TransferableSuspendedApp): DumpResult =
+ mService.dump(packageInfo)
+
+ fun setPackagesSuspended(packages: List<TransferableSuspendedApp>, suspended: Boolean,
appExtras: PersistableBundle, launcherExtras: PersistableBundle,
- dialogMessage: String, root: Boolean): Array<String> {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_SET_SUSPENDED)
- argumentParcel.writeStringArray(packageNames)
- argumentParcel.writeByte(if (suspended) 1 else 0)
- argumentParcel.writeBundle(Bundle(appExtras))
- argumentParcel.writeBundle(Bundle(launcherExtras))
- argumentParcel.writeString(dialogMessage)
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val rs = result.createStringArray() ?: arrayOf()
- result.recycle()
- return rs
- } finally {
- argumentParcel.recycle()
- }
+ dialogMessage: String): Array<String> {
+ val result = mService.setPackagesSuspended(packages, suspended, appExtras, launcherExtras, dialogMessage)
+ processError(result)
+ return result.getStringArray(EXTRA_DATA)
}
- @Throws(Throwable::class)
- private fun deserialize(byteArray: ByteArray): Parcel {
- val result = Parcel.obtain()
- result.unmarshall(byteArray, 0, byteArray.size)
- // Thanks to https://github.com/jiaminghan/droidplanner-master/blob/743b5436df6311cbbbfdecd21f796e2b948cbac7/Android/src/com/o3dr/services/android/lib/util/ParcelableUtils.java#L35
- result.setDataPosition(0)
- when (result.readByte()) {
- 1.toByte() -> {
- }
- 0.toByte() -> {
- val throwable = result.readSerializable() as Throwable?
- if (throwable != null) {
- throw throwable
- }
- throw RuntimeException("Unsuccessful result with unknown stacktrace")
+ // Read the Bundle which is returned from some methods.
+ // It contains the crack information and the normal information.
+ // If it has crack information, log it.
+ // #Anti-Crack
+ private fun processError(bundle: Bundle) {
+ when (bundle.getInt(EXTRA_ERROR_CODE)) {
+ 1 -> {
}
// If server returns this code, which means the task is successfully executed but
// it had detected that the app was cracked.
// #Anti-Crack
- 2.toByte() -> {
+ 2 -> {
// The ID is used to prevent from multiple reporting.
- val id = result.readString()
- val reason = result.readString()
+ val id = bundle.getString(EXTRA_ERROR_STATUS)
+ val reason = bundle.getString(EXTRA_ERROR_MSG)
SuspendedStorage.get(mContext).reportCrack(id ?: "nd", reason ?: "nr")
}
}
- return result
- }
-
- fun getPackagesSuspendedByWorkMode(root: Boolean): List<String> {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_GET_ALL_PACKAGES_SUSPENDED_BY_WORK_MODE)
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- val data = result.createStringArrayList()
- result.recycle()
- return data ?: listOf()
- } finally {
- argumentParcel.recycle()
- }
}
- fun apply(suspendList: Array<String>, listMode: ListMode, status: Status, root: Boolean) {
- val argumentParcel: Parcel = obtainArgumentParcel()
- try {
-
- argumentParcel.writeString(WorkModeAccessor.ACTION_APPLY)
- argumentParcel.writeStringArray(suspendList)
- argumentParcel.writeInt(when (listMode) {
- ListMode.BLACKLIST -> 1
- ListMode.WHITELIST -> 2
- })
- argumentParcel.writeInt(when (status) {
- Status.ON -> 1
- Status.OFF -> 2
- })
- val marshalledResult = launchRootProcess(root,
- ByteArraySerializer.serialize(argumentParcel.marshall()))[0]
- val result = deserialize(ByteArraySerializer.deserialize(marshalledResult))
- result.recycle()
- } finally {
- argumentParcel.recycle()
- }
- }
-
- private fun obtainArgumentParcel(): Parcel {
- val argumentParcel: Parcel = Parcel.obtain()
- argumentParcel.writeString(mLogPath)
+ fun apply(suspendList: Array<TransferableSuspendedApp>, listMode: ListMode, status: Status) {
// Tell the trigger times and times to the server, it will disable the app automatically
// #Anti-Crack
val sp = SuspendedStorage.get(mContext).getStorage()
val keys = sp.all.keys.stream()
- .filter {
- return@filter it.startsWith("c_")
- }
- .collect(Collectors.toList())
- val map = mutableMapOf<String, Int>()
+ .filter {
+ return@filter it.startsWith("c_")
+ }
+ .collect(Collectors.toList())
+ val map = hashMapOf<String, Int>()
for (key in keys) {
try {
val times = sp.getInt(key, -1)
map[key] = times
} catch (e: Throwable) {}
}
- argumentParcel.writeMap(map)
- return argumentParcel
+ val dat = Bundle()
+ dat.putSerializable(EXTRA_DAT, map)
+ val result = mService.apply(dat, suspendList,
+ when (listMode) {
+ ListMode.BLACKLIST -> 1
+ ListMode.WHITELIST -> 2
+ },
+ when (status) {
+ Status.ON -> 1
+ Status.OFF -> 2
+ })
+ processError(result)
+ }
+
+ fun getInstalledApplicationsAcrossUser(flags: Int): List<TransferableSuspendedApp> =
+ mService.getInstalledApplicationsAcrossUser(flags)
+
+ fun release() {
+ mListener.release()
+ }
+
+ fun isConnected(): Boolean = mService.asBinder().isBinderAlive
+
+ fun suspend(packages: List<TransferableSuspendedApp>, suspended: Boolean): Array<String> =
+ setPackagesSuspended(packages,
+ suspended,
+ PersistableBundle(),
+ PersistableBundle(), // Removed because there is an unknown bug which prevents from writing launcher extras from the owner (?)
+ mContext.getString(R.string.suspended_message))
+
+ fun apply() {
+ val storage = SuspendedStorage.get(mContext)
+ val status = storage.getStatus()
+ val listMode = storage.getListMode()
+ val list = storage.getList()
+ .stream()
+ .map {
+ return@map it.copyToSimpleTransferableInfo()
+ }
+ .collect(Collectors.toList())
+ apply(list.toTypedArray(), listMode, status)
+ TileService.requestListeningState(mContext, ComponentName(mContext, SuspendTile::class.java))
}
} \ No newline at end of file