Skip to content

Use assistant to launch privileged services and broadcasts without root #1973

@ilmmatias

Description

@ilmmatias

Please check before submitting an issue

  • I am using the latest version of App Manager
  • I have searched the issues and haven't found anything relevant
  • I have read the docs
  • I know that generating a report, in whole part or in part, using AI/LLM is prohibited

Describe the new feature

Root already supports privileged startService and sendBroadcast, but currently ADB only supports startActivity (via assistant). During my personal testing, this seems to work fine on my own Android 16 device (but I haven't tested on other phones):

object SystemContext {
    fun startActivity(context: Context, intent: Intent) =
        context.fireActivityTrampoline(intent)

    fun startService(context: Context, intent: Intent) =
        context.fireTypedTrampoline("SERVICE", intent)

    fun sendBroadcast(context: Context, intent: Intent) =
        context.fireTypedTrampoline("BROADCAST", intent)

    private fun Context.fireActivityTrampoline(intent: Intent) {
        if (checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) != PackageManager.PERMISSION_GRANTED) {
            val pm = IPackageManager.Stub.asInterface(
                ShizukuBinderWrapper(
                    SystemServiceHelper.getSystemService("package")
                )
            )

            pm.grantRuntimePermission(
                packageName,
                android.Manifest.permission.WRITE_SECURE_SETTINGS,
                UserHandle.USER_SYSTEM
            )
        }

        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        val currentAssistant = Settings.Secure.getString(contentResolver, Settings.Secure.ASSISTANT)
        Settings.Secure.putString(
            contentResolver,
            Settings.Secure.ASSISTANT,
            intent.component?.flattenToString()
        )

        searchManager.launchAssist(intent.extras ?: Bundle())

        Thread.sleep(500)
        Settings.Secure.putString(contentResolver, Settings.Secure.ASSISTANT, currentAssistant)
    }

    private fun Context.fireTypedTrampoline(type: String, intent: Intent) {
        fireActivityTrampoline(Intent().apply {
            component = ComponentName(
                "com.android.settings",
                "androidx.glance.appwidget.action.InvisibleActionTrampolineActivity"
            )

            putExtra("ACTION_TYPE", type)
            putExtra("ACTION_INTENT", intent)
        })
    }
}

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Additional context

For now I haven't been able to get bindService from the other 3, though probably there's some way if look deep enough in all apps/services that share UID 1000.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FeatureNew feature or requestStatus: AcceptedAccepted or approved feature/issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions