diff --git a/manager/app/build.gradle.kts b/manager/app/build.gradle.kts index 8b7c017b..df821b47 100644 --- a/manager/app/build.gradle.kts +++ b/manager/app/build.gradle.kts @@ -34,6 +34,7 @@ android { } buildFeatures { + aidl = true buildConfig = true compose = true prefab = true diff --git a/manager/app/src/main/aidl/com/rifsxd/ksunext/IKsuInterface.aidl b/manager/app/src/main/aidl/com/rifsxd/ksunext/IKsuInterface.aidl new file mode 100644 index 00000000..899e79b8 --- /dev/null +++ b/manager/app/src/main/aidl/com/rifsxd/ksunext/IKsuInterface.aidl @@ -0,0 +1,9 @@ +// IKsuInterface.aidl +package com.rifsxd.ksunext; + +import android.content.pm.PackageInfo; +import rikka.parcelablelist.ParcelableListSlice; + +interface IKsuInterface { + ParcelableListSlice getPackages(int flags); +} \ No newline at end of file diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt b/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt index acdaa507..46b66a8d 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt @@ -4,7 +4,6 @@ import android.app.Application import android.system.Os import coil.Coil import coil.ImageLoader -import com.dergoogler.mmrl.platform.Platform import me.zhanghai.android.appiconloader.coil.AppIconFetcher import me.zhanghai.android.appiconloader.coil.AppIconKeyer import okhttp3.Cache @@ -22,8 +21,6 @@ class KernelSUApplication : Application() { super.onCreate() ksuApp = this - Platform.setHiddenApiExemptions() - val context = this val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size) Coil.setImageLoader( diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/KsuService.java b/manager/app/src/main/java/com/rifsxd/ksunext/KsuService.java new file mode 100644 index 00000000..85e613b0 --- /dev/null +++ b/manager/app/src/main/java/com/rifsxd/ksunext/KsuService.java @@ -0,0 +1,77 @@ +package com.rifsxd.ksunext.ui; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.os.UserHandle; +import android.os.UserManager; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.topjohnwu.superuser.ipc.RootService; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import com.rifsxd.ksunext.IKsuInterface; +import rikka.parcelablelist.ParcelableListSlice; + +/** + * @author weishu + * @date 2023/4/18. + */ + +public class KsuService extends RootService { + + private static final String TAG = "KsuService"; + + class Stub extends IKsuInterface.Stub { + @Override + public ParcelableListSlice getPackages(int flags) { + List list = getInstalledPackagesAll(flags); + Log.i(TAG, "getPackages: " + list.size()); + return new ParcelableListSlice<>(list); + } + } + + @Override + public IBinder onBind(@NonNull Intent intent) { + return new Stub(); + } + + List getUserIds() { + List result = new ArrayList<>(); + UserManager um = (UserManager) getSystemService(Context.USER_SERVICE); + List userProfiles = um.getUserProfiles(); + for (UserHandle userProfile : userProfiles) { + int userId = userProfile.hashCode(); + result.add(userProfile.hashCode()); + } + return result; + } + + ArrayList getInstalledPackagesAll(int flags) { + ArrayList packages = new ArrayList<>(); + for (Integer userId : getUserIds()) { + Log.i(TAG, "getInstalledPackagesAll: " + userId); + packages.addAll(getInstalledPackagesAsUser(flags, userId)); + } + return packages; + } + + List getInstalledPackagesAsUser(int flags, int userId) { + try { + PackageManager pm = getPackageManager(); + Method getInstalledPackagesAsUser = pm.getClass().getDeclaredMethod("getInstalledPackagesAsUser", int.class, int.class); + return (List) getInstalledPackagesAsUser.invoke(pm, flags, userId); + } catch (Throwable e) { + Log.e(TAG, "err", e); + } + + return new ArrayList<>(); + } +} \ No newline at end of file diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt index f8e68724..86f14fba 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt @@ -64,7 +64,7 @@ import com.rifsxd.ksunext.ui.util.install import com.rifsxd.ksunext.ui.util.isSuCompatDisabled import com.rifsxd.ksunext.ui.screen.FlashIt import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel -import com.rifsxd.ksunext.ui.webui.initPlatform +import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel class MainActivity : ComponentActivity() { @@ -115,6 +115,7 @@ class MainActivity : ComponentActivity() { val amoledMode = prefs.getBoolean("enable_amoled", false) val moduleViewModel: ModuleViewModel = viewModel() + val superUserViewModel: SuperUserViewModel = viewModel() val moduleUpdateCount = moduleViewModel.moduleList.count { moduleViewModel.checkUpdate(it).first.isNotEmpty() } @@ -139,17 +140,22 @@ class MainActivity : ComponentActivity() { } } + LaunchedEffect(Unit) { + if (superUserViewModel.appList.isEmpty()) { + superUserViewModel.fetchAppList() + } + + if (moduleViewModel.moduleList.isEmpty()) { + moduleViewModel.fetchModuleList() + } + } + val showBottomBar = when (currentDestination?.route) { FlashScreenDestination.route -> false // Hide for FlashScreenDestination ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen else -> true } - // pre-init platform to faster start WebUI X activities - LaunchedEffect(Unit) { - initPlatform() - } - Scaffold( bottomBar = { AnimatedVisibility( @@ -199,17 +205,6 @@ private fun BottomBar(navController: NavHostController, moduleUpdateCount: Int) ) ) { BottomBarDestination.entries - .filter { - // Hide SuperUser and Module when su compat is disabled - if (suCompatDisabled) { - if (suSFS == "Supported" && susSUMode == "2") { - true - } else { - // hide SuperUser and Module - it != BottomBarDestination.SuperUser && it != BottomBarDestination.Module - } - } else true - } .forEach { destination -> if (!fullFeatured && destination.rootRequired) return@forEach val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Developer.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Developer.kt index 9c1286cf..8748ced7 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Developer.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Developer.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.dergoogler.mmrl.platform.Platform import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator @@ -102,25 +101,6 @@ fun DeveloperScreen(navigator: DestinationsNavigator) { } } - var useWebUIX by rememberSaveable { - mutableStateOf( - prefs.getBoolean("use_webuix", true) - ) - } - if (ksuVersion != null) { - SwitchItem( - beta = false, - enabled = Platform.isAlive && developerOptionsEnabled, - icon = Icons.Filled.WebAsset, - title = stringResource(id = R.string.use_webuix), - summary = stringResource(id = R.string.use_webuix_summary), - checked = useWebUIX - ) { - prefs.edit().putBoolean("use_webuix", it).apply() - useWebUIX = it - } - } - var enableWebDebugging by rememberSaveable { mutableStateOf( prefs.getBoolean("enable_web_debugging", false) @@ -138,25 +118,6 @@ fun DeveloperScreen(navigator: DestinationsNavigator) { enableWebDebugging = it } } - - var useWebUIXEruda by rememberSaveable { - mutableStateOf( - prefs.getBoolean("use_webuix_eruda", false) - ) - } - if (ksuVersion != null) { - SwitchItem( - beta = false, - enabled = Platform.isAlive && useWebUIX && enableWebDebugging, - icon = Icons.Filled.FormatListNumbered, - title = stringResource(id = R.string.use_webuix_eruda), - summary = stringResource(id = R.string.use_webuix_eruda_summary), - checked = useWebUIXEruda - ) { - prefs.edit().putBoolean("use_webuix_eruda", it).apply() - useWebUIXEruda = it - } - } } } } diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt index 77f45e74..6f36204c 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt @@ -54,8 +54,6 @@ import com.rifsxd.ksunext.R import com.rifsxd.ksunext.ui.component.rememberConfirmDialog import com.rifsxd.ksunext.ui.util.* import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo -import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel -import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel import java.util.* @OptIn(ExperimentalMaterial3Api::class) @@ -96,20 +94,6 @@ fun HomeScreen(navigator: DestinationsNavigator) { val lkmMode = ksuVersion?.let { if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null } - - val superUserViewModel: SuperUserViewModel = viewModel() - - val moduleViewModel: ModuleViewModel = viewModel() - - LaunchedEffect(Unit) { - if (superUserViewModel.appList.isEmpty()) { - superUserViewModel.fetchAppList() - } - - if (moduleViewModel.moduleList.isEmpty()) { - moduleViewModel.fetchModuleList() - } - } StatusCard(kernelVersion, ksuVersion, lkmMode) { navigator.navigate(InstallScreenDestination) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt index d72a92b1..97f19736 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt @@ -95,7 +95,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.net.toUri import androidx.lifecycle.viewmodel.compose.viewModel -import com.dergoogler.mmrl.platform.Platform import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination @@ -126,7 +125,6 @@ import com.rifsxd.ksunext.ui.util.restoreModule import com.rifsxd.ksunext.ui.util.zygiskRequired import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel import com.rifsxd.ksunext.ui.webui.WebUIActivity -import com.rifsxd.ksunext.ui.webui.WebUIXActivity import com.dergoogler.mmrl.ui.component.LabelItem import com.topjohnwu.superuser.io.SuFile @@ -363,22 +361,11 @@ fun ModuleScreen(navigator: DestinationsNavigator) { }, onClickModule = { id, name, hasWebUi -> if (hasWebUi) { - val wxEngine = Intent(context, WebUIXActivity::class.java) - .setData("kernelsu://webuix/$id".toUri()) - .putExtra("id", id) - .putExtra("name", name) - - val ksuEngine = Intent(context, WebUIActivity::class.java) - .setData("kernelsu://webui/$id".toUri()) - .putExtra("id", id) - .putExtra("name", name) - webUILauncher.launch( - if (prefs.getBoolean("use_webuix", true) && Platform.isAlive) { - wxEngine - } else { - ksuEngine - } + Intent(context, WebUIActivity::class.java) + .setData(Uri.parse("kernelsu://webui/$id")) + .putExtra("id", id) + .putExtra("name", name) ) } }, diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt index 6599c2fc..281dace5 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt @@ -54,7 +54,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.content.FileProvider -import com.dergoogler.mmrl.platform.Platform import com.maxkeppeker.sheets.core.models.base.Header import com.maxkeppeker.sheets.core.models.base.IconSource import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt index 117350fe..92f9701a 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage import coil.request.ImageRequest -import com.dergoogler.mmrl.platform.Platform import com.dergoogler.mmrl.ui.component.LabelItem import com.dergoogler.mmrl.ui.component.LabelItemDefaults import com.ramcosta.composedestinations.annotation.Destination diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt index 979b3903..768d8ce2 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt @@ -9,8 +9,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.dergoogler.mmrl.platform.Platform -import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS import kotlinx.coroutines.delay import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -111,21 +109,9 @@ class ModuleViewModel : ViewModel() { viewModelScope.launch { - withContext(Dispatchers.Main) { - isRefreshing = true - } + isRefreshing = true withContext(Dispatchers.IO) { - withTimeoutOrNull(TIMEOUT_MILLIS) { - while (!Platform.isAlive) { - delay(500) - } - } ?: run { - isRefreshing = false - Log.e(TAG, "Platform is not alive, aborting fetchModuleList") - return@withContext - } - val start = SystemClock.elapsedRealtime() val oldModuleList = modules diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt index abdf4257..28ddf140 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt @@ -6,6 +6,7 @@ import android.content.Intent import android.content.ServiceConnection import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo +import android.os.IBinder import android.os.Parcelable import android.os.SystemClock import android.util.Log @@ -15,15 +16,16 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel -import com.dergoogler.mmrl.platform.Platform -import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS +import com.topjohnwu.superuser.Shell import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize +import com.rifsxd.ksunext.IKsuInterface import com.rifsxd.ksunext.Natives import com.rifsxd.ksunext.ksuApp +import com.rifsxd.ksunext.ui.KsuService import com.rifsxd.ksunext.ui.util.HanziToPinyin -import com.rifsxd.ksunext.ui.webui.getInstalledPackagesAll +import com.rifsxd.ksunext.ui.util.KsuCli import kotlinx.coroutines.delay import kotlinx.coroutines.withTimeoutOrNull import java.text.Collator @@ -33,7 +35,6 @@ import kotlin.coroutines.suspendCoroutine import androidx.core.content.edit class SuperUserViewModel : ViewModel() { - val isPlatformAlive get() = Platform.isAlive companion object { private const val TAG = "SuperUserViewModel" @@ -117,24 +118,56 @@ class SuperUserViewModel : ViewModel() { } } + private suspend inline fun connectKsuService( + crossinline onDisconnect: () -> Unit = {} + ): Pair = suspendCoroutine { + val connection = object : ServiceConnection { + override fun onServiceDisconnected(name: ComponentName?) { + onDisconnect() + } + + override fun onServiceConnected(name: ComponentName?, binder: IBinder?) { + it.resume(binder as IBinder to this) + } + } + + val intent = Intent(ksuApp, KsuService::class.java) + + val task = KsuService.bindOrTask( + intent, + Shell.EXECUTOR, + connection, + ) + val shell = KsuCli.SHELL + task?.let { it1 -> shell.execTask(it1) } + } + + private fun stopKsuService() { + val intent = Intent(ksuApp, KsuService::class.java) + KsuService.stop(intent) + } + suspend fun fetchAppList() { + isRefreshing = true - withContext(Dispatchers.IO) { - withTimeoutOrNull(TIMEOUT_MILLIS) { - while (!isPlatformAlive) { - delay(500) - } - } ?: return@withContext // Exit early if timeout + val result = connectKsuService { + Log.w(TAG, "KsuService disconnected") + } + withContext(Dispatchers.IO) { val pm = ksuApp.packageManager val start = SystemClock.elapsedRealtime() - val packages = Platform.getInstalledPackagesAll { - Log.e(TAG, "getInstalledPackagesAll:", it) - Toast.makeText(ksuApp, "Something went wrong, check logs", Toast.LENGTH_SHORT).show() + val binder = result.first + val allPackages = IKsuInterface.Stub.asInterface(binder).getPackages(0) + + withContext(Dispatchers.Main) { + stopKsuService() } + val packages = allPackages.list + apps = packages.map { val appInfo = it.applicationInfo val uid = appInfo!!.uid @@ -145,7 +178,6 @@ class SuperUserViewModel : ViewModel() { profile = profile, ) }.filter { it.packageName != ksuApp.packageName } - profileOverrides = emptyMap() Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}") } } diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/KsuLibSuProvider.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/KsuLibSuProvider.kt deleted file mode 100644 index 2fb027f1..00000000 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/KsuLibSuProvider.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.rifsxd.ksunext.ui.webui - -import android.content.ServiceConnection -import android.content.pm.PackageInfo -import android.util.Log -import com.dergoogler.mmrl.platform.Platform -import com.dergoogler.mmrl.platform.hiddenApi.HiddenPackageManager -import com.dergoogler.mmrl.platform.hiddenApi.HiddenUserManager -import com.dergoogler.mmrl.platform.model.IProvider -import com.dergoogler.mmrl.platform.model.PlatformIntent -import com.rifsxd.ksunext.Natives -import com.rifsxd.ksunext.ksuApp -import com.topjohnwu.superuser.ipc.RootService -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext - -class KsuLibSuProvider : IProvider { - override val name = "KsuLibSu" - - override fun isAvailable() = true - - override suspend fun isAuthorized() = Natives.becomeManager(ksuApp.packageName) - - private val serviceIntent - get() = PlatformIntent( - ksuApp, - Platform.KsuNext, - SuService::class.java - ) - - override fun bind(connection: ServiceConnection) { - RootService.bind(serviceIntent.intent, connection) - } - - override fun unbind(connection: ServiceConnection) { - RootService.stop(serviceIntent.intent) - } -} - -suspend fun initPlatform() = withContext(Dispatchers.IO) { - try { - val active = Platform.init { - this.context = ksuApp - this.platform = Platform.KsuNext - this.provider = from(KsuLibSuProvider()) - } - - while (!active) { - delay(1000) - } - - return@withContext active - } catch (e: Exception) { - Log.e("KsuLibSu", "Failed to initialize platform", e) - return@withContext false - } -} - -fun Platform.Companion.getInstalledPackagesAll(catch: (Exception) -> Unit = {}): List = - try { - val packages = mutableListOf() - val userInfos = userManager.getUsers() - - for (userInfo in userInfos) { - packages.addAll(packageManager.getInstalledPackages(0, userInfo.id)) - } - - packages - } catch (e: Exception) { - catch(e) - packageManager.getInstalledPackages(0, userManager.myUserId) - } \ No newline at end of file diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuService.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuService.kt deleted file mode 100644 index ab1c3b7a..00000000 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuService.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.rifsxd.ksunext.ui.webui - -import android.content.Intent -import android.os.IBinder -import com.dergoogler.mmrl.platform.model.PlatformIntent.Companion.getPlatform -import com.dergoogler.mmrl.platform.service.ServiceManager -import com.topjohnwu.superuser.ipc.RootService - -class SuService : RootService() { - override fun onBind(intent: Intent): IBinder { - val mode = intent.getPlatform() - return ServiceManager(mode) - } -} diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt index 30ab391d..a4e34b72 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt @@ -15,8 +15,6 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updateLayoutParams import androidx.webkit.WebViewAssetLoader -import com.dergoogler.mmrl.platform.model.ModId -import com.dergoogler.mmrl.webui.interfaces.WXOptions import com.topjohnwu.superuser.Shell import com.rifsxd.ksunext.ui.util.createRootShell import java.io.File @@ -41,10 +39,9 @@ class WebUIActivity : ComponentActivity() { val name = intent.getStringExtra("name")!! if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { @Suppress("DEPRECATION") - setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name")) + setTaskDescription(ActivityManager.TaskDescription("KSUNEXT - $name")) } else { - val taskDescription = - ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build() + val taskDescription = ActivityManager.TaskDescription.Builder().setLabel("KSUNEXT - $name").build() setTaskDescription(taskDescription) } @@ -65,7 +62,7 @@ class WebUIActivity : ComponentActivity() { val webViewClient = object : WebViewClient() { override fun shouldInterceptRequest( view: WebView, - request: WebResourceRequest, + request: WebResourceRequest ): WebResourceResponse? { return webViewAssetLoader.shouldInterceptRequest(request.url) } @@ -85,9 +82,7 @@ class WebUIActivity : ComponentActivity() { settings.javaScriptEnabled = true settings.domStorageEnabled = true settings.allowFileAccess = false - webviewInterface = WebViewInterface( - WXOptions(this@WebUIActivity, this, ModId(moduleId)) - ) + webviewInterface = WebViewInterface(this@WebUIActivity, this, moduleDir) addJavascriptInterface(webviewInterface, "ksu") setWebViewClient(webViewClient) loadUrl("https://mui.kernelsu.org/index.html") diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIXActivity.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIXActivity.kt deleted file mode 100644 index 1b11f406..00000000 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIXActivity.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.rifsxd.ksunext.ui.webui - -import android.app.ActivityManager -import android.os.Build -import android.os.Bundle -import android.webkit.WebView -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.lifecycle.lifecycleScope -import com.dergoogler.mmrl.platform.Platform -import com.dergoogler.mmrl.platform.model.ModId -import com.dergoogler.mmrl.ui.component.Loading -import com.dergoogler.mmrl.webui.screen.WebUIScreen -import com.dergoogler.mmrl.webui.util.rememberWebUIOptions -import com.rifsxd.ksunext.BuildConfig -import com.rifsxd.ksunext.ui.theme.KernelSUTheme -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -class WebUIXActivity : ComponentActivity() { - private lateinit var webView: WebView - - private val userAgent - get(): String { - val ksuVersion = BuildConfig.VERSION_CODE - - val platform = Platform.get("Unknown") { - platform.name - } - - val platformVersion = Platform.get(-1) { - moduleManager.versionCode - } - - val osVersion = Build.VERSION.RELEASE - val deviceModel = Build.MODEL - - return "KernelSU Next/$ksuVersion (Linux; Android $osVersion; $deviceModel; $platform/$platformVersion)" - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - webView = WebView(this) - - lifecycleScope.launch { - initPlatform() - } - - val moduleId = intent.getStringExtra("id")!! - val name = intent.getStringExtra("name")!! - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { - @Suppress("DEPRECATION") - setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name")) - } else { - val taskDescription = - ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build() - setTaskDescription(taskDescription) - } - - val prefs = getSharedPreferences("settings", MODE_PRIVATE) - - setContent { - KernelSUTheme { - var isLoading by remember { mutableStateOf(true) } - - LaunchedEffect(Platform.isAlive) { - while (!Platform.isAlive) { - delay(1000) - } - - isLoading = false - } - - if (isLoading) { - Loading() - - return@KernelSUTheme - } - - val webDebugging = prefs.getBoolean("enable_web_debugging", false) - val erudaInject = prefs.getBoolean("use_webuix_eruda", false) - val dark = isSystemInDarkTheme() - - val options = rememberWebUIOptions( - modId = ModId(moduleId), - debug = webDebugging, - appVersionCode = BuildConfig.VERSION_CODE, - isDarkMode = dark, - enableEruda = erudaInject, - cls = WebUIXActivity::class.java, - userAgentString = userAgent - ) - - WebUIScreen( - webView = webView, - options = options, - interfaces = listOf( - WebViewInterface.factory() - ) - ) - } - } - } -} diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt index 1e4b2c20..0bad500d 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt @@ -1,17 +1,16 @@ package com.rifsxd.ksunext.ui.webui import android.app.Activity +import android.content.Context import android.os.Handler import android.os.Looper import android.text.TextUtils import android.view.Window import android.webkit.JavascriptInterface +import android.webkit.WebView import android.widget.Toast import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import com.dergoogler.mmrl.webui.interfaces.WXInterface -import com.dergoogler.mmrl.webui.interfaces.WXOptions -import com.dergoogler.mmrl.webui.model.JavaScriptInterface import com.topjohnwu.superuser.CallbackList import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.internal.UiThreadHandler @@ -24,15 +23,10 @@ import java.io.File import java.util.concurrent.CompletableFuture class WebViewInterface( - wxOptions: WXOptions, -) : WXInterface(wxOptions) { - override var name: String = "ksu" - - companion object { - fun factory() = JavaScriptInterface(WebViewInterface::class.java) - } - - private val modDir get() = "/data/adb/modules/${modId.id}" + val context: Context, + private val webView: WebView, + private val modDir: String +) { @JavascriptInterface fun exec(cmd: String): String { @@ -65,7 +59,7 @@ class WebViewInterface( fun exec( cmd: String, options: String?, - callbackFunc: String, + callbackFunc: String ) { val finalCommand = StringBuilder() processOptions(finalCommand, options) @@ -174,9 +168,9 @@ class WebViewInterface( if (context is Activity) { Handler(Looper.getMainLooper()).post { if (enable) { - hideSystemUI(activity.window) + hideSystemUI(context.window) } else { - showSystemUI(activity.window) + showSystemUI(context.window) } } } @@ -185,7 +179,7 @@ class WebViewInterface( @JavascriptInterface fun moduleInfo(): String { val moduleInfos = JSONArray(listModules()) - val currentModuleInfo = JSONObject() + var currentModuleInfo = JSONObject() currentModuleInfo.put("moduleDir", modDir) val moduleId = File(modDir).getName() for (i in 0 until moduleInfos.length()) { @@ -195,7 +189,7 @@ class WebViewInterface( continue } - val keys = currentInfo.keys() + var keys = currentInfo.keys() for (key in keys) { currentModuleInfo.put(key, currentInfo.get(key)) } @@ -208,12 +202,8 @@ class WebViewInterface( fun hideSystemUI(window: Window) = WindowInsetsControllerCompat(window, window.decorView).let { controller -> controller.hide(WindowInsetsCompat.Type.systemBars()) - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } fun showSystemUI(window: Window) = - WindowInsetsControllerCompat( - window, - window.decorView - ).show(WindowInsetsCompat.Type.systemBars()) + WindowInsetsControllerCompat(window, window.decorView).show(WindowInsetsCompat.Type.systemBars()) \ No newline at end of file