### 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
```