Я вставил некоторые новые функции в Android Runtime (ИЗОБРАЗИТЕЛЬНОЕ ИСКУССТВО), и теперь я хочу показать его внешнему миру через интерфейс. Поскольку это нативный код, я буду использовать JNI
интерфейс для вызова этой новой функциональности, аналогично функциональности сборщика мусора: Runtime.getInstance().gc()
,
Тем не менее, меня не волнует создание нового SDK, который может быть использован IDE, поскольку я буду вручную вводить байт-код в файлы .dex, которые будут выполнять вызов.
Я редактировал Runtime.java
в libcore/luni
, а также java_lang_Runtime.cc
в art
аналогичным образом с gc()
функция. Я создаю новый libart.so
а также core-libart.jar
и я прошить их на устройстве.
Тем не менее, когда я пытаюсь перезагрузить устройство, я получаю сообщение:
Failed to register native method java.lang.Runtime.myMethod()V in /system/framework/core-libart.jar
...
----- class 'Ljava/lang/Runtime;' cl=0x0 -----
vtable (24 entries, 11 in super):
// 24 entries are listed here. My entry is missing.
...
в Runtime.java
Я регистрирую нативный метод и подавляю некоторые предупреждения на полную сборку, используя @hide. например,
/** @hide */
public native void myMethod();
в java_lang_Runtime.cc
Я определяю функцию (которая будет вызывать внутреннюю структуру ART) и регистрирую ее в массиве gMethods [] с помощью макроса. например,
static void Runtime_myMethod(JNIEnv*, jclass) {
// body
}
NATIVE_METHOD(Runtime, myMethod, "()V")
Устройство находится на загрузочной петле. Есть ли другие файлы, которые я должен был отредактировать? Стоит ли создавать дополнительные модули или отправлять какие-либо другие файлы на устройство?
Кстати, я не хочу строить новый SDK
что касается вызова myMethod
Я буду вводить Dalvik bytecode
в файл APK. В основном я получу экземпляр Runtime, а затем вызову метод.
Эта проблема:
Android поставляет заводские образы с предварительно оптимизированными компонентами фреймворка.
Файл boot.oat
содержит предварительно оптимизированный код (или код odex), доступ к которому можно получить, прочитав указатели, содержащиеся в boot.art
файл.
Эти два файла содержат код только для boot classpath
,
Остальная часть фреймворка и остальные системные приложения (в app
а также priv-app
) папки имеют автономные odex
файлы.
На этом этапе предварительной оптимизации код dex изъятые модуля фреймворка (jar или apk), компилируется с использованием dex2oat
и полученный код находится в файлах, которые я только что упомянул.
Некоторые из вещей, которые я пробовал:
Доставка только libart.so
а также core-libart.jar
не работает, хотя последний содержит код dex. Это потому, что среда выполнения все еще пытается прочитать эту информацию из boot.oat
,
Изменяя конфигурацию устройства, чтобы сделать предварительную оптимизацию, aosp build system
может генерировать boot.oat|art
а остальное odex
файлы (больше Вот). Я ожидал, что перепрошивка все это должно работать, но это не так.
(по крайней мере, для marshmallow-release
ветка, на нексус6)
Я попытался перепрограммировать всю сгенерированную aosp сборку, и она не работала, даже с собственным ядром, которое я собираю с функциями безопасности (verity
) отключен.
Я уверен, что некоторые из них должны были работать, но должно быть что-то еще, что следует учитывать при сборке ОС.
Решение:
В крайнем случае, был deodexing
и, к счастью, это сработало.
Я написал небольшой скрипт это делает это для Nexus 6 на Зефире.
Сценарий, во время 1-го этапа, он убирает все oat/odex
код из соответствующих мест, и де-оптимизирует его dex
код, благодаря oat2dex а также smali проекты.
На втором этапе он упаковывает dex
Код обратно, в рамках модулей (jars / apks).
Доставка совершенно новый core-libart.jar
к устройству все еще не работает (не уверен почему), но мастеринг файлов dex перед упаковкой их в модули делает свое дело! :))
libart.so
теперь могу найти Runtime.myMethod()
, который может быть вызван приложением (снова smali возиться), чтобы запустить мой код внутри ART
,
Других решений пока нет …