Camera tools xiaomi что это
Перейти к содержимому

Camera tools xiaomi что это

  • автор:

Скрытые функции камеры смартфонов Xiaomi, о которых не знает большинство пользователей

Смартфоны Xiaomi имеют скрытые от пользователя возможности камеры, о которых многие не знают. Получить к ним доступ можно в стандартном приложении «Камера», но некоторые режимы хорошо спрятаны в системе, и мы расскажем, как их активировать.

Скрытые функции камеры смартфонов Xiaomi, о которых не знает большинство пользователей - today.ua

Для активации скрытых режимов камеры Xiaomi понадобится стандартный «Проводник MIUI». Первое, что нужно сделать — это открыть проводник, найти папку «DCIM» с медиа и перейти в папку «Camera».

Создаем новую папку на смартфоне Xiaomi внутри папки «Camera» и даем ей название lab_options_visible. Нажимаем OK, после чего перезагружаем смартфон, чтобы новые изменения сохранились.

Подпишитесь на Today.ua, чтобы быть в курсе последних новостей:

Скрытые функции камеры смартфонов Xiaomi, о которых не знает большинство пользователей

Переходим к приложению «Камера» — «Настройка», и после проведенных предварительных манипуляций перед вами появится «Experimental Feature (Экспериментальная функция)» с большим количеством режимов на выбор. Некоторые из них будут включены по умолчанию.

Популярные сейчас

  • «Internal magic tools» — функция для создания эффектов для фото;
  • «Turn on dual camera» — функция включает в себя двойную камеру смартфона. Трогать функцию НЕ НУЖНО — она по умолчанию включена в смартфоне, и ее отключения вызывает сбой в работе камеры, после чего приложение выдает сообщение «Не удается подключиться к камере». Вполне возможно, что функция предназначена для отладки.
  • «Turn on dual SAT camera» — проходим и мимо этой функции. Ее отключения вызывает ту же ошибку.
  • «Turn on MFNR» — функция Multi-frame noise reduction убирает шум на фото путем объединения нескольких фотографий в одну. Лучше работа MFNR заметна при ночной съемке.
  • «Turn on parallel processing» — включает многоядерных обработку. Отключать функцию не нужно — она влияет на скорость фокусировки и обработки изображений.

XiaomiMiTool — как скачать?

Оригинальная прошивка MIUI, устанавливаемая на смартфоны Xiaomi, обладает большими возможностями по настройке устройства. Опытным пользователям этого может быть недостаточно и поэтому они устанавливают модифицированные прошивки или дополнительные программы. Рут Magisk, например. Для упрощения этих операций была создана утилита Xiaomi Mi Tool V2. О том, что с ее помощью можно сделать и расскажет эта статья.

Xiaomi Mi Tool V2

Приложение Xiaomi Mi Tool V2 нужна для перепрошивки смартфонов Xiaomi.

О приложении

Xiaomi Mi Tool V2 — это многофункциональная утилита для перепрошивки смартфонов Xiaomi, работающая на компьютерах с операционными системами программный инструмент для компьютеров под управлением Windows (7,8,10) Ubuntu/Debian Linux и Apple MacOS.

Основные функции и возможности

К ним можно отнести:

  • автоматическое скачивание и установка Global Stable версии прошивки, подобранной на основе сведений о подключенном к компьютеру смартфоне;
  • обзор общей информации о смартфоне: версия прошивки, статус загрузчика;
  • установка модифицированных/неофициальных прошивок, рекавери или получение прав суперпользователя через режим fastboot или стандартный рекавери;
  • разблокировка загрузчика;
  • встроенные в утилиту инструменты для работы с Android смартфонами и набор драйверов для устройств Xiaomi;
  • автоматическое управление смартфоном во время процедуры перепрошивки.

Скачивание и установка

Порядок действий следующий:

Порядок установки

Порядок установи Xiaomi Mi Tool.

  1. Перейти на страницу загрузки на сайте разработчика утилиты Xiaomi Mi Tool:
  1. Выбрать версию утилиты и операционную систему, куда будет установлена программа.
  2. Нажать “Click here”.
  3. Разрешить браузеру сохранить файл и указать место сохранения, если это предусмотрено настройками.
  4. Запустить скачанный файл, разрешив ему вносить изменения в систему.
  5. Нажать “Next” в открывшемся окне.
  6. Указать место установки утилиты нажав кнопку “Browse…”.
  7. Нажать “Install”.
  8. Снять галочку с “Run Xiaomi Mi Tool” и нажать “Finish”.

Установка официальной прошивки

  • Tenorshare Android Data Recovery: https://www.tenorshare.ru/products/android-data-recovery.html

Для этой процедуры не нужен разблокированный загрузчик. Порядок действий следующий:

Выбор устройства

