Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for non-root autostart on boot (can be enabled whit the same toggle in settings) #584

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions manager/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
<uses-permission android:name="moe.shizuku.manager.permission.MANAGER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<!-- this permission is required for autostart on non-root! -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" tools:ignore="ProtectedPermissions" />

<uses-permission
android:name="moe.shizuku.manager.permission.API_V23"
tools:node="remove" />
Expand Down Expand Up @@ -83,6 +87,9 @@
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
</intent-filter>
</activity>
<activity
android:name=".receiver.LaunchActivity"
android:label="" />
<activity
android:name=".starter.StarterActivity"
android:label="@string/starter" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import moe.shizuku.manager.databinding.AboutDialogBinding
import moe.shizuku.manager.databinding.HomeActivityBinding
import moe.shizuku.manager.ktx.toHtml
import moe.shizuku.manager.management.appsViewModel
import moe.shizuku.manager.receiver.LaunchActivity
import moe.shizuku.manager.settings.SettingsActivity
import moe.shizuku.manager.starter.Starter
import moe.shizuku.manager.utils.AppIconCache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,35 @@ package moe.shizuku.manager.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import android.os.Looper
import android.os.Process
import android.provider.Settings.Global
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.UiThreadHandler.handler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.shizuku.manager.AppConstants
import moe.shizuku.manager.ShizukuSettings
import moe.shizuku.manager.ShizukuSettings.LaunchMethod
import moe.shizuku.manager.adb.AdbClient
import moe.shizuku.manager.adb.AdbKey
import moe.shizuku.manager.adb.AdbMdns
import moe.shizuku.manager.adb.PreferenceAdbKeyStore
import moe.shizuku.manager.starter.Starter
import rikka.shizuku.Shizuku

@RequiresApi(Build.VERSION_CODES.R)
class BootCompleteReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
if (Intent.ACTION_LOCKED_BOOT_COMPLETED != intent.action
&& Intent.ACTION_BOOT_COMPLETED != intent.action) {
return
}

if (Process.myUid() / 100000 > 0) return

// TODO Record if receiver is called
if (ShizukuSettings.getLastLaunchMode() == LaunchMethod.ROOT) {
Log.i(AppConstants.TAG, "start on boot, action=" + intent.action)
Expand All @@ -35,11 +45,13 @@ class BootCompleteReceiver : BroadcastReceiver() {

private fun start(context: Context) {
if (!Shell.rootAccess()) {
//NotificationHelper.notify(context, AppConstants.NOTIFICATION_ID_STATUS, AppConstants.NOTIFICATION_CHANNEL_STATUS, R.string.notification_service_start_no_root)
return
Log.i("shizuku", "start non-root sihzuku")
val intents = Intent(context, LaunchActivity::class.java)
intents.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intents)
} else {
Starter.writeDataFiles(context)
Shell.su(Starter.dataCommand).exec()
}

Starter.writeDataFiles(context)
Shell.su(Starter.dataCommand).exec()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package moe.shizuku.manager.receiver

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.topjohnwu.superuser.internal.UiThreadHandler.handler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.shizuku.manager.ShizukuSettings
import moe.shizuku.manager.adb.AdbClient
import moe.shizuku.manager.adb.AdbKey
import moe.shizuku.manager.adb.AdbMdns
import moe.shizuku.manager.adb.PreferenceAdbKeyStore
import moe.shizuku.manager.starter.Starter

fun SecureSettingsAllowed(context: Context): Boolean {
val packageInfo: PackageInfo = context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
val list: List<String> = packageInfo.requestedPermissions!!.filterIndexed { index, permission ->
(packageInfo.requestedPermissionsFlags[index] and PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
}
if (list.contains("android.permission.WRITE_SECURE_SETTINGS")) { return true } else {return false}
}

class LaunchActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GlobalScope.launch { delay(1000)
Starter.writeSdcardFiles(applicationContext)
val context = applicationContext
if(SecureSettingsAllowed(context)) {
Log.i(application.packageName, "SecureSettingsAllowed")
val serviceIntent = Intent(context, StartService::class.java)
context.startService(serviceIntent)
}
}
}
}
85 changes: 85 additions & 0 deletions manager/src/main/java/moe/shizuku/manager/receiver/startService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package moe.shizuku.manager.receiver

import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.os.Looper
import android.provider.Settings.Global
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.topjohnwu.superuser.internal.UiThreadHandler.handler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.shizuku.manager.ShizukuSettings
import moe.shizuku.manager.adb.AdbClient
import moe.shizuku.manager.adb.AdbKey
import moe.shizuku.manager.adb.AdbMdns
import moe.shizuku.manager.adb.PreferenceAdbKeyStore
import moe.shizuku.manager.starter.Starter

private fun Launch(port: Int) {
Log.i("AAAA", "LAUNCHING SHIZUKU")
GlobalScope.launch(Dispatchers.IO) {
val host = "127.0.0.1"

val key = try {
AdbKey(PreferenceAdbKeyStore(ShizukuSettings.getPreferences()), "shizuku")
} catch (e: Throwable) {
e.printStackTrace()
return@launch
}
AdbClient(host, port, key).runCatching {
connect()
shellCommand(Starter.sdcardCommand) {}
close()
}.onFailure {
it.printStackTrace()
}
}

}

@RequiresApi(Build.VERSION_CODES.R)
fun startupNonRoot(context: Context) {
val adbPort = MutableLiveData<Int>()
val adbConnect = AdbMdns(context, AdbMdns.TLS_CONNECT, adbPort)
val ConnectObserver = Observer<Int> { port ->
if (port in 0..65535) {
Log.i(context.packageName, "port: " + port)
adbConnect.stop()
Launch(port)
}
}
if (Looper.myLooper() == Looper.getMainLooper()) {
adbPort.observeForever(ConnectObserver)
} else {
handler.post { adbPort.observeForever(ConnectObserver) }
}
adbConnect.start()
}


class StartService() : Service() {
@RequiresApi(Build.VERSION_CODES.R)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(application.packageName, "startservice")
GlobalScope.launch {
delay(500)
val context = getApplicationContext();
Global.putLong(context.getContentResolver(), "adb_allowed_connection_time", 0L)
Global.putInt(context.getContentResolver(), "adb_wifi_enabled", 1);
Log.i(application.packageName, "adb_wifi_enabled")
startupNonRoot(context)
}
return START_STICKY // Consider using START_STICKY to restart the service if killed
}
override fun onBind(intent: Intent?): IBinder? {
return null // We don't intend to bind to this service from other components
}
}