diff options
author | YuutaW <17158086+Trumeet@users.noreply.github.com> | 2019-02-24 11:59:17 -0800 |
---|---|---|
committer | YuutaW <17158086+Trumeet@users.noreply.github.com> | 2019-02-24 11:59:17 -0800 |
commit | a08328403be84d85c006f801169a3feed0d956a4 (patch) | |
tree | ceebece6443a3e6662a4937b911c58904bb5b1ff /app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt | |
download | WorkMode-a08328403be84d85c006f801169a3feed0d956a4.tar WorkMode-a08328403be84d85c006f801169a3feed0d956a4.tar.gz WorkMode-a08328403be84d85c006f801169a3feed0d956a4.tar.bz2 WorkMode-a08328403be84d85c006f801169a3feed0d956a4.zip |
First Commit
Signed-off-by: YuutaW <17158086+Trumeet@users.noreply.github.com>
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.kt | 199 |
1 files changed, 199 insertions, 0 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 new file mode 100644 index 0000000..c8aae67 --- /dev/null +++ b/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt @@ -0,0 +1,199 @@ +package moe.yuuta.workmode.access + +import android.content.Context +import android.os.Bundle +import android.os.Parcel +import android.os.PersistableBundle +import com.elvishew.xlog.Logger +import com.elvishew.xlog.XLog +import eu.chainfire.librootjava.RootJava +import eu.chainfire.libsuperuser.Shell +import moe.yuuta.workmode.BuildConfig +import moe.yuuta.workmode.suspend.data.ListMode +import moe.yuuta.workmode.suspend.data.Status +import moe.yuuta.workmode.utils.ByteArraySerializer + +/** + * 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() + + companion object { + 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, + WorkModeAccessor::class.java, + null, + null, + args, + BuildConfig.APPLICATION_ID + ":accessor") + + return if (root) { + Shell.SU.run(command) + } else { + Shell.SH.run(command) + } + } + + fun getSuspendedPackageAppExtras(packageName: String, root: Boolean): Bundle? { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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() + } + } + + fun getSuspendedPackageLauncherExtras(packageName: String, root: Boolean): Bundle? { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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() + } + } + + fun isPackageSuspended(packageNames: Array<out String>, root: Boolean): Boolean { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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 dump(packageName: String, root: Boolean): DumpResult { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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 setPackagesSuspended(packageNames: Array<String>, suspended: Boolean, + appExtras: PersistableBundle, launcherExtras: PersistableBundle, + dialogMessage: String, root: Boolean): Array<String> { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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() + } + } + + @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") + } + } + return result + } + + fun getPackagesSuspendedByWorkMode(root: Boolean): List<String> { + val argumentParcel: Parcel = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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 = Parcel.obtain() + try { + argumentParcel.writeString(mLogPath) + 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() + } + } +}
\ No newline at end of file |