Выбор устройства

  1. Выйти из Google и Mи-аккаунта на смартфоне.
  2. Сделать резервную копию личных данных с помощью утилиты Tenorshare Android Data Recovery.
  3. Зарядить аккумулятор смартфона до 80-90%.
  4. Включить отладку по USB.
  5. Подключить телефон к компьютеру и разрешить сопряжение устройств, нажав на кнопку “Разрешить” в уведомлении, появившемся на экране смартфона.
  6. Запустить Xiaomi Mi Tool. При первом запуске появится предупреждение о том, что смартфон может выйти из строя при использовании утилиты и разработчик не несет за это ответственности. Чтобы закрыть предупреждение нужно нажать “Agree”.
  7. Выбрать регион “Russia”.
  8. Нажать кнопку “Choose” под надписью “My device works normally. I want to mod it”. (перев. Мое устройство работает нормально. Я хочу модифицировать его.)
  9. Выбрать телефон, выделив строку в таблице щелчком левой кнопкой мыши и нажав “Select”.
  10. Подождать, пока утилита соберет информацию о смартфоне.
  11. Выбрать в появившемся меню пункт “Xiaomi official ROM”.
  12. В перечне подходящих прошивок выбрать вариант Global Stable.
  13. Согласиться с предупреждениями и нажать “Continue”.
  14. Подождать, пока не скачается и установится прошивка. Отсоединять смартфон от компьютера во время процедуры запрещено! В противном случае устройство перестанет включаться или загрузка будет бесконечной.

Xiaomi Official ROM

Процесс установки новой прошивки.

Удачное окончание перепрошивки будет обозначено надписью “Installation completed successfully”. После этого смартфон можно отключить от компьютера, а утилиту Xiaomi Mi Tool закрыть. Устройство автоматически перезагрузится.

Возможные трудности

  • Драйверы для Xiaomi: https://androidmtk.com/download-xiaomi-usb-drivers
  1. Проверить, включена ли отладка по USB.
  2. Переустановить утилиту и попробовать снова.
  1. Проверить, включена ли отладка по USB.
  2. Установить драйверы для смартфона.
  1. Закрыть Mi Tool.
  2. Включить отладку по USB.
  3. Отключить смартфон от компьютера и выключить его.
  4. Включить смартфон, зажав кнопки питания и повышения громкости.
  5. Выбрать в меню рекавери пункт “Connect with mi assistant”.
  6. Подключить телефон к ПК.
  7. Запустить Mi Tool.

Подводя итог, можно сказать, что утилита Xiaomi Mi Tool это удобный и многофункциональный инструмент для обновления и переустановки прошивки, установки неофициальных прошивок и кастомных рекавери, получения прав суперпользователя и разблокировки загрузчика.

Сетевая камера Xiaomi Xiaomo Smart AI Camera CG010

Сетевая камера Xiaomi Xiaomo Smart AI Camera CG010

В наши дни многие готовы пересечь океаны и вскарабкаться на вершины только ради хорошего портрета. Но не у всех есть знакомый, которые эти хорошие портреты умеет делать, да и самому делать фотографии намного удобнее. Камера XiaoMo поможет Вам открыть себя с совершенно новых ракурсов и запечатлеть каждый момент во всей его красе. Она умеет делать не только превосходные снимки, но и короткие видео. Теперь Вам не придется таскать с собой штатив или искать оператора, камера сама все сделает.

Управление жестами

Теперь можно запечатлеть больше

Благодаря использованию технологий больших данных и глубокого машинного обучения, камера XiaoMo с высокой точностью распознает жесты пользователя. Например, точность распознавания жеста “ножницы” ✌️ составляет 91%. Не нужно думать о том, как и когда спустить затвор, ведь можно одним жестом поставить таймер на 3 секунды и дать волю воображению.

Жест 1: Ладонь в кулак

1. В течение 0.5 секунд держите в объективе свою ладонь, на камере загорится белый полукруг (Как на картинке), который означает, что жест распознан.

2. После распознавания жеста, сожмите ладонь в кулак, на камере загорятся дополнительные огоньки (Как на картинке), после чего включится таймер.

3. По истечению времени отсчета камера сделает один снимок. Белый круг в этом случае будет служить таймером.

Жест 2: ножницы

1. В течение 0.5 секунд держите перед камерой жест “ножницы”, после чего загорится белый полукруг (Как на картинке). Это означает, что жест распознан.

2. Подождите, пока не загорятся дополнительные огоньки (Как на картинке), после чего включится таймер.

3. По истечению таймера камера сделает один снимок. Белый круг в этом случае будет служить индикатором времени.

Данные получены от испытательной лаборатории MeetVR. Оптимальная дистанция распознавания жеста — 0.7-3 м. Эффективность распознавания жестов может отличаться. В условиях чрезмерного или обратного освещения распознавание жестов не так эффективно, как в нормальных условиях.

Крепление на магнитах

Для съёмки с любого ракурса

Камера XiaoMo оснащена многофункциональным креплением, которое также может сыграть роль небольшого штатива, позволяющего крутить камеру на все 360° и делать снимки с самых разных углов.

