├── common ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── moe │ │ └── shizuku │ │ └── common │ │ └── util │ │ ├── OsUtils.java │ │ └── BuildUtils.java └── build.gradle ├── server ├── .gitignore ├── proguard-rules.pro ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── rikka │ │ └── shizuku │ │ └── server │ │ ├── ShizukuClientManager.java │ │ ├── ktx │ │ └── Handler.kt │ │ ├── ServerConstants.java │ │ ├── api │ │ └── IContentProviderUtils.java │ │ └── ShizukuConfig.java └── build.gradle ├── shell ├── .gitignore ├── src │ └── main │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── starter ├── proguard-rules.pro ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── moe │ │ └── shizuku │ │ └── starter │ │ └── util │ │ └── IContentProviderCompat.java └── build.gradle ├── manager ├── src │ └── main │ │ ├── .gitignore │ │ ├── jni │ │ ├── adb_pairing.h │ │ ├── android.h │ │ ├── cgroup.h │ │ ├── misc.h │ │ ├── selinux.h │ │ ├── android.cpp │ │ ├── logging.h │ │ ├── helper.cpp │ │ ├── cgroup.cpp │ │ ├── CMakeLists.txt │ │ └── selinux.cpp │ │ ├── res │ │ ├── values-bg │ │ │ └── strings.xml │ │ ├── values-ml │ │ │ └── strings.xml │ │ ├── values-ars │ │ │ └── strings.xml │ │ ├── mipmap-xhdpi │ │ │ ├── banner.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ └── ic_launcher_foreground.png │ │ ├── values-sw600dp │ │ │ ├── bools.xml │ │ │ ├── dimens.xml │ │ │ └── values.xml │ │ ├── values-night │ │ │ └── styles.xml │ │ ├── drawable │ │ │ ├── ic_launcher.xml │ │ │ ├── ic_server_start_24dp.xml │ │ │ ├── ic_warning_24.xml │ │ │ ├── shape_circle_icon_background.xml │ │ │ ├── ic_outline_play_arrow_24.xml │ │ │ ├── ic_code_24dp.xml │ │ │ ├── ic_outline_arrow_upward_24.xml │ │ │ ├── ic_close_24.xml │ │ │ ├── ic_numeric_1_circle_outline_24.xml │ │ │ ├── ic_terminal_24.xml │ │ │ ├── ic_action_about_24dp.xml │ │ │ ├── ic_outline_info_24.xml │ │ │ ├── ic_outline_open_in_new_24.xml │ │ │ ├── ic_numeric_2_circle_outline_24.xml │ │ │ ├── ic_root_24dp.xml │ │ │ ├── ic_baseline_link_24.xml │ │ │ ├── ic_numeric_3_circle_outline_24.xml │ │ │ ├── ic_server_ok_24dp.xml │ │ │ ├── ic_server_error_24dp.xml │ │ │ ├── ic_learn_more_24dp.xml │ │ │ ├── grant_permissions_buttons_bottom.xml │ │ │ ├── grant_permissions_buttons_top.xml │ │ │ ├── ic_adb_24dp.xml │ │ │ ├── ic_outline_translate_24.xml │ │ │ ├── ic_system_icon.xml │ │ │ ├── ic_server_restart.xml │ │ │ ├── ic_outline_dark_mode_24.xml │ │ │ ├── ic_wadb_24.xml │ │ │ ├── ic_outline_notifications_active_24.xml │ │ │ ├── card_btn_background.xml │ │ │ ├── home_card_foreground.xml │ │ │ ├── ic_monochrome.xml │ │ │ ├── ic_help_outline_24dp.xml │ │ │ ├── ic_action_settings_24dp.xml │ │ │ └── ic_settings_outline_24dp.xml │ │ ├── values │ │ │ ├── attrs.xml │ │ │ ├── values.xml │ │ │ ├── bools.xml │ │ │ ├── strings_untranslatable.xml │ │ │ ├── colors.xml │ │ │ ├── arrays.xml │ │ │ ├── themes_overlay.xml │ │ │ ├── dimens.xml │ │ │ └── themes.xml │ │ ├── color │ │ │ ├── home_card_foreground_color.xml │ │ │ ├── home_card_background_color.xml │ │ │ └── grant_permissions_button_ripple_color_selector.xml │ │ ├── color-night │ │ │ ├── home_card_foreground_color.xml │ │ │ └── home_card_background_color.xml │ │ ├── xml │ │ │ ├── backup_descriptor.xml │ │ │ ├── data_extraction_rules.xml │ │ │ └── settings.xml │ │ ├── drawable-v26 │ │ │ ├── ic_default_app_icon.xml │ │ │ └── ic_launcher.xml │ │ ├── values-ang │ │ │ └── strings.xml │ │ ├── values-v31 │ │ │ └── themes_overlay.xml │ │ ├── values-es │ │ │ └── strings.xml │ │ ├── menu │ │ │ └── main.xml │ │ ├── layout │ │ │ ├── appbar_activity.xml │ │ │ ├── home_item_container.xml │ │ │ ├── shell_dialog.xml │ │ │ ├── preference_recyclerview.xml │ │ │ ├── apps_activity.xml │ │ │ ├── appbar_fragment_activity.xml │ │ │ ├── home_activity.xml │ │ │ ├── appbar.xml │ │ │ ├── app_list_empty.xml │ │ │ ├── adb_dialog.xml │ │ │ ├── home_learn_more.xml │ │ │ ├── home_manage_apps_item.xml │ │ │ ├── starter_activity.xml │ │ │ ├── home_terminal.xml │ │ │ ├── home_server_status.xml │ │ │ ├── confirmation_dialog.xml │ │ │ ├── about_dialog.xml │ │ │ ├── home_start_adb.xml │ │ │ ├── home_start_root.xml │ │ │ ├── home_start_wireless_adb.xml │ │ │ ├── home_extra_step_required.xml │ │ │ └── app_list_item.xml │ │ ├── animator │ │ │ └── alpha_animator.xml │ │ ├── values-he │ │ │ └── strings.xml │ │ ├── raw │ │ │ └── start.sh │ │ ├── values-eo │ │ │ └── strings.xml │ │ ├── drawable-v24 │ │ │ └── ic_default_app_icon_foreground.xml │ │ ├── values-v21 │ │ │ └── themes_override.xml │ │ ├── values-es-rCL │ │ │ └── strings.xml │ │ └── values-ar │ │ │ └── strings.xml │ │ ├── assets │ │ ├── rish_shizuku.dex │ │ └── rish │ │ └── java │ │ └── moe │ │ └── shizuku │ │ └── manager │ │ ├── MainActivity.java │ │ ├── Manifest.java │ │ ├── utils │ │ ├── UserInfoCompat.java │ │ ├── UserHandleCompat.java │ │ ├── EnvironmentUtils.kt │ │ ├── MultiLocaleEntity.java │ │ └── EmptySharedPreferencesImpl.java │ │ ├── model │ │ └── ServiceStatus.kt │ │ ├── legacy │ │ └── ShellRequestHandlerActivity.kt │ │ ├── AppConstants.java │ │ ├── receiver │ │ ├── ShizukuReceiver.kt │ │ └── BootCompleteReceiver.kt │ │ ├── ktx │ │ ├── String.kt │ │ ├── Context.kt │ │ ├── PackageManager.kt │ │ ├── Log.kt │ │ └── RecyclerView.kt │ │ ├── adb │ │ ├── AdbException.kt │ │ └── AdbProtocol.kt │ │ ├── home │ │ ├── WadbNotEnabledDialogFragment.kt │ │ ├── LearnMoreViewHolder.kt │ │ ├── AdbPermissionLimitedViewHolder.kt │ │ ├── TerminalViewHolder.kt │ │ ├── ManageAppsViewHolder.kt │ │ ├── HomeViewModel.kt │ │ ├── HomeAdapter.kt │ │ ├── StartRootViewHolder.kt │ │ └── StartAdbViewHolder.kt │ │ ├── settings │ │ └── SettingsActivity.kt │ │ ├── management │ │ ├── AppsAdapter.java │ │ ├── EmptyViewHolder.kt │ │ ├── ApplicationManagementActivity.kt │ │ └── AppsViewModel.kt │ │ ├── shell │ │ ├── ShellBinderRequestHandler.kt │ │ └── Shell.java │ │ ├── ShizukuApplication.kt │ │ ├── widget │ │ ├── VerticalPaddingDecoration.java │ │ └── CheckedImageView.java │ │ ├── app │ │ ├── ThemeHelper.java │ │ ├── AppBarActivity.kt │ │ └── AppActivity.kt │ │ ├── Helps.java │ │ └── ShizukuManagerProvider.kt ├── .gitignore ├── aapt2-resources.cfg └── proguard-rules.pro ├── .github └── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.md ├── .gitattributes ├── .idea ├── .gitignore ├── compiler.xml ├── vcs.xml ├── misc.xml ├── gradle.xml └── jarRepositories.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitmodules ├── .gitignore ├── local.properties ├── gradle.properties ├── signing.gradle ├── settings.gradle ├── gradle-mavenizer.gradle └── gradlew.bat /common/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /server/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shell/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /starter/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /starter/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /manager/src/main/.gitignore: -------------------------------------------------------------------------------- 1 | /assets/*.dex -------------------------------------------------------------------------------- /manager/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /signing.properties 3 | /.cxx -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.bat text eol=crlf 4 | *.jar binary -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /manager/src/main/jni/adb_pairing.h: -------------------------------------------------------------------------------- 1 | #ifndef ADB_H 2 | #define ADB_H 3 | 4 | #endif // ADB_H 5 | -------------------------------------------------------------------------------- /manager/src/main/res/values-bg/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /manager/src/main/res/values-ml/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /manager/src/main/res/values-ars/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shell/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /starter/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /server/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /manager/src/main/assets/rish_shizuku.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/assets/rish_shizuku.dex -------------------------------------------------------------------------------- /shell/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keep class rikka.shizuku.shell.ShizukuShellLoader { 2 | public static void main(java.lang.String[]); 3 | } 4 | -------------------------------------------------------------------------------- /manager/src/main/jni/android.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace android { 4 | 5 | int GetApiLevel(); 6 | 7 | int GetPreviewApiLevel(); 8 | } -------------------------------------------------------------------------------- /manager/src/main/res/mipmap-xhdpi/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/res/mipmap-xhdpi/banner.png -------------------------------------------------------------------------------- /manager/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /manager/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /manager/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /manager/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ShizukuHack/HEAD/manager/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /manager/src/main/res/values-sw600dp/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | -------------------------------------------------------------------------------- /manager/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_server_start_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_warning_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/shape_circle_icon_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_outline_play_arrow_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/model/ServiceStatus.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.model 2 | 3 | import rikka.shizuku.Shizuku 4 | 5 | data class ServiceStatus( 6 | val uid: Int = -1, 7 | val apiVersion: Int = -1, 8 | val patchVersion: Int = -1, 9 | val seContext: String? = null, 10 | val permission: Boolean = false 11 | ) { 12 | val isRunning: Boolean 13 | get() = uid != -1 && Shizuku.pingBinder() 14 | } -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_code_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_outline_arrow_upward_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/jni/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef MISC_H 2 | #define MISC_H 3 | 4 | int copyfile(const char *src_path, const char *dst_path); 5 | uintptr_t memsearch(const uintptr_t start, const uintptr_t end, const void *value, size_t size); 6 | int switch_mnt_ns(int pid); 7 | int get_proc_name(int pid, char *name, size_t _size); 8 | 9 | using foreach_proc_function = void(pid_t); 10 | void foreach_proc(foreach_proc_function *func); 11 | 12 | char *trim(char *str); 13 | 14 | #endif // MISC_H 15 | -------------------------------------------------------------------------------- /server/src/main/java/rikka/shizuku/server/ktx/Handler.kt: -------------------------------------------------------------------------------- 1 | package rikka.shizuku.server.ktx 2 | 3 | import android.os.Handler 4 | import android.os.HandlerThread 5 | import android.os.Looper 6 | 7 | val mainHandler by lazy { 8 | Handler(Looper.getMainLooper()) 9 | } 10 | 11 | private val workerThread by lazy(LazyThreadSafetyMode.NONE) { 12 | HandlerThread("Worker").apply { start() } 13 | } 14 | 15 | val workerHandler by lazy { 16 | Handler(workerThread.looper) 17 | } 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /manager/src/main/assets/rish: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | BASEDIR=$(dirname "$0") 3 | DEX="$BASEDIR"/rish_shizuku.dex 4 | 5 | if [ ! -f "$DEX" ]; then 6 | echo "Cannot find $DEX, please check the tutorial in Shizuku app" 7 | exit 1 8 | fi 9 | 10 | # Replace "PKG" with the application id of your terminal app 11 | [ -z "$RISH_APPLICATION_ID" ] && export RISH_APPLICATION_ID="PKG" 12 | /system/bin/app_process -Djava.class.path="$DEX" /system/bin --nice-name=rish rikka.shizuku.shell.ShizukuShellLoader "$@" 13 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_close_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_numeric_1_circle_outline_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /manager/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @string/dark_theme_off 6 | @string/dark_theme_on 7 | @string/follow_system 8 | 9 | 10 | 11 | 1 12 | 2 13 | -1 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_terminal_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_action_about_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_outline_info_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/legacy/ShellRequestHandlerActivity.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.legacy 2 | 3 | import android.os.Bundle 4 | import android.widget.Toast 5 | import moe.shizuku.manager.app.AppActivity 6 | import moe.shizuku.manager.shell.ShellBinderRequestHandler 7 | 8 | class ShellRequestHandlerActivity : AppActivity() { 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | 13 | ShellBinderRequestHandler.handleRequest(this, intent) 14 | finish() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_outline_open_in_new_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_numeric_2_circle_outline_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/AppConstants.java: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager; 2 | 3 | public class AppConstants { 4 | 5 | public static final String TAG = "ShizukuManager"; 6 | 7 | public static final String NOTIFICATION_CHANNEL_STATUS = "starter"; 8 | public static final String NOTIFICATION_CHANNEL_WORK = "work"; 9 | public static final int NOTIFICATION_ID_STATUS = 1; 10 | public static final int NOTIFICATION_ID_WORK = 2; 11 | 12 | private static final String PACKAGE = "moe.shizuku.manager"; 13 | public static final String EXTRA = PACKAGE + ".extra"; 14 | } 15 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/receiver/ShizukuReceiver.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.receiver 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import moe.shizuku.manager.shell.ShellBinderRequestHandler 7 | 8 | class ShizukuReceiver : BroadcastReceiver() { 9 | 10 | override fun onReceive(context: Context, intent: Intent) { 11 | if ("rikka.shizuku.intent.action.REQUEST_BINDER" == intent.action) { 12 | ShellBinderRequestHandler.handleRequest(context, intent) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_root_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /starter/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | buildFeatures { 7 | buildConfig = false 8 | } 9 | } 10 | 11 | dependencies { 12 | implementation project(':common') 13 | implementation project(':shared') 14 | implementation project(':server-shared') 15 | compileOnly project(':provider') 16 | implementation 'androidx.annotation:annotation:1.3.0' 17 | implementation 'dev.rikka.hidden:compat:3.2.0' 18 | compileOnly 'dev.rikka.hidden:stub:3.2.0' 19 | implementation("dev.rikka.tools.refine:runtime:3.1.1") 20 | } 21 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_baseline_link_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/ktx/String.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.ktx 2 | 3 | import android.text.Spanned 4 | import rikka.html.text.HtmlCompat 5 | 6 | fun CharSequence.toHtml(flags: Int = 0): Spanned { 7 | return HtmlCompat.fromHtml(this.toString(), flags) 8 | } 9 | 10 | fun CharSequence.toHtml(tagHandler: HtmlCompat.TagHandler): Spanned { 11 | return HtmlCompat.fromHtml(this.toString(), null, tagHandler) 12 | } 13 | 14 | fun CharSequence.toHtml(flags: Int, tagHandler: HtmlCompat.TagHandler): Spanned { 15 | return HtmlCompat.fromHtml(this.toString(), flags, null, tagHandler) 16 | } -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/utils/UserHandleCompat.java: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.utils; 2 | 3 | import android.system.Os; 4 | 5 | public class UserHandleCompat { 6 | 7 | private static final int MY_USER_ID = getUserId(Os.getuid()); 8 | 9 | public static final int PER_USER_RANGE = 100000; 10 | 11 | public static int getUserId(int uid) { 12 | return uid / PER_USER_RANGE; 13 | } 14 | 15 | public static int getAppId(int uid) { 16 | return uid % PER_USER_RANGE; 17 | } 18 | 19 | public static int myUserId() { 20 | return MY_USER_ID; 21 | } 22 | } -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/adb/AdbException.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.adb 2 | 3 | @Suppress("NOTHING_TO_INLINE") 4 | inline fun adbError(message: Any): Nothing = throw AdbException(message.toString()) 5 | 6 | open class AdbException : Exception { 7 | 8 | constructor(message: String, cause: Throwable?) : super(message, cause) 9 | constructor(message: String) : super(message) 10 | constructor(cause: Throwable) : super(cause) 11 | constructor() 12 | } 13 | 14 | class AdbInvalidPairingCodeException : AdbException() 15 | 16 | class AdbKeyException(cause: Throwable) : AdbException(cause) 17 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_numeric_3_circle_outline_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_server_ok_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_server_error_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_learn_more_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/values-es/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Inicie conectándose a una computadora 4 | Versión %2$s, %1$s<br>Inicie nuevamente para actualizar a la versión %3$s 5 | Versión %2$s, %1$s 6 | %1$s no se está ejecutando 7 | %1$s se está ejecutando 8 | Nápoles 9 | -------------------------------------------------------------------------------- /server/src/main/java/rikka/shizuku/server/ServerConstants.java: -------------------------------------------------------------------------------- 1 | package rikka.shizuku.server; 2 | 3 | public class ServerConstants { 4 | 5 | public static final int MANAGER_APP_NOT_FOUND = 50; 6 | 7 | public static final int PATCH_VERSION = 13; 8 | 9 | public static final String PERMISSION = "moe.shizuku.manager.permission.API_V23"; 10 | public static final String MANAGER_APPLICATION_ID = "moe.shizuku.privileged.api"; 11 | public static final String REQUEST_PERMISSION_ACTION = MANAGER_APPLICATION_ID + ".intent.action.REQUEST_PERMISSION"; 12 | 13 | public static final int BINDER_TRANSACTION_getApplications = 10001; 14 | } 15 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/grant_permissions_buttons_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/grant_permissions_buttons_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /manager/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/adb/AdbProtocol.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.adb 2 | 3 | object AdbProtocol { 4 | 5 | const val A_SYNC = 0x434e5953 6 | const val A_CNXN = 0x4e584e43 7 | const val A_AUTH = 0x48545541 8 | const val A_OPEN = 0x4e45504f 9 | const val A_OKAY = 0x59414b4f 10 | const val A_CLSE = 0x45534c43 11 | const val A_WRTE = 0x45545257 12 | const val A_STLS = 0x534C5453 13 | 14 | const val A_VERSION = 0x01000000 15 | const val A_MAXDATA = 4096 16 | 17 | const val A_STLS_VERSION = 0x01000000 18 | 19 | const val ADB_AUTH_TOKEN = 1 20 | const val ADB_AUTH_SIGNATURE = 2 21 | const val ADB_AUTH_RSAPUBLICKEY = 3 22 | } -------------------------------------------------------------------------------- /manager/src/main/jni/selinux.h: -------------------------------------------------------------------------------- 1 | #ifndef SELINUX_H 2 | #define SELINUX_H 3 | 4 | namespace se { 5 | void init(); 6 | 7 | using getcon_t = int(char **); 8 | using setcon_t = int(const char *); 9 | using setfilecon_t = int(const char *, const char *); 10 | using selinux_check_access_t = int(const char *, const char *, const char *, const char *, 11 | void *); 12 | using freecon_t = void(char *); 13 | 14 | extern getcon_t *getcon; 15 | extern setcon_t *setcon; 16 | extern setfilecon_t *setfilecon; 17 | extern selinux_check_access_t *selinux_check_access; 18 | extern freecon_t *freecon; 19 | } 20 | 21 | #endif // SELINUX_H 22 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_adb_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_outline_translate_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## For more details on how to configure your build environment visit 2 | # http://www.gradle.org/docs/current/userguide/build_environment.html 3 | # 4 | # Specifies the JVM arguments used for the daemon process. 5 | # The setting is particularly useful for tweaking memory settings. 6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 7 | 8 | # When configured, Gradle will run in incubating parallel mode. 9 | # This option should only be used with decoupled projects. More details, visit 10 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 11 | android.useAndroidX=true 12 | android.enableD8=true 13 | android.enableResourceOptimizations=true 14 | android.enableParallelJsonGen=true 15 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_system_icon.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /manager/src/main/res/drawable/ic_server_restart.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /manager/src/main/res/values/themes_overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 15 | 16 | 27 | 28 | 10 | 11 | 16 | 17 | 21 | 22 | 26 | 27 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/utils/MultiLocaleEntity.java: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.utils; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.util.LinkedHashMap; 6 | import java.util.Locale; 7 | 8 | import moe.shizuku.manager.ShizukuSettings; 9 | 10 | public class MultiLocaleEntity extends LinkedHashMap { 11 | 12 | public abstract static class LocaleProvider { 13 | public abstract Locale get(); 14 | } 15 | 16 | public static final LocaleProvider DEFAULT_LOCAL_PROVIDER = new LocaleProvider() { 17 | @Override 18 | public Locale get() { 19 | return ShizukuSettings.getLocale(); 20 | } 21 | }; 22 | 23 | private static LocaleProvider sLocaleProvider = DEFAULT_LOCAL_PROVIDER; 24 | 25 | public static void setLocaleProvider(@NonNull LocaleProvider localeProvider) { 26 | sLocaleProvider = localeProvider; 27 | } 28 | 29 | public String get() { 30 | return get(sLocaleProvider.get()); 31 | } 32 | 33 | public String get(@NonNull Locale locale) { 34 | if (size() > 0) { 35 | String language = locale.getLanguage(); 36 | String region = locale.getCountry(); 37 | 38 | // fully match 39 | locale = new Locale(language, region); 40 | for (String l : keySet()) { 41 | if (locale.toString().equals(l.replace('-', '_'))) { 42 | return get(l); 43 | } 44 | } 45 | 46 | // match language only keys 47 | locale = new Locale(language); 48 | for (String l : keySet()) { 49 | if (locale.toString().equals(l)) { 50 | return get(l); 51 | } 52 | } 53 | 54 | // match a language_region with only language 55 | for (String l : keySet()) { 56 | if (l.startsWith(locale.toString())) { 57 | return get(l); 58 | } 59 | } 60 | 61 | if (containsKey("en")) { 62 | return get("en"); 63 | } 64 | 65 | if (containsKey("default")) { 66 | return get("default"); 67 | } 68 | 69 | for (String key : keySet()) { 70 | if (!"overwrite_default".equals(key)) 71 | return get(key); 72 | } 73 | } 74 | return null; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /manager/src/main/res/layout/home_start_wireless_adb.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | 23 | 30 | 31 | 32 | 33 | 41 | 42 | 47 | 48 | 53 | 54 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/app/AppActivity.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.app 2 | 3 | import android.content.res.Resources 4 | import android.content.res.Resources.Theme 5 | import android.graphics.Color 6 | import android.os.Build 7 | import androidx.annotation.RequiresApi 8 | import moe.shizuku.manager.R 9 | import rikka.core.res.isNight 10 | import rikka.core.res.resolveColor 11 | import rikka.material.app.MaterialActivity 12 | 13 | abstract class AppActivity : MaterialActivity() { 14 | 15 | override fun computeUserThemeKey(): String { 16 | return ThemeHelper.getTheme(this) + ThemeHelper.isUsingSystemColor() 17 | } 18 | 19 | override fun onApplyUserThemeResource(theme: Theme, isDecorView: Boolean) { 20 | if (ThemeHelper.isUsingSystemColor()) { 21 | if (resources.configuration.isNight()) 22 | theme.applyStyle(R.style.ThemeOverlay_DynamicColors_Dark, true) 23 | else 24 | theme.applyStyle(R.style.ThemeOverlay_DynamicColors_Light, true) 25 | } 26 | 27 | theme.applyStyle(ThemeHelper.getThemeStyleRes(this), true) 28 | } 29 | 30 | @RequiresApi(Build.VERSION_CODES.M) 31 | override fun onApplyTranslucentSystemBars() { 32 | super.onApplyTranslucentSystemBars() 33 | 34 | val window = window 35 | val theme = theme 36 | 37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 38 | window?.decorView?.post { 39 | if (window.decorView.rootWindowInsets?.systemWindowInsetBottom ?: 0 >= Resources.getSystem().displayMetrics.density * 40) { 40 | window.navigationBarColor = 41 | theme.resolveColor(android.R.attr.navigationBarColor) and 0x00ffffff or -0x20000000 42 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 43 | window.isNavigationBarContrastEnforced = false 44 | } 45 | } else { 46 | window.navigationBarColor = Color.TRANSPARENT 47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 48 | window.isNavigationBarContrastEnforced = true 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | override fun onSupportNavigateUp(): Boolean { 56 | if (!super.onSupportNavigateUp()) { 57 | finish() 58 | } 59 | return true 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /manager/src/main/res/values-es-rCL/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Iniciar desde depuración inalámbrica 4 | Enviar 5 | Copiar 6 | <font face=monospace>%1$s</font><br><br>* Esto tiene otras consideraciones, por favor confirme que ha leído la información de ayuda primero. 7 | Ver ayuda 8 | Ver comando 9 | Para dispositivos sin root, usted necesita ADB para ejecutar Shizuku (requiere una conexión a un ordenador). Este proceso se debe repetir cada vez que el dispositivo sea reiniciando. <b><a href=\"%1$s\">obtener más ayuda</a></b>. 10 | Versión %2$s, %1$s 11 | %1$s no está activo 12 | %1$s está activo 13 | Abrir Shizuku 14 | Acerca de 15 | Opciones de desarrollador 16 | El sistema requiere que el cuadro de diálogo de emparejamiento esté siempre visible, el uso del modo de pantalla dividida es la única forma de permitir que esta aplicación y el cuadro de diálogo del sistema estén visibles al mismo tiempo. 17 | Ingrese primero al modo de pantalla dividida (ventanas múltiples). 18 | El puerto es un número entero comprendido entre 1 y 65535. 19 | Puerto 20 | Buscando servicio de depuración inalámbrica 21 | Empiece por conectarse a su computador 22 | —Peter Cuevas 23 | Versión %2$s, %1$s<br>Reinicie para actualizar a la versión %3$s 24 | 25 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/home/ManageAppsViewHolder.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.home 2 | 3 | import android.content.Intent 4 | import android.text.method.LinkMovementMethod 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import moe.shizuku.manager.Helps 9 | import moe.shizuku.manager.R 10 | import moe.shizuku.manager.databinding.HomeItemContainerBinding 11 | import moe.shizuku.manager.databinding.HomeManageAppsItemBinding 12 | import moe.shizuku.manager.ktx.toHtml 13 | import moe.shizuku.manager.management.ApplicationManagementActivity 14 | import moe.shizuku.manager.model.ServiceStatus 15 | import rikka.html.text.HtmlCompat 16 | import rikka.recyclerview.BaseViewHolder 17 | import rikka.recyclerview.BaseViewHolder.Creator 18 | 19 | class ManageAppsViewHolder(private val binding: HomeManageAppsItemBinding, root: View) : 20 | BaseViewHolder>(root), View.OnClickListener { 21 | 22 | companion object { 23 | val CREATOR = Creator> { inflater: LayoutInflater, parent: ViewGroup? -> 24 | val outer = HomeItemContainerBinding.inflate(inflater, parent, false) 25 | val inner = HomeManageAppsItemBinding.inflate(inflater, outer.root, true) 26 | ManageAppsViewHolder(inner, outer.root) 27 | } 28 | } 29 | 30 | init { 31 | root.setOnClickListener(this) 32 | } 33 | 34 | private inline val title get() = binding.text1 35 | private inline val summary get() = binding.text2 36 | 37 | override fun onBind() { 38 | val context = itemView.context 39 | if (!data.first.isRunning) { 40 | itemView.isEnabled = false 41 | title.setText(R.string.home_app_management_title) 42 | summary.text = context.getString( 43 | R.string.home_status_service_not_running, 44 | context.getString(R.string.app_name) 45 | ) 46 | } else { 47 | itemView.isEnabled = true 48 | title.text = context.resources.getQuantityString( 49 | R.plurals.home_app_management_authorized_apps_count, 50 | data.second, 51 | data.second 52 | ) 53 | summary.text = context.getString(R.string.home_app_management_view_authorized_apps) 54 | } 55 | } 56 | 57 | override fun onClick(v: View) { 58 | v.context.startActivity(Intent(v.context, ApplicationManagementActivity::class.java)) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/home/HomeViewModel.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.home 2 | 3 | import android.content.pm.PackageManager 4 | import androidx.lifecycle.LiveData 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import kotlinx.coroutines.CancellationException 9 | import kotlinx.coroutines.Dispatchers 10 | import kotlinx.coroutines.launch 11 | import moe.shizuku.manager.BuildConfig 12 | import moe.shizuku.manager.Manifest 13 | import moe.shizuku.manager.model.ServiceStatus 14 | import moe.shizuku.manager.utils.Logger.LOGGER 15 | import moe.shizuku.manager.utils.ShizukuSystemApis 16 | import rikka.lifecycle.Resource 17 | import rikka.shizuku.Shizuku 18 | 19 | class HomeViewModel : ViewModel() { 20 | 21 | private val _serviceStatus = MutableLiveData>() 22 | val serviceStatus = _serviceStatus as LiveData> 23 | 24 | private fun load(): ServiceStatus { 25 | if (!Shizuku.pingBinder()) { 26 | return ServiceStatus() 27 | } 28 | 29 | val uid = Shizuku.getUid() 30 | val apiVersion = Shizuku.getVersion() 31 | val patchVersion = Shizuku.getServerPatchVersion().let { if (it < 0) 0 else it } 32 | val seContext = if (apiVersion >= 6) { 33 | try { 34 | Shizuku.getSELinuxContext() 35 | } catch (tr: Throwable) { 36 | LOGGER.w(tr, "getSELinuxContext") 37 | null 38 | } 39 | } else null 40 | val permissionTest = 41 | Shizuku.checkRemotePermission("android.permission.GRANT_RUNTIME_PERMISSIONS") == PackageManager.PERMISSION_GRANTED || uid == 1000 42 | 43 | // Before a526d6bb, server will not exit on uninstall, manager installed later will get not permission 44 | // Run a random remote transaction here, report no permission as not running 45 | ShizukuSystemApis.checkPermission(Manifest.permission.API_V23, BuildConfig.APPLICATION_ID, 0) 46 | return ServiceStatus(uid, apiVersion, patchVersion, seContext, permissionTest) 47 | } 48 | 49 | fun reload() { 50 | viewModelScope.launch(Dispatchers.IO) { 51 | try { 52 | val status = load() 53 | _serviceStatus.postValue(Resource.success(status)) 54 | } catch (e: CancellationException) { 55 | 56 | } catch (e: Throwable) { 57 | _serviceStatus.postValue(Resource.error(e, ServiceStatus())) 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /manager/src/main/res/layout/home_extra_step_required.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 23 | 24 | 30 | 31 | 39 | 40 | 41 | 42 | 43 | 44 | 53 | 54 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /manager/src/main/res/values-ar/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | الإصدار %2$s, %1$s 4 | %1$s ليس قيد التشغيل 5 | %1$s قيد التشغيل 6 | البدء في الإتصال بالكمبيوتر 7 | قراءة التعليمات 8 | عرض الأمر 9 | نسخ 10 | إرسال 11 | الإصدار %2$s, %1$s<br>البدء من جديد للتحديث إلى الإصدار %3$s 12 | للأجهزة التي ليس بها روت ، تحتاج إلى استخدام ADB لبدء شيزوكو (يتطلب اتصال الكمبيوتر). وتحتاج هذه العملية لتكرارها في كل مرة يتم إعادة تشغيل الجهاز. يرجى <ب> <a href=\"٪1$s\"> قراءة المساعدة </a> </ B>. 13 | يرجى تمكين \"التصحيح اللاسلكي\" في \"خيارات المطور\". \"تصحيح لاسلكي\" يتم تعطيلها عندما تتغير الشبكة تلقائيا. 14 | \n 15 | \n ملاحظة، لا تعطل \"خيارات المطور\" أو \"تصحيح USB\"، أو سيتم إيقاف شيزوكو 16 | المنفذ 17 | الاقتران 18 | font face=monospace>%1$s</font><br><br>* هناك بعض الاعتبارات الأخرى، يرجى تأكيد أنك قرأت التعليمات أولا. 19 | البدء باستخدام التصحيح اللاسلكي 20 | على أندرويد ١١ وما فوق ، يمكنك تفعيل التصحيح اللاسلكي وبدء شيزوكو مباشرة من جهازك ، بدون الاتصال بالكمبيوتر.<p>يرجى الاطلاع على الدليل المفصل خطوة بخطوة أولاً. 21 | البحث عن خدمة التصحيح اللاسلكي 22 | المنفذ هو عدد صحيح يتراوح من ١ إلى ٦٥٥٣٥. 23 | ‌دليل خطوة بخطوة 24 | إقران مع الجهاز 25 | على الأجهزة الأقدم من أندرويد ١١ ، يلزم الاتصال بجهاز كمبيوتر لتمكين تصحيح الأخطاء اللاسلكي. 26 | جاري البحث على جهاز للإتصال 27 | ‮المشاركين في الترجمة 28 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/ktx/RecyclerView.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.ktx 2 | 3 | import android.graphics.Canvas 4 | import android.widget.EdgeEffect 5 | import androidx.recyclerview.widget.RecyclerView 6 | 7 | class FixedAlwaysClipToPaddingEdgeEffectFactory( 8 | private val paddingLeft: Int, 9 | private val paddingTop: Int, 10 | private val paddingRight: Int, 11 | private val paddingBottom: Int 12 | ) : RecyclerView.EdgeEffectFactory() { 13 | 14 | 15 | override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect { 16 | 17 | return object : EdgeEffect(view.context) { 18 | private var ensureSize = false 19 | 20 | private fun ensureSize() { 21 | if (ensureSize) return 22 | ensureSize = true 23 | 24 | when (direction) { 25 | DIRECTION_LEFT -> { 26 | setSize(view.measuredHeight - paddingTop - paddingBottom, 27 | view.measuredWidth - paddingLeft - paddingRight) 28 | } 29 | DIRECTION_TOP -> { 30 | setSize(view.measuredWidth - paddingLeft - paddingRight, 31 | view.measuredHeight - paddingTop - paddingBottom) 32 | } 33 | DIRECTION_RIGHT -> { 34 | setSize(view.measuredHeight - paddingTop - paddingBottom, 35 | view.measuredWidth - paddingLeft - paddingRight) 36 | } 37 | DIRECTION_BOTTOM -> { 38 | setSize(view.measuredWidth - paddingLeft - paddingRight, 39 | view.measuredHeight - paddingTop - paddingBottom) 40 | } 41 | } 42 | } 43 | 44 | override fun draw(c: Canvas): Boolean { 45 | ensureSize() 46 | 47 | val restore = c.save() 48 | when (direction) { 49 | DIRECTION_LEFT -> { 50 | c.translate(paddingBottom.toFloat(), 0f) 51 | } 52 | DIRECTION_TOP -> { 53 | c.translate(paddingLeft.toFloat(), paddingTop.toFloat()) 54 | } 55 | DIRECTION_RIGHT -> { 56 | c.translate(-paddingTop.toFloat(), 0f) 57 | } 58 | DIRECTION_BOTTOM -> { 59 | c.translate(paddingRight.toFloat(), paddingBottom.toFloat()) 60 | } 61 | } 62 | val res = super.draw(c) 63 | c.restoreToCount(restore) 64 | return res 65 | } 66 | } 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/Helps.java: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager; 2 | 3 | import moe.shizuku.manager.utils.MultiLocaleEntity; 4 | 5 | public class Helps { 6 | 7 | public static final MultiLocaleEntity ADB = new MultiLocaleEntity(); 8 | public static final MultiLocaleEntity ADB_ANDROID11 = new MultiLocaleEntity(); 9 | public static final MultiLocaleEntity APPS = new MultiLocaleEntity(); 10 | public static final MultiLocaleEntity HOME = new MultiLocaleEntity(); 11 | public static final MultiLocaleEntity DOWNLOAD = new MultiLocaleEntity(); 12 | public static final MultiLocaleEntity SUI = new MultiLocaleEntity(); 13 | public static final MultiLocaleEntity RISH = new MultiLocaleEntity(); 14 | public static final MultiLocaleEntity ADB_PERMISSION = new MultiLocaleEntity(); 15 | 16 | static { 17 | ADB.put("zh-CN", "https://shizuku.rikka.app/zh-hans/guide/setup/"); 18 | ADB.put("zh-TW", "https://shizuku.rikka.app/zh-hant/guide/setup/"); 19 | ADB.put("en", "https://shizuku.rikka.app/guide/setup/"); 20 | 21 | ADB_ANDROID11.put("zh-CN", "https://shizuku.rikka.app/zh-hans/guide/setup/"); 22 | ADB_ANDROID11.put("zh-TW", "https://shizuku.rikka.app/zh-hant/guide/setup/"); 23 | ADB_ANDROID11.put("en", "https://shizuku.rikka.app/guide/setup/"); 24 | 25 | APPS.put("zh-CN", "https://shizuku.rikka.app/zh-hans/apps/"); 26 | APPS.put("zh-TW", "https://shizuku.rikka.app/zh-hant/apps/"); 27 | APPS.put("en", "https://shizuku.rikka.app/apps/"); 28 | 29 | HOME.put("zh-CN", "https://shizuku.rikka.app/zh-hans/"); 30 | HOME.put("zh-TW", "https://shizuku.rikka.app/zh-hant/"); 31 | HOME.put("en", "https://shizuku.rikka.app/"); 32 | 33 | DOWNLOAD.put("zh-CN", "https://shizuku.rikka.app/zh-hans/download/"); 34 | DOWNLOAD.put("zh-TW", "https://shizuku.rikka.app/zh-hant/download/"); 35 | DOWNLOAD.put("en", "https://shizuku.rikka.app/download/"); 36 | 37 | ADB_PERMISSION.put("zh-CN", "https://shizuku.rikka.app/zh-hans/guide/setup/#%E9%80%9A%E8%BF%87%E6%97%A0%E7%BA%BF%E8%B0%83%E8%AF%95%E5%90%AF%E5%8A%A8-%E9%80%9A%E8%BF%87%E8%BF%9E%E6%8E%A5%E7%94%B5%E8%84%91%E5%90%AF%E5%8A%A8-adb-%E6%9D%83%E9%99%90%E5%8F%97%E9%99%90"); 38 | ADB_PERMISSION.put("zh-TW", "https://shizuku.rikka.app/zh-hant/guide/setup/#%E9%80%8F%E9%81%8E%E7%84%A1%E7%B7%9A%E9%99%A4%E9%8C%AF%E5%95%9F%E5%8B%95-%E9%80%8F%E9%81%8E%E9%80%A3%E7%B7%9A%E9%9B%BB%E8%85%A6%E5%95%9F%E5%8B%95-adb-%E6%AC%8A%E9%99%90%E5%8F%97%E9%99%90"); 39 | ADB_PERMISSION.put("en", "https://shizuku.rikka.app/guide/setup/#start-via-wireless-debugging-start-by-connecting-to-a-computer-the-permission-of-adb-is-limited"); 40 | 41 | SUI.put("en", "https://github.com/RikkaApps/Sui"); 42 | 43 | RISH.put("en", "https://github.com/RikkaApps/Shizuku-API/tree/master/rish"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/home/HomeAdapter.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.home 2 | 3 | import android.os.Build 4 | import moe.shizuku.manager.management.AppsViewModel 5 | import moe.shizuku.manager.utils.EnvironmentUtils 6 | import moe.shizuku.manager.utils.UserHandleCompat 7 | import rikka.recyclerview.IdBasedRecyclerViewAdapter 8 | import rikka.recyclerview.IndexCreatorPool 9 | import rikka.shizuku.Shizuku 10 | 11 | class HomeAdapter(private val homeModel: HomeViewModel, private val appsModel: AppsViewModel) : 12 | IdBasedRecyclerViewAdapter(ArrayList()) { 13 | 14 | init { 15 | updateData() 16 | setHasStableIds(true) 17 | } 18 | 19 | companion object { 20 | 21 | private const val ID_STATUS = 0L 22 | private const val ID_APPS = 1L 23 | private const val ID_TERMINAL = 2L 24 | private const val ID_START_ROOT = 3L 25 | private const val ID_START_WADB = 4L 26 | private const val ID_START_ADB = 5L 27 | private const val ID_LEARN_MORE = 6L 28 | private const val ID_ADB_PERMISSION_LIMITED = 7L 29 | } 30 | 31 | override fun onCreateCreatorPool(): IndexCreatorPool { 32 | return IndexCreatorPool() 33 | } 34 | 35 | fun updateData() { 36 | val status = homeModel.serviceStatus.value?.data ?: return 37 | val grantedCount = appsModel.grantedCount.value?.data ?: 0 38 | val adbPermission = status.permission 39 | val running = status.isRunning 40 | val isPrimaryUser = UserHandleCompat.myUserId() == 0 41 | 42 | clear() 43 | addItem(ServerStatusViewHolder.CREATOR, status, ID_STATUS) 44 | 45 | if (adbPermission) { 46 | addItem(ManageAppsViewHolder.CREATOR, status to grantedCount, ID_APPS) 47 | addItem(TerminalViewHolder.CREATOR, status, ID_TERMINAL) 48 | } 49 | 50 | if (running && !adbPermission) { 51 | addItem(AdbPermissionLimitedViewHolder.CREATOR, status, ID_ADB_PERMISSION_LIMITED) 52 | } 53 | 54 | if (isPrimaryUser) { 55 | val root = EnvironmentUtils.isRooted() 56 | val rootRestart = running && status.uid == 0 57 | 58 | if (root) { 59 | addItem(StartRootViewHolder.CREATOR, rootRestart, ID_START_ROOT) 60 | } 61 | 62 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || EnvironmentUtils.getAdbTcpPort() > 0) { 63 | addItem(StartWirelessAdbViewHolder.CREATOR, null, ID_START_WADB) 64 | } 65 | 66 | addItem(StartAdbViewHolder.CREATOR, null, ID_START_ADB) 67 | 68 | if (!root) { 69 | addItem(StartRootViewHolder.CREATOR, rootRestart, ID_START_ROOT) 70 | } 71 | } 72 | addItem(LearnMoreViewHolder.CREATOR, null, ID_LEARN_MORE) 73 | notifyDataSetChanged() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /manager/src/main/res/layout/app_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 22 | 23 | 30 | 31 | 37 | 38 | 47 | 48 | 53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/management/ApplicationManagementActivity.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.management 2 | 3 | import android.os.Bundle 4 | import android.util.TypedValue 5 | import android.view.MenuItem 6 | import android.widget.Toast 7 | import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver 8 | import moe.shizuku.manager.Helps 9 | import moe.shizuku.manager.R 10 | import moe.shizuku.manager.app.AppBarActivity 11 | import moe.shizuku.manager.databinding.AppsActivityBinding 12 | import moe.shizuku.manager.utils.CustomTabsHelper 13 | import rikka.lifecycle.Status 14 | import rikka.recyclerview.addEdgeSpacing 15 | import rikka.recyclerview.fixEdgeEffect 16 | import rikka.shizuku.Shizuku 17 | import java.util.* 18 | 19 | class ApplicationManagementActivity : AppBarActivity() { 20 | 21 | private val viewModel by appsViewModel() 22 | private val adapter = AppsAdapter() 23 | 24 | private val binderDeadListener = Shizuku.OnBinderDeadListener { 25 | if (!isFinishing) { 26 | finish() 27 | } 28 | } 29 | 30 | override fun onCreate(savedInstanceState: Bundle?) { 31 | super.onCreate(savedInstanceState) 32 | 33 | if (!Shizuku.pingBinder()) { 34 | finish() 35 | return 36 | } 37 | 38 | val binding = AppsActivityBinding.inflate(layoutInflater) 39 | setContentView(binding.root) 40 | 41 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 42 | 43 | viewModel.packages.observe(this) { 44 | when (it.status) { 45 | Status.SUCCESS -> { 46 | adapter.updateData(it.data) 47 | } 48 | Status.ERROR -> { 49 | finish() 50 | val tr = it.error 51 | Toast.makeText(this, Objects.toString(tr, "unknown"), Toast.LENGTH_SHORT).show() 52 | tr.printStackTrace() 53 | } 54 | Status.LOADING -> { 55 | 56 | } 57 | } 58 | } 59 | if (viewModel.packages.value == null) { 60 | viewModel.load() 61 | } 62 | 63 | val recyclerView = binding.list 64 | recyclerView.adapter = adapter 65 | recyclerView.fixEdgeEffect() 66 | recyclerView.addEdgeSpacing(top = 8f, bottom = 8f, unit = TypedValue.COMPLEX_UNIT_DIP) 67 | 68 | adapter.registerAdapterDataObserver(object : AdapterDataObserver() { 69 | override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) { 70 | viewModel.loadCount() 71 | } 72 | }) 73 | 74 | Shizuku.addBinderDeadListener(binderDeadListener) 75 | } 76 | 77 | override fun onDestroy() { 78 | super.onDestroy() 79 | 80 | Shizuku.removeBinderDeadListener(binderDeadListener) 81 | } 82 | 83 | override fun onResume() { 84 | super.onResume() 85 | adapter.notifyDataSetChanged() 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/ShizukuManagerProvider.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager 2 | 3 | import android.os.Bundle 4 | import androidx.core.os.bundleOf 5 | import moe.shizuku.api.BinderContainer 6 | import moe.shizuku.manager.utils.Logger.LOGGER 7 | import rikka.shizuku.Shizuku 8 | import rikka.shizuku.ShizukuApiConstants.USER_SERVICE_ARG_TOKEN 9 | import rikka.shizuku.ShizukuProvider 10 | import java.util.concurrent.CountDownLatch 11 | import java.util.concurrent.TimeUnit 12 | import java.util.concurrent.TimeoutException 13 | 14 | class ShizukuManagerProvider : ShizukuProvider() { 15 | 16 | companion object { 17 | private const val EXTRA_BINDER = "moe.shizuku.privileged.api.intent.extra.BINDER" 18 | private const val METHOD_SEND_USER_SERVICE = "sendUserService" 19 | } 20 | 21 | override fun onCreate(): Boolean { 22 | disableAutomaticSuiInitialization() 23 | return super.onCreate() 24 | } 25 | 26 | override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { 27 | if (extras == null) return null 28 | 29 | return if (method == METHOD_SEND_USER_SERVICE) { 30 | try { 31 | extras.classLoader = BinderContainer::class.java.classLoader 32 | 33 | val token = extras.getString(USER_SERVICE_ARG_TOKEN) ?: return null 34 | val binder = extras.getParcelable(EXTRA_BINDER)?.binder ?: return null 35 | 36 | val countDownLatch = CountDownLatch(1) 37 | var reply: Bundle? = Bundle() 38 | 39 | val listener = object : Shizuku.OnBinderReceivedListener { 40 | 41 | override fun onBinderReceived() { 42 | try { 43 | Shizuku.attachUserService(binder, bundleOf( 44 | USER_SERVICE_ARG_TOKEN to token 45 | )) 46 | reply!!.putParcelable(EXTRA_BINDER, BinderContainer(Shizuku.getBinder())) 47 | } catch (e: Throwable) { 48 | LOGGER.e(e, "attachUserService $token") 49 | reply = null 50 | } 51 | 52 | Shizuku.removeBinderReceivedListener(this) 53 | 54 | countDownLatch.countDown() 55 | } 56 | } 57 | 58 | Shizuku.addBinderReceivedListenerSticky(listener) 59 | 60 | return try { 61 | countDownLatch.await(5, TimeUnit.SECONDS) 62 | reply 63 | } catch (e: TimeoutException) { 64 | LOGGER.e(e, "Binder not received in 5s") 65 | null 66 | } 67 | } catch (e: Throwable) { 68 | LOGGER.e(e, "sendUserService") 69 | null 70 | } 71 | } else { 72 | super.call(method, arg, extras) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/management/AppsViewModel.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.management 2 | 3 | import android.content.Context 4 | import android.content.pm.PackageInfo 5 | import androidx.activity.ComponentActivity 6 | import androidx.annotation.MainThread 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.LiveData 9 | import androidx.lifecycle.MutableLiveData 10 | import androidx.lifecycle.ViewModel 11 | import androidx.lifecycle.viewModelScope 12 | import kotlinx.coroutines.CancellationException 13 | import kotlinx.coroutines.Dispatchers 14 | import kotlinx.coroutines.launch 15 | import moe.shizuku.manager.authorization.AuthorizationManager 16 | import rikka.lifecycle.Resource 17 | import rikka.lifecycle.activitySharedViewModels 18 | import rikka.lifecycle.sharedViewModels 19 | import java.util.* 20 | 21 | @MainThread 22 | fun ComponentActivity.appsViewModel() = sharedViewModels { AppsViewModel(this) } 23 | 24 | @MainThread 25 | fun Fragment.appsViewModel() = activitySharedViewModels { AppsViewModel(requireContext()) } 26 | 27 | class AppsViewModel(context: Context) : ViewModel() { 28 | 29 | private val _packages = MutableLiveData>>() 30 | val packages = _packages as LiveData>> 31 | 32 | private val _grantedCount = MutableLiveData>() 33 | val grantedCount = _grantedCount as LiveData> 34 | 35 | fun load() { 36 | viewModelScope.launch(Dispatchers.IO) { 37 | try { 38 | val list: MutableList = ArrayList() 39 | var count = 0 40 | for (pi in AuthorizationManager.getPackages()) { 41 | list.add(pi) 42 | if (AuthorizationManager.granted(pi.packageName, pi.applicationInfo.uid)) count++ 43 | } 44 | _packages.postValue(Resource.success(list)) 45 | _grantedCount.postValue(Resource.success(count)) 46 | } catch (e: CancellationException) { 47 | 48 | } catch (e: Throwable) { 49 | _packages.postValue(Resource.error(e, null)) 50 | _grantedCount.postValue(Resource.error(e, 0)) 51 | } 52 | } 53 | } 54 | 55 | fun loadCount() { 56 | viewModelScope.launch(Dispatchers.IO) { 57 | try { 58 | val list: MutableList = ArrayList() 59 | val packages: MutableList = ArrayList() 60 | for (pi in AuthorizationManager.getPackages()) { 61 | list.add(pi) 62 | if (AuthorizationManager.granted( 63 | pi.packageName, 64 | pi.applicationInfo.uid 65 | ) 66 | ) packages.add(pi.packageName) 67 | } 68 | } catch (e: CancellationException) { 69 | 70 | } catch (e: Throwable) { 71 | _packages.postValue(Resource.error(e, null)) 72 | _grantedCount.postValue(Resource.error(e, 0)) 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/utils/EmptySharedPreferencesImpl.java: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.utils; 2 | 3 | import android.content.SharedPreferences; 4 | 5 | import androidx.annotation.Nullable; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | public class EmptySharedPreferencesImpl implements SharedPreferences { 12 | 13 | @Override 14 | public Map getAll() { 15 | return new HashMap<>(); 16 | } 17 | 18 | @Nullable 19 | @Override 20 | public String getString(String key, @Nullable String defValue) { 21 | return defValue; 22 | } 23 | 24 | @Nullable 25 | @Override 26 | public Set getStringSet(String key, @Nullable Set defValues) { 27 | return defValues; 28 | } 29 | 30 | @Override 31 | public int getInt(String key, int defValue) { 32 | return defValue; 33 | } 34 | 35 | @Override 36 | public long getLong(String key, long defValue) { 37 | return defValue; 38 | } 39 | 40 | @Override 41 | public float getFloat(String key, float defValue) { 42 | return defValue; 43 | } 44 | 45 | @Override 46 | public boolean getBoolean(String key, boolean defValue) { 47 | return defValue; 48 | } 49 | 50 | @Override 51 | public boolean contains(String key) { 52 | return false; 53 | } 54 | 55 | @Override 56 | public Editor edit() { 57 | return new EditorImpl(); 58 | } 59 | 60 | @Override 61 | public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 62 | 63 | } 64 | 65 | @Override 66 | public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 67 | 68 | } 69 | 70 | private static class EditorImpl implements Editor { 71 | 72 | @Override 73 | public Editor putString(String key, @Nullable String value) { 74 | return this; 75 | } 76 | 77 | @Override 78 | public Editor putStringSet(String key, @Nullable Set values) { 79 | return this; 80 | } 81 | 82 | @Override 83 | public Editor putInt(String key, int value) { 84 | return this; 85 | } 86 | 87 | @Override 88 | public Editor putLong(String key, long value) { 89 | return this; 90 | } 91 | 92 | @Override 93 | public Editor putFloat(String key, float value) { 94 | return this; 95 | } 96 | 97 | @Override 98 | public Editor putBoolean(String key, boolean value) { 99 | return this; 100 | } 101 | 102 | @Override 103 | public Editor remove(String key) { 104 | return this; 105 | } 106 | 107 | @Override 108 | public Editor clear() { 109 | return this; 110 | } 111 | 112 | @Override 113 | public boolean commit() { 114 | return true; 115 | } 116 | 117 | @Override 118 | public void apply() { 119 | 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/home/StartRootViewHolder.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.home 2 | 3 | import android.content.Intent 4 | import android.text.method.LinkMovementMethod 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.appcompat.app.AlertDialog 9 | import moe.shizuku.manager.Helps 10 | import moe.shizuku.manager.R 11 | import moe.shizuku.manager.databinding.HomeItemContainerBinding 12 | import moe.shizuku.manager.databinding.HomeStartRootBinding 13 | import moe.shizuku.manager.ktx.toHtml 14 | import moe.shizuku.manager.starter.StarterActivity 15 | import rikka.html.text.HtmlCompat 16 | import rikka.recyclerview.BaseViewHolder 17 | import rikka.recyclerview.BaseViewHolder.Creator 18 | import rikka.shizuku.Shizuku 19 | 20 | class StartRootViewHolder(private val binding: HomeStartRootBinding, root: View) : 21 | BaseViewHolder(root) { 22 | 23 | companion object { 24 | val CREATOR = Creator { inflater: LayoutInflater, parent: ViewGroup? -> 25 | val outer = HomeItemContainerBinding.inflate(inflater, parent, false) 26 | val inner = HomeStartRootBinding.inflate(inflater, outer.root, true) 27 | StartRootViewHolder(inner, outer.root) 28 | } 29 | } 30 | 31 | private inline val start get() = binding.button1 32 | private inline val restart get() = binding.button2 33 | 34 | private var alertDialog: AlertDialog? = null 35 | 36 | init { 37 | val listener = View.OnClickListener { v: View -> onStartClicked(v) } 38 | start.setOnClickListener(listener) 39 | restart.setOnClickListener(listener) 40 | binding.text1.movementMethod = LinkMovementMethod.getInstance() 41 | } 42 | 43 | private fun onStartClicked(v: View) { 44 | val context = v.context 45 | val intent = Intent(context, StarterActivity::class.java).apply { 46 | putExtra(StarterActivity.EXTRA_IS_ROOT, true) 47 | } 48 | context.startActivity(intent) 49 | } 50 | 51 | override fun onBind() { 52 | start.isEnabled = true 53 | restart.isEnabled = true 54 | if (data!!) { 55 | start.visibility = View.GONE 56 | restart.visibility = View.VISIBLE 57 | } else { 58 | start.visibility = View.VISIBLE 59 | restart.visibility = View.GONE 60 | } 61 | 62 | val sb = StringBuilder() 63 | .append( 64 | context.getString( 65 | R.string.home_root_description, 66 | "Don\'t kill my app!" 67 | ) 68 | ) 69 | if (Shizuku.pingBinder()) { 70 | sb.append("

").append( 71 | context.getString( 72 | R.string.home_root_description_sui, 73 | "Sui", 74 | "Sui" 75 | ) 76 | ) 77 | } 78 | 79 | binding.text1.text = sb.toHtml(HtmlCompat.FROM_HTML_OPTION_TRIM_WHITESPACE) 80 | } 81 | 82 | override fun onRecycle() { 83 | super.onRecycle() 84 | alertDialog = null 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /manager/src/main/java/moe/shizuku/manager/home/StartAdbViewHolder.kt: -------------------------------------------------------------------------------- 1 | package moe.shizuku.manager.home 2 | 3 | import android.content.Intent 4 | import android.text.method.LinkMovementMethod 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.Toast 9 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 10 | import moe.shizuku.manager.Helps 11 | import moe.shizuku.manager.R 12 | import moe.shizuku.manager.databinding.HomeItemContainerBinding 13 | import moe.shizuku.manager.databinding.HomeStartAdbBinding 14 | import moe.shizuku.manager.ktx.toHtml 15 | import moe.shizuku.manager.starter.Starter 16 | import rikka.core.util.ClipboardUtils 17 | import rikka.html.text.HtmlCompat 18 | import rikka.recyclerview.BaseViewHolder 19 | import rikka.recyclerview.BaseViewHolder.Creator 20 | 21 | class StartAdbViewHolder(binding: HomeStartAdbBinding, root: View) : BaseViewHolder(root) { 22 | 23 | companion object { 24 | val CREATOR = Creator { inflater: LayoutInflater, parent: ViewGroup? -> 25 | val outer = HomeItemContainerBinding.inflate(inflater, parent, false) 26 | val inner = HomeStartAdbBinding.inflate(inflater, outer.root, true) 27 | StartAdbViewHolder(inner, outer.root) 28 | } 29 | } 30 | 31 | init { 32 | binding.button1.setOnClickListener { v: View -> 33 | val context = v.context 34 | MaterialAlertDialogBuilder(context) 35 | .setTitle(R.string.home_adb_button_view_command) 36 | .setMessage( 37 | HtmlCompat.fromHtml( 38 | context.getString( 39 | R.string.home_adb_dialog_view_command_message, 40 | Starter.adbCommand 41 | ) 42 | ) 43 | ) 44 | .setPositiveButton(R.string.home_adb_dialog_view_command_copy_button) { _, _ -> 45 | if (ClipboardUtils.put(context, Starter.adbCommand)) { 46 | Toast.makeText( 47 | context, 48 | context.getString(R.string.toast_copied_to_clipboard, Starter.adbCommand), 49 | Toast.LENGTH_SHORT 50 | ).show() 51 | } 52 | } 53 | .setNegativeButton(android.R.string.cancel, null) 54 | .setNeutralButton(R.string.home_adb_dialog_view_command_button_send) { _, _ -> 55 | var intent = Intent(Intent.ACTION_SEND) 56 | intent.type = "text/plain" 57 | intent.putExtra(Intent.EXTRA_TEXT, Starter.adbCommand) 58 | intent = Intent.createChooser( 59 | intent, 60 | context.getString(R.string.home_adb_dialog_view_command_button_send) 61 | ) 62 | context.startActivity(intent) 63 | } 64 | .show() 65 | } 66 | binding.text1.movementMethod = LinkMovementMethod.getInstance() 67 | binding.text1.text = context.getString(R.string.home_adb_description, Helps.ADB.get()) 68 | .toHtml(HtmlCompat.FROM_HTML_OPTION_TRIM_WHITESPACE) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /manager/src/main/jni/selinux.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "selinux.h" 9 | 10 | namespace se { 11 | 12 | static int __getcon(char **context) { 13 | int fd = open("/proc/self/attr/current", O_RDONLY | O_CLOEXEC); 14 | if (fd < 0) 15 | return fd; 16 | 17 | char *buf; 18 | size_t size; 19 | int errno_hold; 20 | ssize_t ret; 21 | 22 | size = sysconf(_SC_PAGE_SIZE); 23 | buf = (char *) malloc(size); 24 | if (!buf) { 25 | ret = -1; 26 | goto out; 27 | } 28 | memset(buf, 0, size); 29 | 30 | do { 31 | ret = read(fd, buf, size - 1); 32 | } while (ret < 0 && errno == EINTR); 33 | if (ret < 0) 34 | goto out2; 35 | 36 | if (ret == 0) { 37 | *context = nullptr; 38 | goto out2; 39 | } 40 | 41 | *context = strdup(buf); 42 | if (!(*context)) { 43 | ret = -1; 44 | goto out2; 45 | } 46 | ret = 0; 47 | out2: 48 | free(buf); 49 | out: 50 | errno_hold = errno; 51 | close(fd); 52 | errno = errno_hold; 53 | return 0; 54 | } 55 | 56 | static int __setcon(const char *ctx) { 57 | int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC); 58 | if (fd < 0) 59 | return fd; 60 | size_t len = strlen(ctx) + 1; 61 | ssize_t rc = write(fd, ctx, len); 62 | close(fd); 63 | return rc != len; 64 | } 65 | 66 | static int __setfilecon(const char *path, const char *ctx) { 67 | int rc = syscall(__NR_setxattr, path, "security.selinux"/*XATTR_NAME_SELINUX*/, ctx, 68 | strlen(ctx) + 1, 0); 69 | if (rc) { 70 | errno = -rc; 71 | return -1; 72 | } 73 | return 0; 74 | } 75 | 76 | static int __selinux_check_access(const char *scon, const char *tcon, 77 | const char *tclass, const char *perm, void *auditdata) { 78 | return 0; 79 | } 80 | 81 | static void __freecon(char *con) { 82 | free(con); 83 | } 84 | 85 | getcon_t *getcon = __getcon; 86 | setcon_t *setcon = __setcon; 87 | setfilecon_t *setfilecon = __setfilecon; 88 | selinux_check_access_t *selinux_check_access = __selinux_check_access; 89 | freecon_t *freecon = __freecon; 90 | 91 | void init() { 92 | if (access("/system/lib/libselinux.so", F_OK) != 0 && access("/system/lib64/libselinux.so", F_OK) != 0) 93 | return; 94 | 95 | void *handle = dlopen("libselinux.so", RTLD_LAZY | RTLD_LOCAL); 96 | if (handle == nullptr) 97 | return; 98 | 99 | getcon = (getcon_t *) dlsym(handle, "getcon"); 100 | setcon = (setcon_t *) dlsym(handle, "setcon"); 101 | setfilecon = (setfilecon_t *) dlsym(handle, "setfilecon"); 102 | selinux_check_access = (selinux_check_access_t *) dlsym(handle, "selinux_check_access"); 103 | freecon = (freecon_t *) (dlsym(handle, "freecon")); 104 | } 105 | } 106 | --------------------------------------------------------------------------------