Android даже не должен иметь двоичный файл su
, если вы не прошивали какой-либо корневой метод для устройства, такой как Magisk или SuperSU.
Даже если в нем есть su
двоичный файл, я не ожидаю, что он будет работать по одной из двух причин. Предполагая, что ваше устройство поставляется с предустановленным двоичным файлом su
, кто им управляет? Если он неуправляем, он должен просто отклонить все запросы. Если вы перенесете корневой метод, то этот менеджер сам решит, получит ли ваше приложение доступ к su
, независимо от того, есть ли у вас разрешения на уровне подписи или нет (в конце концов, корневой менеджер использует другую подпись).
А зачем вам вообще нужен доступ к su
в качестве приложения для подписи? В любом случае у вас есть полный доступ к устройству. Если вам нужно запустить команду, у вас не должно возникнуть проблем, независимо от того, что вы запускаете, если это выполняется из пакета, подписанного платформой. Но поскольку у вас есть полный доступ, нативные API-интерфейсы должны позволять вам делать все, что вам нужно.
Что касается IOException, возвращаемого при попытке выполнить su
в Процессе, это просто странная причуда Android. Если двоичный файл su
не установлен, он иногда возвращает command not found
, а иногда permission denied
, в зависимости от устройства.
Я хочу сказать, что, если ваше приложение не является корневым менеджером, вы можете быть частью system_server и по-прежнему иметь такой же доступ к su
, как и все остальные. С каким утверждением я согласен, я думаю, что № 3, хотя я не полностью согласен с этим, потому что шансов на то, что su
просто не существует, или это глупый двоичный файл.
Я объяснил, почему # 1 не должно быть правдой, а # 2 просто неверно. Если вы посмотрите на платформенный манифест , каждое разрешение, которое требует привилегированного приложения, также может быть предоставлено приложениям подписи. Поэтому, даже если вы переместите свое приложение на /system/priv-app/
(/system/app/
не сделает его привилегированным), это не будет иметь значения. По сути, если ваше приложение подписано подписью платформы, не имеет значения, где оно установлено.
EDIT:
Вы можете легко перезагрузиться, просто запустив команду reboot
, поскольку у вас есть доступ к системе на уровне подписи, но для этого немного более элегантно использовать подходящий API. Если вы используете API, вы получаете анимацию выключения, но вы также позволяете системе корректно завершать работу, останавливая службы и отправляя трансляцию ACTION_REBOOT всем приложениям, которые могут это прослушивать.
Чтобы использовать API, сначала добавьте следующее разрешение на AndroidManifest:
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
Теперь, когда вам нужно вызвать действие перезагрузки, используйте следующий код:
IStatusBarService bar = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
bar.reboot(false); //using true here will reboot to Safe Mode
Этот метод является скрытым, поэтому, если вы используете Android Studio для редактирования и компиляции, произойдет ошибка. Вы можете использовать отражение или использовать Android Hidden API для прямого доступа к нему.
Вот как System UI реализует это в меню питания: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
Это класс, реализующий сервис IStatusBar: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/services/core/java/com/android/server/statusbar/StatusBarManagerService.java#L969