Съёмка с помощью XiaoMo

Установите камеру XiaoMo на ровной поверхности, настройте желаемый ракурс и начните делать снимки.

Внутренний неодимовый магнит имеет силу притяжения 3300 GS, что позволяет устанавливать камеру на абсолютно любой металлической поверхности.

Стойкий полиуретановый клей может выдержать до 500 циклов мойки, и все равно будет отлично держаться на любой поверхности.

Приложение XiaoMo Camera

Широкие функции, простота использования

С помощью приложения XiaoMo Camera Вы сможете делать коллажи из фотографий, просматривать изображение через объектив камеры, управлять ей, загружать фотографии и видео, применять фильтры и делать множество полезных вещей. Приложение XiaoMo Camera делает управление камерой еще проще, позволяя Вам создавать непревзойденные снимки в любом месте и в любое время.

Быстрая зарядка, долгое время работы от батареи

XiaoMo Camera оснащена литий-ионным аккумулятором емкостью 910 мАч, который обеспечивает более 100 минут работы устройства, чего вполне хватит для повседневного использования. А если Вы с собой носите переносной аккумулятор, то можно и вовсе не волноваться о такой мелочи — лишь бы фотографии хорошими вышли.

Стильная и компактная

Особая технология ультразвуковой сварки обеспечивает максимальную прочность и компактность камеры XiaoMo. Корпус камеры выполнен из 61 детали из поликарбоната и ABS-пластика, он невероятно легкий, при этом прочный и устойчивый к истиранию. Все 287 электронных компонентов уложены в пространство размером 47 * 47 *27 мм, общий вес камеры — всего 65 гр. Ее можно с легкостью взять с собой, и она не займет много места.

Начало использования XiaoMo Camera

1. Установите приложение

Отсканируйте QR-код и скачайте приложение XiaoMo Camera

2. Включите камеру

Для включения камеры зажмите на 2 секунды кнопку на корпусе, первый запуск может занять до 30 секунд.

3. Подключите камеру

Включите камеру и откройте приложение, после чего следуйте указаниям приложения.

Камерой можно управлять как с помощью жестов, так и с помощью смартфона.

До 12Мп — 4608 x 2592

Wi-Fi 802.11 b/g/n, возможность дистанционного управления камерой со смартфона.

Копаемся в встроенном приложении камеры старого Xiaomi. Часть 1

Всем привет! Шел 2023 год, и я не на шутку решил задуматься о смене своего верного бойца Xiaomi Mi A1 2017 года выпуска на что-то посвежее. Об успешности этого старичка можно говорить много – начиная тем что он первый Xiaomi на Android One и заканчивая огромной популярностью в свои годы.

Но сегодня хочется поговорить о другом. О камере. Сразу отмечу, что камера у этого устройства не была его сильным преимуществом даже в далеком 2017 году.

Пример интерфейса камеры на Xiaomi Mi A1

Но за годы пользования мне приглянулся встроенный фильтр в стандартном приложении камеры – «Ломо».

Пожалуй, этот фильтр — настоящее спасение для многих снимков для камеры этого устройства и сопоставимых по качеству. Пролистав галерею я обнаружил, что четверть снимков была сделана именно с ним.

И вот купил я себе Redmi Note 12 Pro, вроде и камера получше, и фильтры всякие разные, а того самого привычного «Ломо» мне стало очень не хватать. Ну, значит попытаемся его портировать!

Инструменты

Для доведения дела до конца мне понадобились следующие инструменты –

1. MT Manager – удобный базовый транслятор apk в smali инструкции, а также инструмент для подписи приложения

2. APK Editor – простой инструмент для работы с apk (переименование, замена ресурсов)

3. ADB – отладочный мост для андроид

4. ApkDecompiler – онлайн сервис для декомпиляции приложений

5. Patchelf – утилита для
переименования символов в нативных библиотеках

Первая попытка – попытаемся установить в лоб

Сам файл приложения можно с легкостью сковырнуть по пути /system/system/priv-app/MiuiCamera/MiuiCamera.apk на смартфоне Mi A1. Исходный файл приложения можно найти тут.

Приступим к установке?

Вот и установили.

Получаем ожидаемый результат – совпадение имен пакетов apk, из-за чего установка не удалась. Заметим, что на новеньком Redmi приложение имеет не только одинаковое название пакета, но и является приложением потомком, если так можно сказать, приложения установленном на нашем старичке.

Вторая попытка – переименовываем пакет

У нас на пути проблема – имя пакета уже занято в списке установленных приложений. Первое очевидное ее решение – а давайте переименуем пакет для нашего приложения? Используя APK Editor так и поступим.

Окно редактирования пакета в ApkEditor

Хочу обратить внимание на то, что изначальное название пакета – com.android.camera , а заменить мы его пытаемся на com.android.camerb , тем самым поменяв лишь одну букву. Вообще, принцип минимальных изменений предпочтителен в патчах, т.к. чем меньше мы изменили, тем меньше шансы что мы что-то сломаем (даже в случае переименования, ведь никто не гарантирует что где-то мы не собьем привязку к длине имени пакета, например). Об этом нам также дружелюбно напоминает окно Apk Editor.

