manager: supports grant root access to cross profile. close #271

This commit is contained in:
tiann
2023-04-18 17:38:48 +08:00
parent a3c72c22c1
commit 2bc84014c2
5 changed files with 144 additions and 4 deletions

View File

@@ -81,7 +81,9 @@ dependencies {
implementation("io.coil-kt:coil-compose:2.2.2")
implementation("me.zhanghai.android.appiconloader:appiconloader-coil:1.5.0")
implementation("com.github.topjohnwu.libsu:core:5.0.3")
val libsuVersion = "5.0.4"
implementation("com.github.topjohnwu.libsu:core:$libsuVersion")
implementation("com.github.topjohnwu.libsu:service:$libsuVersion")
implementation("com.github.alorma:compose-settings-ui-m3:0.22.0")
ksp("io.github.raamcosta.compose-destinations:ksp:$composeDestinationsVersion")

View File

@@ -0,0 +1,9 @@
// IKsuInterface.aidl
package me.weishu.kernelsu;
import android.content.pm.PackageInfo;
import java.util.List;
interface IKsuInterface {
List<PackageInfo> getPackages();
}

View File

@@ -0,0 +1,79 @@
package me.weishu.kernelsu.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 me.weishu.kernelsu.IKsuInterface;
/**
* @author weishu
* @date 2023/4/18.
*/
public class KsuService extends RootService {
private static final String TAG = "KsuService";
class Stub extends IKsuInterface.Stub {
@Override
public List<PackageInfo> getPackages() {
List<PackageInfo> list = getInstalledPackagesAll();
Log.i(TAG, "getPackages: " + list.size());
return list;
}
}
@Override
public IBinder onBind(@NonNull Intent intent) {
return new Stub();
}
List<Integer> getUserIds() {
List<Integer> result = new ArrayList<>();
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
List<UserHandle> userProfiles = um.getUserProfiles();
for (UserHandle userProfile : userProfiles) {
int userId = userProfile.hashCode();
if (userId == 0) {
continue;
}
result.add(userProfile.hashCode());
}
return result;
}
ArrayList<PackageInfo> getInstalledPackagesAll() {
ArrayList<PackageInfo> packages = new ArrayList<>();
for (Integer userId : getUserIds()) {
Log.i(TAG, "getInstalledPackagesAll: " + userId);
packages.addAll(getInstalledPackagesAsUser(userId));
}
return packages;
}
List<PackageInfo> getInstalledPackagesAsUser(int userId) {
try {
PackageManager pm = getPackageManager();
Method getInstalledPackagesAsUser = pm.getClass().getDeclaredMethod("getInstalledPackagesAsUser", int.class, int.class);
return (List<PackageInfo>) getInstalledPackagesAsUser.invoke(pm, 0, userId);
} catch (Throwable e) {
Log.e(TAG, "err", e);
}
return new ArrayList<>();
}
}

View File

@@ -108,7 +108,7 @@ fun SuperUserScreen() {
val failMessage = stringResource(R.string.superuser_failed_to_grant_root)
LazyColumn(Modifier.fillMaxSize()) {
items(viewModel.appList, key = { it.packageName }) { app ->
items(viewModel.appList, key = { it.packageName + it.uid }) { app ->
var isChecked by rememberSaveable(app) { mutableStateOf(app.onAllowList) }
val dialogHost = LocalDialogHost.current
val content =

View File

@@ -1,8 +1,11 @@
package me.weishu.kernelsu.ui.viewmodel
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.graphics.drawable.Drawable
import android.os.IBinder
import android.os.SystemClock
import android.util.Log
import androidx.compose.runtime.derivedStateOf
@@ -10,13 +13,19 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import me.weishu.kernelsu.IKsuInterface
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.KsuService
import me.weishu.kernelsu.ui.util.HanziToPinyin
import me.weishu.kernelsu.ui.util.KsuCli
import java.text.Collator
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class SuperUserViewModel : ViewModel() {
@@ -62,7 +71,44 @@ class SuperUserViewModel : ViewModel() {
}
}
private suspend inline fun connectKsuService(
crossinline onDisconnect: () -> Unit = {}
): Pair<IBinder, ServiceConnection> = 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() {
val result = connectKsuService {
Log.w(TAG, "KsuService disconnected")
}
val binder = result.first
val extraPackages = IKsuInterface.Stub.asInterface(binder).packages
stopKsuService()
withContext(Dispatchers.IO) {
isRefreshing = true
val pm = ksuApp.packageManager
@@ -71,7 +117,11 @@ class SuperUserViewModel : ViewModel() {
Log.i(TAG, "allowList: $allowList")
Log.i(TAG, "denyList: $denyList")
val start = SystemClock.elapsedRealtime()
apps = pm.getInstalledPackages(0).map {
val packages = pm.getInstalledPackages(0)
packages.addAll(extraPackages)
apps = packages.map {
val appInfo = it.applicationInfo
val uid = appInfo.uid
AppInfo(