### Configure Optional Stellar Startup Permission Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Add this meta-data to automatically start your application when the Stellar service starts. Requires the 'stellar' base permission. ```xml ``` -------------------------------- ### Migrate Shizuku Example to Stellar Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Demonstrates the migration of a MainActivity from using Shizuku to Stellar, updating listener registration and permission checks. ```kotlin import rikka.shizuku.Shizuku import rikka.shizuku.ShizukuProvider class MainActivity : AppCompatActivity() { private val binderReceivedListener = Shizuku.OnBinderReceivedListener { checkStatus() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Shizuku.addBinderReceivedListenerSticky(binderReceivedListener) } private fun checkStatus() { if (!Shizuku.pingBinder()) return if (Shizuku.checkSelfPermission() != PackageManager.PERMISSION_GRANTED) { Shizuku.requestPermission(1) return } val uid = Shizuku.getUid() println("UID: $uid") } } ``` ```kotlin import roro.stellar.Stellar import roro.stellar.StellarProvider class MainActivity : AppCompatActivity() { private val binderReceivedListener = Stellar.OnBinderReceivedListener { checkStatus() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Stellar.addBinderReceivedListenerSticky(binderReceivedListener) } private fun checkStatus() { if (!Stellar.pingBinder()) return if (!Stellar.checkSelfPermission()) { Stellar.requestPermission(requestCode = 1) return } val uid = Stellar.uid println("UID: $uid") } } ``` -------------------------------- ### StellarHelper Class Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Helper functions for checking Stellar manager installation, opening it, and retrieving service information. ```APIDOC ## StellarHelper.isManagerInstalled ### Description Checks if the Stellar manager application is installed on the device. ### Method `StellarHelper.isManagerInstalled(context: Context): Boolean` ### Parameters * **context** (Context) - Required - The application context. ## StellarHelper.openManager ### Description Attempts to open the Stellar manager application. ### Method `StellarHelper.openManager(context: Context): Boolean` ### Parameters * **context** (Context) - Required - The application context. ## StellarHelper.serviceInfo ### Description Retrieves information about the Stellar service, including its UID, version, and SELinux context. ### Method `val serviceInfo = StellarHelper.serviceInfo` ### Response * **serviceInfo** (ServiceInfo?) - Information about the Stellar service, or null if not available. * **uid** (Int) - The user ID of the service. * **version** (String) - The version of the service. * **seLinuxContext** (String) - The SELinux context of the service. * **isRoot** (Boolean) - True if the service is running as root (uid == 0). * **isAdb** (Boolean) - True if the service is running as ADB (uid == 2000). ``` -------------------------------- ### Root Startup Flow with Demotion Source: https://github.com/roro2239/stellar/blob/main/README.md Illustrates the sequence of execution when Stellar is started with Root privileges and the demotion activation feature is enabled. This flow ensures enhanced security by running the service as a less privileged user. ```bash su (root) → libchid.so 2000 → libstellar.so --apk=... ``` -------------------------------- ### Execute and Manage Standard Remote Process Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Example of creating a standard remote process using `Stellar.newProcess` and accessing its input/output streams, waiting for completion, and destroying it. ```kotlin val process = Stellar.newProcess(arrayOf("ls", "-la", "/sdcard"), null, null) // 标准进程方法 process.getInputStream(): InputStream process.getOutputStream(): OutputStream process.getErrorStream(): InputStream process.waitFor(): Int process.exitValue(): Int process.destroy() // 额外方法 process.alive(): Boolean process.waitForTimeout(timeout: Long, unit: TimeUnit): Boolean ``` -------------------------------- ### Handle Permission Denied Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Implement a listener to manage permission denial, showing rationale or guiding the user to manual authorization. ```kotlin private val permissionResultListener = Stellar.OnRequestPermissionResultListener { requestCode, allowed, onetime -> if (!allowed) { // 权限被拒绝 if (Stellar.shouldShowRequestPermissionRationale()) { // 显示权限说明对话框 showPermissionRationaleDialog() } else { // 用户选择了"不再询问",引导用户到管理器手动授权 StellarHelper.openManager(this) } } } ``` -------------------------------- ### Check and Open Stellar Manager Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Utility functions to check if the Stellar manager is installed and to open it using `StellarHelper.isManagerInstalled` and `StellarHelper.openManager`. ```kotlin // 检查管理器是否已安装 StellarHelper.isManagerInstalled(context: Context): Boolean // 打开管理器 StellarHelper.openManager(context: Context): Boolean ``` -------------------------------- ### Start Interactive PTY Shell (Kotlin) Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Initiates an interactive pseudo-terminal (PTY) shell using Stellar. Ensure `newPtyProcess` is called on a background thread. The terminal echoes commands by default; filter output in `onOutput` if needed. The file descriptor is closed and the reading thread exits upon calling `destroy()`. ```kotlin import android.os.ParcelFileDescriptor import roro.stellar.Stellar import kotlin.concurrent.thread class PtyShellSession( private val pty: StellarPtyProcess, private val writer: java.io.OutputStream ) { fun send(cmd: String) { writer.write("$cmd\n".toByteArray()) } fun resize(cols: Int, rows: Int) = pty.resize(cols, rows) fun destroy() = pty.destroy() } fun startPtyShell(onOutput: (String) -> Unit): PtyShellSession? { if (!Stellar.pingBinder() || !Stellar.checkSelfPermission()) return null val pty = try { Stellar.newPtyProcess(arrayOf("sh"), null, null) } catch (_: Exception) { return null } val fd = pty.ptyFd val session = PtyShellSession(pty, ParcelFileDescriptor.AutoCloseOutputStream(fd)) thread { try { val reader = ParcelFileDescriptor.AutoCloseInputStream(fd) val buf = ByteArray(4096) while (true) { val n = reader.read(buf) if (n < 0) break onOutput(String(buf, 0, n)) } } catch (_: Exception) {} } return session } ``` -------------------------------- ### Start Interactive PTY Shell Session Source: https://context7.com/roro2239/stellar/llms.txt Create a pseudo-terminal process supporting full terminal features like ANSI colors, Ctrl+C signals, and window resizing. Reading and writing share the same `ParcelFileDescriptor`. This is suitable for interactive shell scenarios. ```kotlin import android.os.ParcelFileDescriptor import roro.stellar.Stellar import kotlin.concurrent.thread fun startInteractivePtyShell(onOutput: (String) -> Unit) { thread { if (!Stellar.pingBinder() || !Stellar.checkSelfPermission()) return@thread val pty = Stellar.newPtyProcess(arrayOf("sh"), null, null) // 调整终端窗口大小 pty.resize(cols = 120, rows = 40) val fd = pty.ptyFd val writer = ParcelFileDescriptor.AutoCloseOutputStream(fd) val reader = ParcelFileDescriptor.AutoCloseInputStream(fd) // 启动输出读取线程 thread { try { val buf = ByteArray(4096) while (true) { val n = reader.read(buf) if (n < 0) break onOutput(String(buf, 0, n)) } } catch (_: Exception) {} } // 发送命令 writer.write("id\n".toByteArray()) writer.write("ls /sdcard\n".toByteArray()) writer.flush() // 等待退出 val exitCode = pty.waitFor() println("PTY 进程退出,退出码: $exitCode") pty.destroy() } } ``` -------------------------------- ### Get Stellar Service Information Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Retrieve information about the Stellar service, including UID, version, SELinux context, and root/ADB status, using `StellarHelper.serviceInfo`. ```kotlin // 获取服务信息 val serviceInfo = StellarHelper.serviceInfo serviceInfo?.let { val uid = it.uid val version = it.version val seContext = it.seLinuxContext val isRoot = it.isRoot // uid == 0 val isAdb = it.isAdb // uid == 2000 } ``` -------------------------------- ### Check if Stellar Manager is Installed Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Verify if the Stellar manager application is installed on the device using StellarHelper.isManagerInstalled. ```kotlin if (!StellarHelper.isManagerInstalled(context)) { // 管理器未安装,引导用户安装 AlertDialog.Builder(context) .setTitle("需要 Stellar 管理器") .setMessage("此功能需要安装 Stellar 管理器") .show() } ``` -------------------------------- ### Initialize Stellar with Listeners in MainActivity Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Set up listeners for Stellar service connection and permission results in your Activity. Use Sticky listeners to handle immediate callbacks if the service is already connected. ```kotlin import roro.stellar.Stellar class MainActivity : ComponentActivity() { private val binderReceivedListener = Stellar.OnBinderReceivedListener { Log.i("MyApp", "Stellar 服务已连接") // 服务连接成功,可以开始使用 API checkServiceStatus() } private val binderDeadListener = Stellar.OnBinderDeadListener { Log.w("MyApp", "Stellar 服务已断开") // 服务断开,更新 UI 状态 } private val permissionResultListener = Stellar.OnRequestPermissionResultListener { requestCode, allowed, onetime -> if (allowed) { Log.i("MyApp", "权限已授予") // 权限已授予,可以执行特权操作 } else { Log.w("MyApp", "权限被拒绝") // 权限被拒绝,提示用户 } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 添加监听器 // 使用 Sticky 版本:如果服务已连接,会立即触发回调;否则等待服务连接后触发 Stellar.addBinderReceivedListenerSticky(binderReceivedListener) Stellar.addBinderDeadListener(binderDeadListener) Stellar.addRequestPermissionResultListener(permissionResultListener) } override fun onDestroy() { super.onDestroy() // 移除监听器 Stellar.removeBinderReceivedListener(binderReceivedListener) Stellar.removeBinderDeadListener(binderDeadListener) Stellar.removeRequestPermissionResultListener(permissionResultListener) } private fun checkServiceStatus() { // 检查服务是否运行 if (!Stellar.pingBinder()) { Log.e("MyApp", "服务未运行") return } // 检查权限 if (!Stellar.checkSelfPermission()) { // 请求权限 Stellar.requestPermission(requestCode = 1) return } // 服务已连接且权限已授予,可以使用 API Log.i("MyApp", "服务版本: ${Stellar.version}") Log.i("MyApp", "服务 UID: ${Stellar.uid}") } } ``` -------------------------------- ### Execute and Manage PTY Process Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Demonstrates creating a PTY process with `Stellar.newPtyProcess`, accessing its single file descriptor for reading and writing, resizing the terminal, waiting for exit, and destroying the process. ```kotlin val pty = Stellar.newPtyProcess(arrayOf("sh"), null, null) // 获取 PTY 文件描述符(读写共用同一个 fd) pty.ptyFd: ParcelFileDescriptor // 调整终端窗口大小 pty.resize(cols: Int, rows: Int) // 等待进程退出并返回退出码 pty.waitFor(): Int // 销毁进程 pty.destroy() ``` -------------------------------- ### Get Active User Service Count Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Query the number of currently active user services managed by Stellar using `StellarUserService.getUserServiceCount()`. ```kotlin // 获取当前活跃的用户服务数量 StellarUserService.getUserServiceCount(): Int ``` -------------------------------- ### Build Release APK Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Build the release APK. Requires a signing.properties file in the root directory. ```bash ./gradlew :manager:assembleRelease ``` -------------------------------- ### Stellar.newPtyProcess() Source: https://context7.com/roro2239/stellar/llms.txt Create a pseudo-terminal process with full terminal features like ANSI colors, Ctrl+C signals, and window size adjustments. It's suitable for interactive shell scenarios, using a shared `ParcelFileDescriptor` for reading and writing. ```APIDOC ## `Stellar.newPtyProcess()` — PTY Terminal Session Create a pseudo-terminal process with full terminal features (ANSI colors, Ctrl+C signals, window size adjustments). It's suitable for interactive shell scenarios, using a shared `ParcelFileDescriptor` for reading and writing. ### Description This method provides an interactive shell experience by creating a pseudo-terminal. You can send commands, receive output with proper formatting, and control terminal properties like window size. ### Method `Stellar.newPtyProcess(command: Array, environment: Array?, workingDirectory: String?): StellarPtyProcess` ### Parameters - `command` (Array): The command to execute in the PTY (e.g., `arrayOf("sh")`). - `environment` (Array?, Optional): Environment variables for the new process. If null, inherits the environment of the Stellar service. - `workingDirectory` (String?, Optional): The working directory for the command. If null, uses the default working directory. ### Returns - `StellarPtyProcess`: An object representing the PTY process, with methods to interact with the terminal. ### Example ```kotlin import android.os.ParcelFileDescriptor import roro.stellar.Stellar import kotlin.concurrent.thread fun startInteractivePtyShell(onOutput: (String) -> Unit) { thread { if (!Stellar.pingBinder() || !Stellar.checkSelfPermission()) return@thread val pty = Stellar.newPtyProcess(arrayOf("sh"), null, null) // Adjust terminal window size pty.resize(cols = 120, rows = 40) val fd = pty.ptyFd val writer = ParcelFileDescriptor.AutoCloseOutputStream(fd) val reader = ParcelFileDescriptor.AutoCloseInputStream(fd) // Start output reading thread thread { try { val buf = ByteArray(4096) while (true) { val n = reader.read(buf) if (n < 0) break onOutput(String(buf, 0, n)) } } catch (_: Exception) {} } // Send commands writer.write("id\n".toByteArray()) writer.write("ls /sdcard\n".toByteArray()) writer.flush() // Wait for exit val exitCode = pty.waitFor() println("PTY process exited with code: $exitCode") pty.destroy() } } ``` ``` -------------------------------- ### Create Privileged Process with Stellar Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use `Stellar.newProcess` to create a privileged process executing as the Stellar service. Specify command, optional environment variables, and working directory. ```kotlin // 创建特权进程(以 Stellar 服务的身份执行) Stellar.newProcess( cmd: Array, // 命令和参数 env: Array?, // 环境变量(可选) dir: String? // 工作目录(可选) ): StellarRemoteProcess ``` -------------------------------- ### Build Server Module Only Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Build only the server module of the project. ```bash ./gradlew :server:assemble ``` -------------------------------- ### Check Stellar Service Status and API Version Source: https://context7.com/roro2239/stellar/llms.txt Use Stellar.pingBinder() to verify if the Stellar service is running. Stellar.uid indicates the running mode (Root or ADB), and Stellar.version provides the API version. Additional details like SELinux context and manager version are also available. ```kotlin import roro.stellar.Stellar fun checkServiceStatus() { // 1. 检查服务是否在线 if (!Stellar.pingBinder()) { println("❌ Stellar 服务未运行") return } // 2. 判断运行模式 val mode = when (Stellar.uid) { 0 -> "Root 模式" 2000 -> "ADB 模式" else -> "未知模式 (uid=${Stellar.uid})" } println("✅ 服务在线 | 模式: $mode | API 版本: ${Stellar.version}") // 3. 读取附加信息 println("SELinux 上下文: ${Stellar.sELinuxContext}") println("管理器版本: ${Stellar.versionName} (${Stellar.versionCode})") // 示例输出: // ✅ 服务在线 | 模式: ADB 模式 | API 版本: 3 // SELinux 上下文: u:r:shell:s0 // 管理器版本: 1.0.16 (100160) } ``` -------------------------------- ### Stellar.newProcess() Source: https://context7.com/roro2239/stellar/llms.txt Create and execute a system command as the Stellar service (Shell uid=2000 or Root uid=0). It returns a `StellarRemoteProcess` object, providing standard stdin/stdout/stderr streams and timeout capabilities. ```APIDOC ## `Stellar.newProcess()` — Privileged Process Execution Create and execute a system command as the Stellar service (Shell uid=2000 or Root uid=0). It returns a `StellarRemoteProcess` object, providing standard stdin/stdout/stderr streams and timeout capabilities. ### Description This method allows you to execute commands with elevated privileges, similar to running them from the `adb shell` or as root. It's useful for system-level operations that require special permissions. ### Method `Stellar.newProcess(command: Array, environment: Array?, workingDirectory: String?): StellarRemoteProcess` ### Parameters - `command` (Array): The command and its arguments to execute. - `environment` (Array?, Optional): Environment variables for the new process. If null, inherits the environment of the Stellar service. - `workingDirectory` (String?, Optional): The working directory for the command. If null, uses the default working directory. ### Returns - `StellarRemoteProcess`: An object representing the remote process, with methods to access streams and manage its lifecycle. ### Example ```kotlin import roro.stellar.Stellar import kotlin.concurrent.thread fun executePrivilegedCommand() { thread { try { // Execute commands that require Shell privileges val process = Stellar.newProcess( arrayOf("ls", "-la", "/data/local/tmp"), null, // Environment variables (null = inherit) null // Working directory (null = default) ) // Read standard output val stdout = process.inputStream.bufferedReader().readText() println("Output:\n$stdout") // Read error output val stderr = process.errorStream.bufferedReader().readText() if (stderr.isNotEmpty()) println("Error:\n$stderr") // Wait for completion (with timeout) val finished = process.waitForTimeout(10, java.util.concurrent.TimeUnit.SECONDS) if (!finished) { println("Command timed out, forcing termination") process.destroy() } else { println("Exit code: ${process.exitValue()}") } } catch (e: Exception) { println("Execution failed: ${e.message}") } } } ``` ``` -------------------------------- ### Enable Multi-Process Support Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Configure StellarProvider for multi-process applications by enabling support and requesting binders in non-provider processes. ```kotlin class MyApplication : Application() { override fun onCreate() { super.onCreate() // 判断当前进程是否是 Provider 进程 val isProviderProcess = // 你的判断逻辑 StellarProvider.enableMultiProcessSupport(isProviderProcess) // 如果不是 Provider 进程,请求 Binder if (!isProviderProcess) { StellarProvider.requestBinderForNonProviderProcess(this) } } } ``` -------------------------------- ### Update Helper Methods for Stellar Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Replace ShizukuProvider helper methods with their StellarHelper equivalents. ```kotlin // 替换 // ShizukuProvider.isShizukuInstalled(context) // ShizukuProvider.openShizuku(context) // 为 StellarHelper.isManagerInstalled(context) StellarHelper.openManager(context) ``` -------------------------------- ### Clean Build Artifacts Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Use this command to clean previously built artifacts. ```bash ./gradlew clean ``` -------------------------------- ### Build API Library Only Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Build only the API library module of the project. ```bash ./gradlew :api:assemble ``` -------------------------------- ### Execute Command with Timeout Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Execute a command using Stellar and handle potential timeouts by waiting for a specified duration and destroying the process if necessary. ```kotlin fun executeCommandWithTimeout() { thread { try { val process = Stellar.newProcess( arrayOf("sleep", "10"), null, null ) // 等待最多 5 秒 val finished = process.waitForTimeout(5, TimeUnit.SECONDS) if (!finished) { println("命令超时,强制终止") process.destroy() } else { println("命令完成,退出码: ${process.exitValue()}") } } catch (e: Exception) { println("错误: ${e.message}") } } } ``` -------------------------------- ### Add Stellar API Dependency and Configure Manifest Source: https://context7.com/roro2239/stellar/llms.txt Integrate Stellar by adding its dependency via JitPack and configuring the AndroidManifest.xml with StellarProvider and necessary meta-data for permissions. ```gradle dependencyResolutionManagement { repositories { google() mavenCentral() maven { url 'https://jitpack.io' } } } // app/build.gradle dependencies { implementation 'com.github.roro2239.Stellar-API:latest.release' } ``` ```xml ``` -------------------------------- ### JitPack Build Configuration Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Note that when building in a JitPack environment (JITPACK=true), the manager and server modules are excluded. ```plaintext JITPACK=true ``` -------------------------------- ### Execute Shell Command via Stellar Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Executes a shell command asynchronously using Stellar's process creation capabilities and prints the command's output and exit code. ```kotlin fun executeCommand() { thread { try { println("$ ls -la /sdcard") val process = Stellar.newProcess( arrayOf("ls", "-la", "/sdcard"), null, null ) val reader = BufferedReader(InputStreamReader(process.inputStream)) reader.lineSequence().forEach { line -> println(line) } val exitCode = process.waitFor() println("退出码: $exitCode") process.destroy() } catch (e: Exception) { println("错误: ${e.message}") } } } ``` -------------------------------- ### Read System Properties Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Retrieves various system properties such as product brand, model, Android version, and SDK version using StellarSystemProperties. ```kotlin fun readSystemProperties() { try { val brand = StellarSystemProperties.get("ro.product.brand") println("品牌: $brand") val model = StellarSystemProperties.get("ro.product.model") println("型号: $model") val androidVersion = StellarSystemProperties.get("ro.build.version.release") println("Android 版本: $androidVersion") val sdkInt = StellarSystemProperties.getInt("ro.build.version.sdk", 0) println("SDK 版本: $sdkInt") } catch (e: Exception) { println("错误: ${e.message}") } } ``` -------------------------------- ### Configure UserServiceArgs with Builder Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use the `UserServiceArgs.Builder` to configure parameters for a user service, such as process name suffix, debug mode, version code, and service mode. ```kotlin val args = UserServiceArgs.Builder(MyUserService::class.java) .processNameSuffix("myservice") // 进程名后缀,默认 "userservice" .debug(BuildConfig.DEBUG) // 是否启用调试模式 .versionCode(BuildConfig.VERSION_CODE.toLong()) // 版本号 .tag("my-tag") // 可选标签 .serviceMode(ServiceMode.DAEMON) // 服务模式 .build() ``` -------------------------------- ### Server Core Components Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Overview of the core components within the server module. ```plaintext - `StellarService`:AIDL Stub 主体,组装所有子系统 - `service/StellarServiceCore`:聚合各功能管理器(权限/进程/日志/系统属性/用户服务) - `communication/`:通信层 - `StellarCommunicationBridge`:统一请求分发(调用 StellarServiceCore 各子管理器) - `PermissionEnforcer`:调用级权限校验(管理器/自身/客户端三级判断) - `CallerContext`:封装调用者 uid/pid - `bootstrap/ServerBootstrap`:服务引导(等待系统服务就绪、获取管理器信息) - `binder/BinderDistributor`:Binder 分发到所有客户端和管理器 - `service/permission/`:PermissionManager、PermissionChecker、PermissionConfirmation、PermissionRequester - `service/process/ProcessManager`:进程管理 - `service/log/LogManager`:日志管理(支持持久化) - `service/system/SystemPropertyManager`:系统属性管理 - `service/info/`:ServiceInfoProvider、VersionProvider - `service/userservice/UserServiceCoordinator`:用户服务协调 - `userservice/UserServiceManager` / `UserServiceStarter`:用户服务生命周期 - `shizuku/ShizukuServiceIntercept`:Shizuku 兼容层服务端实现 - `ClientManager` / `ClientRecord`:客户端连接管理 - `ConfigManager`:配置持久化(权限标记、开关等) - `grant/ManagerGrantHelper`:管理器权限授予(WRITE_SECURE_SETTINGS、无障碍服务) - `api/`:RemoteProcessHolder、RemotePtyProcessHolder、IContentProviderUtils - `monitor/PackageMonitor`:包变更监听 - `ext/FollowStellarStartupExt`:跟随服务启动命令执行 ``` -------------------------------- ### Check Stellar Service Status Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use pingBinder() to check if the Stellar service is running. Access uid, version, and SELinux context for service information. ```kotlin // 检查服务是否运行 Stellar.pingBinder(): Boolean // 获取服务 UID (0 = root, 2000 = adb) Stellar.uid: Int // 获取服务 API 版本 Stellar.version: Int // 获取最新支持的版本 Stellar.latestServiceVersion: Int // 获取 SELinux 上下文 Stellar.sELinuxContext: String? // 获取管理器版本 Stellar.versionName: String? Stellar.versionCode: Int ``` -------------------------------- ### Build Debug APK Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Use this command to build the debug version of the Android application. ```bash ./gradlew :manager:assembleDebug ``` -------------------------------- ### Local Properties Configuration Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Configuration for using local API source code. Set `api.useLocal=true` and `api.dir` to the path of the local API source. ```properties api.useLocal=true api.dir=路径 ``` -------------------------------- ### Create PTY Privileged Process with Stellar Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use `Stellar.newPtyProcess` for privileged processes that require terminal features like colors, signals, and window size adjustments. Supports command, optional environment variables, and working directory. ```kotlin // 创建 PTY 特权进程(支持终端特性:颜色、信号、窗口大小调整) Stellar.newPtyProcess( cmd: Array, // 命令和参数 env: Array?, // 环境变量(可选) dir: String? // 工作目录(可选) ): StellarPtyProcess ``` -------------------------------- ### Execute System Commands as Stellar Service Source: https://context7.com/roro2239/stellar/llms.txt Create and execute system commands with the identity of the Stellar service (Shell uid=2000 or Root uid=0). Returns a `StellarRemoteProcess` with stdin/stdout/stderr streams and timeout capabilities. ```kotlin import roro.stellar.Stellar import kotlin.concurrent.thread fun executePrivilegedCommand() { thread { try { // 执行需要 Shell 权限的命令 val process = Stellar.newProcess( arrayOf("ls", "-la", "/data/local/tmp"), null, // 环境变量(null = 继承) null // 工作目录(null = 默认) ) // 读取标准输出 val stdout = process.inputStream.bufferedReader().readText() println("输出:\n$stdout") // 读取错误输出 val stderr = process.errorStream.bufferedReader().readText() if (stderr.isNotEmpty()) println("错误:\n$stderr") // 等待完成(带超时) val finished = process.waitForTimeout(10, java.util.concurrent.TimeUnit.SECONDS) if (!finished) { println("命令超时,强制终止") process.destroy() } else { println("退出码: ${process.exitValue()}") } } catch (e: Exception) { println("执行失败: ${e.message}") } } } ``` -------------------------------- ### Stellar.checkSelfPermission() / Stellar.requestPermission() Source: https://context7.com/roro2239/stellar/llms.txt Checks if the current application has been granted a specific permission and triggers a system authorization prompt if not. Supports 'stellar' (basic API access) and 'follow_stellar_startup' (service companion startup) permission types. ```APIDOC ## Stellar.checkSelfPermission() / Stellar.requestPermission() ### Description Checks if the current application has been granted a specific permission and triggers a system authorization prompt if not. Supports 'stellar' (basic API access) and 'follow_stellar_startup' (service companion startup) permission types. ### Method `checkSelfPermission()`: Returns `true` if the permission is granted, `false` otherwise. `requestPermission(permission: String, requestCode: Int)`: Requests the specified permission. `addRequestPermissionResultListener(listener: OnRequestPermissionResultListener)`: Adds a listener for permission request results. `removeRequestPermissionResultListener(listener: OnRequestPermissionResultListener)`: Removes a previously added listener. `shouldShowRequestPermissionRationale()`: Returns `true` if the system recommends showing a rationale for the permission. ### Parameters #### Permission Types - **stellar**: Basic API access permission. - **follow_stellar_startup**: Service companion startup permission. ### Usage Example ```kotlin import roro.stellar.Stellar import androidx.activity.ComponentActivity import android.os.Bundle class MainActivity : ComponentActivity() { private val permissionResultListener = Stellar.OnRequestPermissionResultListener { requestCode, allowed, onetime -> when { allowed && onetime -> println("Permission granted (one-time)") allowed && !onetime -> println("Permission permanently granted") else -> { println("Permission denied") if (Stellar.shouldShowRequestPermissionRationale()) { // Show explanation dialog } else { // Guide user to grant permission manually in the manager StellarHelper.openManager(this) } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Stellar.addRequestPermissionResultListener(permissionResultListener) // Check and request permission if (Stellar.pingBinder() && !Stellar.checkSelfPermission()) { Stellar.requestPermission(permission = "stellar", requestCode = 100) } } override fun onDestroy() { super.onDestroy() Stellar.removeRequestPermissionResultListener(permissionResultListener) } } ``` ``` -------------------------------- ### Dependency and Import Replacements for Stellar API Source: https://context7.com/roro2239/stellar/llms.txt Replace Shizuku dependencies with Stellar API and update import statements accordingly. This is the first step in migrating your application. ```kotlin // ── 依赖替换 ───────────────────────────────────────── // 移除: implementation 'dev.rikka.shizuku:api:13.1.5' // 添加: implementation 'com.github.roro2239.Stellar-API:latest.release' ``` ```kotlin // ── 导入替换 ───────────────────────────────────────── // import rikka.shizuku.Shizuku → import roro.stellar.Stellar // import rikka.shizuku.ShizukuProvider → import roro.stellar.StellarProvider ``` -------------------------------- ### Add JitPack Repository to settings.gradle Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Configure your project to use the JitPack repository to fetch Stellar API dependencies. ```gradle dependencyResolutionManagement { repositories { google() mavenCentral() maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### UserServiceHelper Methods Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Provides utility methods for interacting with a user service Binder, including destroying the service, checking its liveness, and retrieving its UID and PID. ```kotlin // 销毁用户服务 UserServiceHelper.destroy(binder: IBinder) // 检查服务是否存活 UserServiceHelper.isAlive(binder: IBinder): Boolean // 获取服务进程的 UID UserServiceHelper.getUid(binder: IBinder): Int // 获取服务进程的 PID UserServiceHelper.getPid(binder: IBinder): Int ``` -------------------------------- ### Stellar Service Callback Interface Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Implement the `ServiceCallback` interface to handle events like service connection, disconnection, and startup failures. ```kotlin interface ServiceCallback { // 服务连接成功 fun onServiceConnected(service: IBinder) // 服务断开连接 fun onServiceDisconnected() // 服务启动失败(可选实现) fun onServiceStartFailed(errorCode: Int, message: String) {} } ``` -------------------------------- ### Stellar API to Shizuku API Mapping Source: https://context7.com/roro2239/stellar/llms.txt A comparative table showing equivalent API calls between Shizuku and Stellar. Note that some Shizuku methods are mapped to properties in Stellar. ```kotlin // ── API 对照表 ──────────────────────────────────────── // Shizuku.pingBinder() → Stellar.pingBinder() // Shizuku.getUid() → Stellar.uid (改为属性) // Shizuku.getVersion() → Stellar.version (改为属性) // Shizuku.checkSelfPermission() → Stellar.checkSelfPermission() // Shizuku.requestPermission(code) → Stellar.requestPermission(requestCode = code) // ShizukuProvider.isShizukuInstalled() → StellarHelper.isManagerInstalled() // ShizukuProvider.openShizuku() → StellarHelper.openManager() // Shizuku.bindUserService() → StellarUserService.bindUserService() ``` -------------------------------- ### Wrap System Service Binder Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use `StellarBinderWrapper` to wrap a system service Binder, enabling privileged access to its methods, demonstrated here with `IPackageManager`. ```kotlin val binder = StellarBinderWrapper.getSystemService("package") val pm = IPackageManager.Stub.asInterface(StellarBinderWrapper(binder)) // 现在可以使用特权 PackageManager API ``` -------------------------------- ### Manage Stellar Permissions with Request and Check Source: https://context7.com/roro2239/stellar/llms.txt Check if the application has the required Stellar permissions using checkSelfPermission() and request them if necessary via requestPermission(). Handles permission results and provides guidance for manual authorization if denied. ```kotlin import roro.stellar.Stellar class MainActivity : ComponentActivity() { private val permissionResultListener = Stellar.OnRequestPermissionResultListener { requestCode, allowed, onetime -> when { allowed && onetime -> println("权限已授予(一次性)") allowed && !onetime -> println("权限已永久授予") else -> { println("权限被拒绝") if (Stellar.shouldShowRequestPermissionRationale()) { // 显示说明对话框 } else { // 引导用户到管理器手动授权 StellarHelper.openManager(this) } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Stellar.addRequestPermissionResultListener(permissionResultListener) // 检查并请求权限 if (Stellar.pingBinder() && !Stellar.checkSelfPermission()) { Stellar.requestPermission(permission = "stellar", requestCode = 100) } } override fun onDestroy() { super.onDestroy() Stellar.removeRequestPermissionResultListener(permissionResultListener) } } ``` -------------------------------- ### Stellar.pingBinder() / Stellar.uid / Stellar.version Source: https://context7.com/roro2239/stellar/llms.txt Checks if the Stellar service is running, determines its operating mode (Root/ADB), and retrieves the API version. This is a prerequisite for all privileged operations. ```APIDOC ## Stellar.pingBinder() / Stellar.uid / Stellar.version ### Description Checks if the Stellar service is running, determines its operating mode (Root/ADB), and retrieves the API version. This is a prerequisite for all privileged operations. ### Method `pingBinder()`: Checks service status. `uid`: Returns the UID of the Stellar service (0 for Root, 2000 for ADB). `version`: Returns the API version number. ### Usage Example ```kotlin import roro.stellar.Stellar fun checkServiceStatus() { // 1. Check if the service is online if (!Stellar.pingBinder()) { println("❌ Stellar service is not running") return } // 2. Determine the operating mode val mode = when (Stellar.uid) { 0 -> "Root Mode" 2000 -> "ADB Mode" else -> "Unknown Mode (uid=${Stellar.uid})" } println("✅ Service Online | Mode: $mode | API Version: ${Stellar.version}") // 3. Read additional information println("SELinux Context: ${Stellar.sELinuxContext}") println("Manager Version: ${Stellar.versionName} (${Stellar.versionCode})") } ``` ### Response Example ``` ✅ Service Online | Mode: ADB Mode | API Version: 3 SELinux Context: u:r:shell:s0 Manager Version: 1.0.16 (100160) ``` ``` -------------------------------- ### Check Service Mode (Root or ADB) Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Determine if the Stellar service is running in Root or ADB mode by checking the UID or using StellarHelper. ```kotlin val uid = Stellar.uid when (uid) { 0 -> println("Root 模式") 2000 -> println("ADB 模式") else -> println("未知模式: $uid") } // 或使用 StellarHelper val serviceInfo = StellarHelper.serviceInfo if (serviceInfo?.isRoot == true) { println("Root 模式") } else if (serviceInfo?.isAdb == true) { println("ADB 模式") } ``` -------------------------------- ### Execute Command and Handle Errors in Kotlin Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Use this Kotlin function to execute a command and capture both its standard output and error streams. It also retrieves the exit code and handles potential exceptions during execution. ```kotlin fun executeCommandWithErrorHandling() { thread { try { val process = Stellar.newProcess( arrayOf("ls", "/nonexistent"), null, null ) // 读取标准输出 val outputReader = BufferedReader(InputStreamReader(process.inputStream)) outputReader.lineSequence().forEach { line -> println("输出: $line") } // 读取错误输出 val errorReader = BufferedReader(InputStreamReader(process.errorStream)) errorReader.lineSequence().forEach { line -> println("错误: $line") } val exitCode = process.waitFor() println("退出码: $exitCode") process.destroy() } catch (e: Exception) { println("异常: ${e.message}") } } } ``` -------------------------------- ### Add Stellar Dependency (Gradle) Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Update your project's Gradle dependencies to include the Stellar API. Ensure the JitPack repository is added to your `settings.gradle` file. ```gradle // 移除 Shizuku 依赖 // implementation 'dev.rikka.shizuku:api:13.1.5' // implementation 'dev.rikka.shizuku:provider:13.1.5' // 添加 Stellar 依赖 implementation 'com.github.roro2239.Stellar-API:<版本号>' ``` -------------------------------- ### StellarSystemProperties Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Utilities for reading and writing system properties with different permission levels. ```APIDOC ## StellarSystemProperties.get ### Description Reads a system property value. ### Method `StellarSystemProperties.get(key: String): String` `StellarSystemProperties.get(key: String, def: String): String` ### Parameters * **key** (String) - Required - The key of the system property. * **def** (String) - Optional - The default value to return if the property is not found. ## StellarSystemProperties.getInt ### Description Reads a system property value as an integer. ### Method `StellarSystemProperties.getInt(key: String, def: Int): Int` ### Parameters * **key** (String) - Required - The key of the system property. * **def** (Int) - Required - The default integer value. ## StellarSystemProperties.getLong ### Description Reads a system property value as a long. ### Method `StellarSystemProperties.getLong(key: String, def: Long): Long` ### Parameters * **key** (String) - Required - The key of the system property. * **def** (Long) - Required - The default long value. ## StellarSystemProperties.getBoolean ### Description Reads a system property value as a boolean. ### Method `StellarSystemProperties.getBoolean(key: String, def: Boolean): Boolean` ### Parameters * **key** (String) - Required - The key of the system property. * **def** (Boolean) - Required - The default boolean value. ## StellarSystemProperties.set ### Description Writes a value to a system property. Requires appropriate permissions (ADB or Root). ### Method `StellarSystemProperties.set(key: String, value: String)` ### Parameters * **key** (String) - Required - The key of the system property. * **value** (String) - Required - The value to set for the property. ### Permissions * **ADB Mode (uid=2000):** Can write `debug.*`, `persist.debug.*`, `log.*`, `vendor.debug.*`. * **Root Mode (uid=0):** Can write most properties, except `ro.*` (read-only) properties. ``` -------------------------------- ### Manage Stellar Permissions Source: https://github.com/roro2239/stellar/blob/main/INTEGRATION_GUIDE.md Check, request, and verify Stellar permissions using checkSelfPermission, requestPermission, and shouldShowRequestPermissionRationale. Also check remote permissions and supported permission lists. ```kotlin // 检查权限是否已授予 Stellar.checkSelfPermission(permission: String = "stellar"): Boolean // 请求权限 Stellar.requestPermission(permission: String = "stellar", requestCode: Int) // 检查是否应该显示权限说明 Stellar.shouldShowRequestPermissionRationale(): Boolean // 检查 Stellar 服务自身是否拥有指定权限 Stellar.checkRemotePermission(permission: String): Int // 获取支持的权限列表 Stellar.supportedPermissions: Array ``` -------------------------------- ### Project Module Structure Source: https://github.com/roro2239/stellar/blob/main/AGENTS.md Overview of the project's module organization. ```plaintext manager/ → Android 应用(管理器 UI),applicationId: roro.stellar.manager server/ → 特权服务端逻辑(运行在 ADB/Root 进程中) api/ → 客户端 SDK(供第三方应用集成) ├── aidl/ → Stellar AIDL 接口(IStellarService, IRemoteProcess, IRemotePtyProcess 等) ├── api/ → 客户端 API 入口(Stellar.kt, StellarHelper.kt) ├── provider/ → StellarProvider(ContentProvider,接收服务端 Binder) ├── shared/ → 共享常量(StellarApiConstants) ├── userservice/ → UserService 框架 └── demo/ → API 示例应用 shizuku/ → Shizuku 兼容层 ├── aidl/ → Shizuku AIDL 接口(IShizukuService 等) └── api/ → ShizukuCompat, ShizukuProvider ```