После переименования пакета мы собьем в нем хеш-суммы для файлов classes.dex и AndroidManifest.xml , что значит невозможность его повторной установки. Благо эту проблему нельзя назвать серьезной – можно заново подписать приложение используя MT Manager прямо на устройстве.

Пункт меню

После подписи новый apk файл будет создан прямо в папке с изначальным пакетом. Пытаемся установить приложение, запускаем и…

Третья попытка – заглядываем внутрь

Чтобы выяснить конкретную проблему падения приложения включаем на смартфоне режим разработчика и отладку по USB. На компьютер устанавливаем средство ADB и начинаем наше расследование.

Запускать ADB будем прямо из консоли Powershell. После того как подключили смартфон по USB и подтвердили сопряжение ADB, запускаем команду на отлавливание ошибок в Powershell — .\adb logcat *:E > err1.txt . Теперь снова пытаемся запустить приложение. Камера закономерно вылетела, как и раньше, но теперь у нас есть больше улик в файле err1.txt. Останавливаем запись логов чтобы не флудить (банальным Ctrl+C) в Powershell и отправляемся на раскопки.

Хочу отметить, что аналогичную отладку можно проводить в том же эмуляторе Nox Player, с установленным aLogcat вместо ADB. Но в данном кейсе т.к. могут быть устройство-специфичные моменты, я провожу отладку через ADB.

Сделав поиск по ключевому слову camerb мы увидим в файле логов следующее:

E/AndroidRuntime( 8734): FATAL EXCEPTION: Thread-12 E/AndroidRuntime( 8734): Process: com.android.camerab, PID: 8734 E/AndroidRuntime( 8734): java.lang.NumberFormatException: null E/AndroidRuntime( 8734): at java.lang.Integer.parseInt(Integer.java:483) E/AndroidRuntime( 8734): at java.lang.Integer.parseInt(Integer.java:556) E/AndroidRuntime( 8734): at android.hardware.Camera$Parameters.getInt(Camera.java:2611) E/AndroidRuntime( 8734): at android.hardware.Camera$Parameters.getJpegThumbnailSize(Camera.java:2728) E/AndroidRuntime( 8734): at com.android.camerab.module.CameraModule.updateCameraParametersPreference(CameraModule.java:3877) E/AndroidRuntime( 8734): at com.android.camerab.module.CameraModule.setCameraParameters(CameraModule.java:4185) E/AndroidRuntime( 8734): at com.android.camerab.module.CameraModule$CameraStartUpThread.run(CameraModule.java:376)

Мельком взглянув на ошибку можно лишь предположить, что какое-то число оказалось не числом при попытке его парсинга. Без более обширного контекста понять суть проблемы сложно, поэтому нам необходим исходный код как минимум класса в котором произошла ошибка.

Для декомпиляции я буду использовать бесплатный онлайн ресурс http://www.javadecompilers.com/apk. Переходим на сайт и выгружаем наше приложение. В моем случае весь процесс декомпиляции занял меньше минуты и вот у нас на руках весь исходный java код.

Сразу направляемся к проблемному месту – вызову getJpegThumbnailSize() внутри метода updateCameraParametersPreference() в классе com.android.camerb.module.CameraModule.

if (21 Log.v("Camera", "Thumbnail size is " + optimalSize2.width + "x" + optimalSize2.height); >

Из комментариев и общей структуры становится понятно, что блок выше – есть установка нужного размера превьюшек для камеры, причем вызываем мы этот блок только с 5.0 андроида и выше.

Мне в начале вообще показалось, что тут ошибка в условии, и должно быть 21 >= Build.VERSION.SDK_INT, ведь Google пометил этот класс параметров устаревшим начиная с 21 API.

В любом случае, учитывая, что вся работа блока — это установка размеров превью, думаю, что мы можем просто вырезать данную логику без последствий, ведь без изначального значения это поле не останется.

Для точечного патчинга будем править smali байткод с помощью того-же MT Manager прямо с нашего смартфона.

Заглядываем в соответствующий класс и видим знакомый If:

.line 3870 sget v25, Landroid/os/Build$VERSION;->SDK_INT:I const/16 v26, 0x15 move/from16 v0, v26 move/from16 v1, v25 if-gt v0, v1, :cond_1fb

Последняя инструкция как раз выполняет прыжок за пределы блока If, проверяя что v0 (ака v26 ака 0x15 ака 21) больше чем v1 (ака v25 ака SDK_INT). Давайте для простоты заменим ее на if-nez v0, :cond_1fb . Что фактически будет делать переход всегда, ведь 21 всегда не равно нулю.

Кстати, если Вас заинтересовал патчинг андроид приложений на уровне Smali байткода, для ознакомления с основными инструкциями можно воспользоваться замечательной статьей на Хабре которая была очень полезна мне в свое время.

Нажимаем сохранить, компилировать, пересобрать и вот у нас уже пропатченное приложение в котором пропущен проблемный участок.

Ну теперь нам должно повезти? Устанавливаем приложение и пытаемся его запустить.

Очень жаль, что снова…

Четвертая попытка – странности ArrayCopy

Повторная отладка показывает нам в чем проблема:

E AndroidRuntime: Process: com.android.camerb, PID: 27794 E AndroidRuntime: java.lang.IllegalAccessError: Method 'void java.lang.System.arraycopy(int[], int, int[], int, int)' is inaccessible to class 'com.android.camerb.IntArray' (declaration of 'com.android.camerb.IntArray' appears in /data/app/~~UjUVTw3OgP_-lbbsTgEHZg==/com.android.camerb-zsFlOpkreTHIR8orTBjIsQ==/base.apk) E AndroidRuntime: at com.android.camerb.IntArray.toArray(IntArray.java:42) E AndroidRuntime: at com.android.camerb.preferences.IconListPreference.filterUnsupported(IconListPreference.java:115) E AndroidRuntime: at com.android.camerb.ui.HdrButton.filterPreference(HdrButton.java:211) E AndroidRuntime: at com.android.camerb.ui.HdrButton.initializeXml(HdrButton.java:46) E AndroidRuntime: at com.android.camerb.ui.HdrButton.onCreate(HdrButton.java:62) E AndroidRuntime: at com.android.camerb.ui.V6RelativeLayout.onCreate(V6RelativeLayout.java:35) E AndroidRuntime: at com.android.camerb.ui.V6ModuleUI.onCreate(V6ModuleUI.java:29) E AndroidRuntime: at com.android.camerb.ui.UIController.onCreate(UIController.java:65) E AndroidRuntime: at com.android.camerb.module.CameraModule.onCreate(CameraModule.java:1840) E AndroidRuntime: at com.android.camerb.Camera.onCreate(Camera.java:95)

Подождите, но ведь System.arraycopy это статичный публичный метод. Как он может быть недоступен из какого-то класса?

Оказывается, может, если имеет неверную сигнатуру. Дело в том, что если обратиться к исходникам андроид нацеленным на 21 API (которое имеет наш старенький Mi A1), то мы обнаружим, что там эта перегрузка arraycopy(int[], int, int[], int, int) действительно присутствует, и имеет видимость public. Однако если глянуть тот-же метод но уже в 30 API (который использует наш преемник – новенький Redmi Note 12), то там есть только канонический arraycopy(Object[], int, Object[], int, int) , а все аналогичные перегрузки уже помечены private, поэтому и недоступны нам.

Для нас это значит, что придется заменить все подобные перегрузки на канонический arraycopy(Object[], int, Object[], int, int) . Приступим! Открываем MT Manager:

Поиск в Smali коде через MT Manager

А вот и наши кандидаты (и еще несколько ниже). Их всех нам нужно заменить на arraycopy(Ljava/lang/Object;ILjava/lang/Object;II) . Можно руками по одному вызову, а можно, например, заменой:

Замена в Smali коде

Аналогичную замену проводим для arraycopy([BI[BII) .

Пытаемся собрать и установить приложение. Запускаем… И видим падение(

Пятая попытка – заглядываем еще дальше

Проделываем трюк с отловом ошибки еще раз и в этот раз видим уже другую проблему. Движение есть, но пока мы не знаем в какую сторону)

E/AndroidRuntime(16927): java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference E/AndroidRuntime(16927): at com.android.camerb.ui.V6SettingsStatusBar.updateZoom(V6SettingsStatusBar.java:133) E/AndroidRuntime(16927): at com.android.camerb.ui.V6SettingsStatusBar.updateStatus(V6SettingsStatusBar.java:100) E/AndroidRuntime(16927): at com.android.camerb.ui.V6SettingsStatusBar.onCameraOpen(V6SettingsStatusBar.java:168) E/AndroidRuntime(16927): at com.android.camerb.ui.V6ModuleUI.onCameraOpen(V6ModuleUI.java:56) E/AndroidRuntime(16927): at com.android.camerb.ui.UIController.onCameraOpen(UIController.java:93) E/AndroidRuntime(16927): at com.android.camerb.module.CameraModule$MainHandler.handleMessage(CameraModule.java:473) E/AndroidRuntime(16927): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime(16927): at android.os.Looper.loop(Looper.java:154) E/AndroidRuntime(16927): at android.app.ActivityThread.main(ActivityThread.java:6176) 

В этот раз приложение пытается получить элемент в списке который равен null. Переходим в соответствующий исходный файл и видим следующую картину:

public void updateZoom() < Camera.Parameters parameters = CameraManager.instance().getStashParameters(); if (((((ActivityBase) this.mContext).getUIController().getZoomButton().getVisibility() == 8) || CameraSettings.isSwitchCameraZoomMode()) && parameters != null) < int value = parameters.getZoomRatios().get(CameraSettings.readZoom(CameraSettingPreferences.instance())).intValue(); if (value >100) < int value2 = value / 10; String text = "x " + (value2 / 10) + "." + (value2 % 10); boolean same = this.mZoomTextView.getText().equals(text); this.mZoomTextView.setText(text); setSubViewVisible(this.mZoomTextView, 0, same); return; >> setSubViewVisible(this.mZoomTextView, 8, true); >

Проблема происходит на 5 строчке, getZoomRatios() возвращает null из API. Вероятно, дело опять в методах которые помечены устаревшими. Мы видим, что все для чего используется получаемое значение, это для отрисовки текста в области статуса во время зума, например, в виде «x 2.5» в случае приближения в 2.5 раза.

Предлагаю применить тот-же подход и просто вырезать эту логику, чтобы не встречать ее вновь. Видите этот && parameters != null в конце условия? Давайте переделаем его чтобы оно перестало выполняться. Отправляемся в MT Manager:

.line 130 .local v0, "parameters":Landroid/hardware/Camera$Parameters; . if-nez v5, :cond_25 invoke-static <>, Lcom/android/camerb/CameraSettings;->isSwitchCameraZoomMode()Z move-result v8 if-eqz v8, :cond_7e :cond_25 if-eqz v0, :cond_7e

Последняя инструкция как раз отвечает за часть условия && parameters != null . Заменяем ее инструкцией goto :cond_7e , чтобы переход был безусловным. Отметим, что метка :cond_7e смотрит ровно за пределы тела If, отсюда и ее неоднократное упоминание выше (которое нужно чтобы «соскочить» если левый операнд && условия будет нулем).

Традиционно сохраняем, компилируем, подписываем, устанавливаем. Что нас ждет в этот раз? Сейчас узнаем – запускаем…

Уже что-то!

Шестая попытка – warning, не значит необязательный

У нас 2 новости. Хорошая – мы увидели интерфейс приложения, оно таки запустилось благодаря нашим правкам. Плохая – приложение камеры работает не показывая изображение с камеры.

Несмотря на то, что мы не наблюдаем вылета, логи все еще для нас могут быть полезными. Поэтому направляемся прямиком в наш свежий файл логов и уже по знакомой строке поиска camerb находим там:

W/System.err(22665): android.provider.Settings$SettingNotFoundException: user_rotation W/System.err(22665): at android.provider.Settings$System.getIntForUser(Settings.java:2046) W/System.err(22665): at android.provider.Settings$System.getInt(Settings.java:2036) W/System.err(22665): at com.android.camerb.Util.checkLockedOrientation(Util.java:507) W/System.err(22665): at com.android.camerb.Camera.onWindowFocusChanged(Camera.java:370) W/System.err(22665): at com.android.internal.policy.DecorView.onWindowFocusChanged(DecorView.java:1457) W/System.err(22665): at android.view.View.dispatchWindowFocusChanged(View.java:10258)

В этот раз устройство не может считать значение настройки user_rotation которая отвечает за ориентацию экрана. Благо мы без труда вместо чтения этой настройки можем подсунуть одну из констант, описанных в документации, а именно – 0.

Открываем исходный код чтобы прикинуть правки:

public static void checkLockedOrientation(Activity activity) < try < if (Settings.System.getInt(activity.getContentResolver(), "accelerometer_rotation") == 0) < mLockedOrientation = Settings.System.getInt(activity.getContentResolver(), "user_rotation"); >else < mLockedOrientation = -1; >> catch (Settings.SettingNotFoundException e) < e.printStackTrace(); >>

Ошибка происходит в 4 строке. Давайте заменим попытку получения значения user_rotation на константный 0. Посмотрим, что из себя представляет этот метод в Smali:

.line 507 invoke-virtual , Landroid/app/Activity;->getContentResolver()Landroid/content/ContentResolver; move-result-object v2 .line 508 const-string/jumbo v3, "user_rotation" .line 507 invoke-static , Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver; move-result v2 sput v2, Lcom/android/camerb/Util;->mLockedOrientation:I

Последние 4 инструкции получают значение user_rotation временно храня его в v2, потом перекладывая в переменную mLockedOrientation , ради которой и написан этот метод.

Заменим попытку получения user_rotation на константу 0:

.line 507 invoke-virtual , Landroid/app/Activity;->getContentResolver()Landroid/content/ContentResolver; move-result-object v2 .line 508 const-string/jumbo v3, "user_rotation" .line 507 const/4 v2, 0x0 sput v2, Lcom/android/camerb/Util;->mLockedOrientation:I

С помощью const/4 присваиваем v2 значение 0.

Пришло время испытать удачу еще раз. Устанавливаем, запускаем.

Успех! Мы видим изображение с камеры.

И вроде все хорошо, но подождите-ка, ради чего мы все это начали? Ради фильтра. А кнопки фильтров то и нет! А она должна быть слева снизу, вот где она была на Mi A1:

Седьмая попытка – в поисках фильтров

Наше положение стало несколько сложнее. Раньше нас за руку вели логи из-за которых падало приложение, и всегда был ориентир куда смотреть – какой класс указан при падении туда и смотрим. А сейчас мы остались один на один со всем приложением и 3.5мб исходного кода.

В таких ситуациях нам нужны хоть какие-то зацепки, предлагаю за такую взять имя фильтра – «Ломо». Т.к. приложение у нас многоязычное, искать эту зацепку изначально следует в resources.arsc , просматриваем ресурсы с помощью MT Manager:

Ищем ресурс через MT Manager

Наша первая зацепка — pref_camera_coloreffect_entry_instagram_rise . Пробуем его искать в исходниках:

Нашли упоминание в исходнике EffectController.java , посмотрим поподробнее:

if (addEntry)

Можем предположить, что он занимается добавлением элемента фильтра на панель. Но почему самой панели не видно? Давайте попробуем поискать ответ в начале метода:

public RenderGroup getEffectGroup(GLCanvas canvas, RenderGroup renderGroup, boolean wholeRender, boolean isSnapShotRender, int index) < boolean matchPartRender0; boolean matchPartRender1; Render gradienterEffectRender; if (!Device.isSupportedShaderEffect()) < return null; >boolean addEntry = canvas == null; boolean initOne = false; if (canvas == null) < . 

Видимо это метод который возвращает всю панель с эффектами. Подождите! А что это за первое условие у нас тут? Посмотрим в реализацию этой функции isSupportedShaderEffect() :

public static boolean isSupportedShaderEffect()

Мы опять имеем дело с своего рода настройками, хорошо хоть эта не выкидывает исключение (хотя так мы нашли бы ее быстрее методом выше). Давайте попробуем интереса ради заменить возвращаемое значение на true , для этого посмотрим на метод в переваренном виде:

.method public static isSupportedShaderEffect()Z .registers 2 .prologue .line 102 const-string/jumbo vO, "support_camera_shader_effect" const/4 v1, 0x0 invoke-static , Lcom/android/camerb/aosp_porting/FeatureParser;->getBoolean(Ljava/lang/String;Z) move-result v0 return v0 .end method

Просто заменим его на константный true :

.method public static isSupportedShaderEffect()Z .registers 2 .prologue .line 102 const-string/jumbo vO, "support_camera_shader_effect" const/4 v1, 0x1 return v1 .end method

Пробуем собрать и установить. Запускаем:

Скриншот с Redmi

По непонятной причине на кнопку фильтра нужно нажимать по верхней границе, однако получилось! Нам удалось вернуть фильтр. Давайте сделаем первый снимок с ним:

Камера очень неожиданно закрылась при попытке снимка. Перезаходим в приложение и видим, что фото к сожалению, не было сохранено. А ведь мы были так близки к успеху!

Восьмая попытка – роднимся с native библиотеками

Остался последний рубеж! Вновь отлавливаем ошибку и в этот раз наблюдаем следующую картину:

E/Camera (10251): ShaderNativeUtil load CameraEffectJNI.so failed. E/Camera (10251): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.android.camerb-1/base.apk"],nativeLibraryDirectories=[/data/app/com.android.camerb-1/lib/x86, /system/lib, /vendor/lib]]] couldn't find "libCameraEffectJNI.so" E/Camera (10251): at java.lang.Runtime.loadLibrary0(Runtime.java:984) E/Camera (10251): at java.lang.System.loadLibrary(System.java:1562) E/Camera (10251): at com.android.camerb.effect.ShaderNativeUtil.(ShaderNativeUtil.java:14) E/Camera (10251): at com.android.camerb.effect.ShaderNativeUtil.initTexture(ShaderNativeUtil.java:26)

Видимо мы совсем забыли про нативные библиотеки. Дело в том, что для системных приложений бывают случаи, когда нужные библиотеки хранятся в /system/system/lib вместо папки lib внутри самого пакета приложения.

И когда мы скопировали пакет приложения из папки /system/system/priv-app/MiuiCamera/MiuiCamera.apk мы забыли скопировать библиотеки.

Какой у нас план действий? Изначально я хотел скопировать нужную библиотеку из системной папки и потом также совершить несколько набегов из-за зависимостей других библиотек этой библиотекой. Но потом я вспомнил про то, что на новеньком Redmi это приложение является «продолжением» старого приложения Mi A1, и я решил его подробнее изучить.

Процесс декомпиляции показал, что по сути, новое приложение - это сильно нарощенное старое. Более того, в нем даже остался весь исходный код отвечающий за эти старинные фильтры типа «Ломо», но весь этот функционал был отключен, и как его включить я не знаю. И о чудо – в пакете камеры от Redmi присутствует папка lib с знакомой нужной нам библиотекой libCameraEffectJNI.so .

Предлагаю особо не копаясь просто скопировать всю папку lib в старое приложение и попробовать запустить.

После установки и запуска мы вновь получаем ошибку, все еще связанную с нативными библиотеками:

E/AndroidRuntime( 5032): java.lang.UnsatisfiedLinkError: No implementation found for int[] com.android.camerb.effect.ShaderNativeUtil.initJpegTexture(byte[], int, int) (tried Java_com_android_camerb_effect_ShaderNativeUtil_initJpegTexture and Java_com_android_camerb_effect_ShaderNativeUtil_initJpegTexture___3BII) E/AndroidRuntime( 5032): at com.android.camerb.effect.ShaderNativeUtil.initJpegTexture(Native Method) E/AndroidRuntime( 5032): at com.android.camerb.effect.ShaderNativeUtil.initTexture(ShaderNativeUtil.java:26) E/AndroidRuntime( 5032): at com.android.camerb.effect.renders.SnapshotEffectRender$EGLHandler.applyEffect(SnapshotEffectRender.java:743) E/AndroidRuntime( 5032): at com.android.camerb.effect.renders.SnapshotEffectRender$EGLHandler.drawMainJpeg(SnapshotEffectRender.java:817) E/AndroidRuntime( 5032): at com.android.camerb.effect.renders.SnapshotEffectRender$EGLHandler.handleMessage(SnapshotEffectRender.java:622)

На этот раз мы видим, что библиотека вроде как подгрузилась, а вот нужный метод в ней java часть найти не может. Если обратиться к логу, то мы увидим попытку доступа к символу (методу) Java_com_android_camerb_* в нативной библиотеке. Однако библиотека вряд ли содержит такой символ, ведь camerb это наше переименование, а в библиотеке скорее всего есть символ Java_com_android_camera_* , к которому и пытается получить доступ приложение.

Касательно этого символа initJpegTexture - он использован чтобы конвертировать GL текстуру в jpeg поток байт (чтобы затем этот поток сохранить в файл).

Для перенаправления есть два пути – первый, это написать промежуточную нативную библиотеку с переименованными «camerb» символами (например, libCameraEffectJNIProxy.so), которую и загрузить через System.loadLibrary . А уже внутри этой поддельной библиотеки внутри поддельных символов дергать настоящие символы из оригинальной библиотеки. Такой метод был бы предпочтителен, когда нам крайне нежелательно как-то трогать файл библиотеки.

Мы же будем использовать второй метод – воспользуемся утилитой для переименования символов Patchelf. Использование очень простое – нужно создать файл в котором в каждой строке будет пара значений типа . Чтобы узнать какие символы присутствуют в нашей библиотеке можно использовать онлайн сервис Elfy. По итогу у меня получился примерно такой файл (для каждого символа я лишь заменил «a» на «b» в слове camera):

Java_com_android_camera_effect_ShaderNativeUtil_readGraphicBuffer Java_com_android_camerb_effect_ShaderNativeUtil_readGraphicBuffer Java_com_android_camera_effect_ShaderNativeUtil_texChannelY Java_com_android_camerb_effect_ShaderNativeUtil_texChannelY Java_com_android_camera_effect_ShaderNativeUtil_initJpegTexture Java_com_android_camerb_effect_ShaderNativeUtil_initJpegTexture Java_com_android_camera_effect_ShaderNativeUtil_mergeWaterMarkRangeAlgo Java_com_android_camerb_effect_ShaderNativeUtil_mergeWaterMarkRangeAlgo Java_com_android_camera_effect_ShaderNativeUtil_nv21CompressToJpeg Java_com_android_camerb_effect_ShaderNativeUtil_nv21CompressToJpeg Java_com_android_camera_effect_ShaderNativeUtil_resizeGraphicBuffer Java_com_android_camerb_effect_ShaderNativeUtil_resizeGraphicBuffer Java_com_android_camera_effect_ShaderNativeUtil_getWaterMarkRange Java_com_android_camerb_effect_ShaderNativeUtil_getWaterMarkRange . 

Запускаем утилиту командой patchelf --output libPatched.so --rename-dynamic-symbols map_file.txt libCameraEffectJNI.so и в файле libPatched.so получаем нашу новую пропатченную библиотеку, которую и копируем в lib папку.

Теперь пытаемся установить и запустить наше приложение…

Итог

Успех! С восьмой (ну или чуть больше) попытки мы смогли портировать любимый фильтр с старого устройства на новое. Конечно и UI выглядит странно (с высокой черной полоской снизу), и остальные фичи вроде панорамы в нем не работают (встречая нас уже знакомой проблемой не переименованных символов), но ведь и цель у нас была совсем другая. Вероятно, это первый Redmi Note 12 Pro который сделал фотографию с старым фильтром Mi A1! Конечное приложение можно скачать себе тут.

Надеюсь, Вы получили удовольствие от данного погружения. Ну а в следующей статье попробуем приоткрыть завесу этого фильтра и разберемся в его внутреннем устройстве. До встречи!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *