Cámaras en ROM personalizadas: cómo los desarrolladores hacen que el hardware funcione sin código fuente

Con el lanzamiento de Android Oreo y muchos dispositivos como Xiaomi Redmi Note 3, Google Nexus 5 y otros que lo reciben de manera no oficial, probablemente sea justo preguntarse por qué las mismas funciones (principalmente la cámara) tienden a romperse cuando los desarrolladores portan un Android Open ROM basada en el Proyecto Fuente (AOSP). Probablemente haya visto hilos de ROM de foro con una larga lista de características rotas en la parte superior. "Lo que funciona" seguido de una lista de características de trabajo, luego debajo de ese icono "¿Qué no funciona? ¡Tú me cuentas! ”Son dos estribillos populares en nuestros foros que prácticamente se han convertido en un meme en lugares como Reddit y Twitter.

¿Por qué se rompe tanta funcionalidad cada vez que un desarrollador intenta portar una ROM AOSP en su dispositivo? La respuesta básica es que debido a que las funciones cambian entre las diferentes versiones de Android, los controladores de dispositivos antiguos empaquetados como BLOB no funcionarán con versiones más nuevas de Android, o incluso solo con AOSP de serie. Para superar eso, los desarrolladores hacen uso de lo que se llama una "cuña", pero el proceso involucrado es complicado, requiere mucho tiempo y, a veces, es muy difícil de depurar.

En este artículo, describiremos cómo funcionan las cuñas, especialmente con respecto a hacer que la cámara funcione correctamente en ROM basadas en AOSP. Utilizaremos el OnePlus 3T como ejemplo. Tenga en cuenta que la dificultad que implica lograr que estas funciones funcionen es muy específica del dispositivo.

OnePlus 3T ejecutando OxygenOS. Aunque los teléfonos OnePlus son conocidos por su facilidad de desarrollo personalizada, los desarrolladores realizan mucho trabajo detrás de escena para crear puertos estables de AOSP.


¿Qué es una cuña o un BLOB?

Para comenzar a comprender parte de lo que los desarrolladores están haciendo, primero tenemos que explicar algunas cosas. Aunque el sistema operativo Android es de código abierto (se llama Proyecto de Código Abierto de Android por una razón), el software (sin el núcleo) enviado en miles de dispositivos Android no lo es. Los desarrolladores no tienen acceso al código fuente de Samsung Experience, EMUI, OxygenOS o cualquiera de los otros sabores de Android de terceros.

Ahora, los desarrolladores que transfieren AOSP de stock a un dispositivo que no es de Google probablemente no se preocupen por el código fuente de estas máscaras de Android, ya que no van a modificar y construir estas ROM. Eso sería cierto, si no fuera por una gran, gran razón: las partes necesarias para que la cámara funcione correctamente, principalmente la cámara HAL (Capa de abstracción de hardware), también son de código cerrado .

El problema de tener no solo la cámara HAL, sino también la ROM de código cerrado es que los desarrolladores que trabajan en portar AOSP en su dispositivo estarán trabajando a ciegas . La ROM OEM de fuente cerrada es capaz de interactuar con la cámara HAL muy bien porque el OEM tiene acceso a la fuente HAL de la cámara. La cámara HAL es lo que permite que la ROM "hable" con el hardware de la cámara; sin ella, la cámara no funcionaría. Piense en la cámara HAL como el volante y los pedales del automóvil. El volante / los pedales permiten el control de los componentes internos del vehículo al proporcionar una interfaz externa para que el conductor (ROM) haga uso de los componentes internos.

Gráfico que muestra la arquitectura de la cámara. Fuente: Google

A medida que el hardware de la cámara se vuelve cada vez más complejo (el advenimiento de las cámaras duales, por ejemplo), tener acceso a la fuente HAL de la cámara haría que transportar una ROM AOSP con una cámara funcional sea un esfuerzo mucho más fácil.

Sin embargo, los OEM no proporcionan acceso a la fuente HAL de la cámara por varias razones. Primero, si no tienen todos los derechos de propiedad de la cámara HAL (como cuando incorporan propiedad intelectual de otras compañías), entonces no pueden distribuir la fuente. En segundo lugar, liberar la fuente HAL de la cámara puede poner en peligro su propia propiedad intelectual. Finalmente, las compañías no tienen la obligación legal de proporcionar este código fuente (a diferencia del código fuente del núcleo que están obligadas a liberar bajo la GPL), por lo que no tienen ningún incentivo para liberarlo. Entonces, sin acceso a la fuente HAL de la cámara, ¿cómo hacen los desarrolladores para que la cámara funcione en ROM AOSP? La respuesta es un BLOB, una cuña y mucha, mucha depuración.

Un dispositivo BLOB (Binary Large OBject) contiene binarios preempaquetados que son la forma compilada de software. En este caso, la fuente HAL de la cámara es compilada por el OEM y se envía a los dispositivos como archivos binarios. Cuando los desarrolladores hablan de BLOB, se refieren a los binarios que se envían en dispositivos en vivo que pueden extraer. Ahora, el tema de los "BLOB de cámara" ha afectado a OnePlus durante muchos meses, pero la verdad es que los desarrolladores siempre han tenido acceso a los BLOB de cámara. Sin embargo, el código fuente HAL de la cámara es el boleto de oro para los desarrolladores aquí, pero eso nunca se lanzará debido al peligro legal que pondría a compañías como OnePlus.

Por lo tanto, los desarrolladores que buscan llevar AOSP a un dispositivo solo se quedan con BLOB de la cámara HAL para los cuales no tienen acceso al código fuente. Raramente, si alguna vez, un desarrollador puede emparejar su código ROM AOSP con la cámara HAL BLOB y esperar que funcione, por lo que para cerrar la brecha entre los dos, los desarrolladores crean lo que se llama una " cuña ".

Para "calzar" es "calzar (algo) o llenar un espacio". Esto es efectivamente lo que hace un desarrollador al escribir una calza: agregan código para permitir que el BLOB interactúe con el código fuente de AOSP con el que está trabajando . Las cuñas se usan para hacer que los BLOBs de todo tipo funcionen con AOSP, pero generalmente, es el BLOB de la cámara el que requiere más shimming. Como mencionamos anteriormente, se requiere shimming no solo para portar versiones más recientes de Android a un dispositivo (como todas esas ROM Oreo de Android no oficiales) sino que también es necesario cuando se transfiere AOSP de la misma versión de Android a ese dispositivo.

Lectura recomendada: de la tienda a la estantería: una capitulación en profundidad de por qué los dispositivos MSM8974 están excluidos del turrón

El OnePlus 2, por ejemplo, recibió su última actualización oficial importante del sistema operativo en forma de Android 6.0 Marshmallow. Sin embargo, el dispositivo en realidad tiene ROM personalizadas basadas en AOSP totalmente basadas en Android Nougat, y eso es gracias al arduo trabajo de los desarrolladores y sus calzas. Vamos a analizar algunos ejemplos de cuñas, pero primero, necesitamos hablar sobre cómo funcionan exactamente las cuñas.


¿Cómo funciona la cuña?

Dado que los desarrolladores no tienen acceso a la fuente de ROM HAL o OEM de la cámara (y solo a los binarios precompilados), no pueden saber qué funciones espera la cámara HAL. Debido a esto, a menudo hay una falta de coincidencia entre el nombre de la función que está buscando la cámara HAL y el nombre real de la función en el código AOSP con el que está trabajando el desarrollador.

Para resolver este problema, el desarrollador simplemente crea una nueva función que usa el mismo nombre de la función que la cámara HAL BLOB espera, pero esta nueva función simplemente ejecuta lo que el desarrollador quiere que haga. Esta nueva función que actúa como intermediario entre BLOB y AOSP es la laminilla. Este escenario particular en el que el BLOB no puede encontrar la función que está buscando es uno de los más comunes donde se necesita una cuña.

Diagrama de pintura MS muy simple que muestra dónde se necesita una cuña.

Tal vez las cosas tengan un poco más de sentido con un ejemplo hipotético del OnePlus 3T. Crearemos un ejemplo usando OxygenOS y la cámara OnePlus. Si utilizamos BLOB de cámara tomados de OxygenOS Nougat para OnePlus 3T para construir una ROM de Nougat basada en AOSP, es posible que tengamos problemas. Esto se debe a que los BLOB de la cámara (que fueron compilados originalmente por el OEM) podrán hacer referencia a todas las funciones que necesita dentro de OxygenOS, pero dado que la ROM AOSP compilada puede no tener esas funciones o puede haberlas compilado con un nombre diferente ( lo que conduce a una falta de coincidencia entre los símbolos de función), habrá un error. Esto se puede solucionar creando una nueva función dentro de la ROM de AOSP con el nombre que BLOB espera: nuestra cuña.

Los símbolos en un contexto de programación se usan para referirse a funciones específicas en el código. Los símbolos son necesarios porque la posición de una función puede cambiar cuando se edita el código, y para evitar referencias de codificación a funciones, el compilador crea una tabla de símbolos que otras funciones pueden usar para referirse siempre a la función correcta. Cuando cambia el nombre de una función antes de compilar, su símbolo también cambia, por lo que básicamente cualquier cambio que el OEM realice en la fuente HAL de la cámara antes de la compilación requerirá que los desarrolladores creen una nueva cuña.

Ver una tabla de símbolos con la tolva. Fuente: Apriorit

La explicación que hemos ofrecido hasta ahora hace que parezca que crear cuñas es fácil. Cambiar algunos nombres de funciones aquí y allá no suena demasiado difícil, ¿verdad? Si solo fuera así de facil. La realidad de las lainas implica algo más que solo cambiar el nombre de las funciones. Hablamos con el desarrollador reconocido Sultanxda, quien pudo brindarnos un ejemplo de una de las cuñas más difíciles en las que ha trabajado.


Shimming: no es tan fácil como parece

Para aquellos que no están familiarizados con OnePlus 3T, la cámara frontal estaba bastante rota inicialmente en ROM personalizadas basadas en AOSP. Para empezar, intentar tomar una foto de más de 8MP provocaría un bloqueo. En su intento de resolver este problema, Sultanxda hizo varias cuñas para permitir que la cámara frontal OnePlus 3T funcione correctamente.

Calce n. ° 1: cambio del nombre del paquete de la cámara

Para evitar que la cámara frontal se bloquee cada vez que el usuario tomó una foto de más de 8MP, Sultanxda forzó a la cámara HAL a identificar todas las cámaras como la cámara OnePlus. Esto se hace porque OnePlus decidió dedicar una función auxiliar a ciertas aplicaciones ( isOnePlusCamera, isFacebookCamera, etc.) por alguna razón. Sultanxda solucionó esto al ajustar la cámara HAL para que apunte a una nueva función que siempre devuelve "verdadero" como si el usuario estuviera usando la cámara OnePlus, incluso cuando no lo están.

Calce n. ° 2: deshabilitar QuadraCfa

Para su próxima cuña, tuvo que desactivar QuadraCfa, que presumiblemente es una tecnología patentada de Qualcomm relacionada con la cámara. Decimos presumiblemente porque ni yo ni Sultanxda estamos exactamente seguros de qué es QuadraCfa, pero Sultanxda sabe que rompió la cámara frontal cada vez que estaba habilitada.

Observó que QuadraCfa se habilitaría de alguna manera, pero no estaba seguro de por qué o cómo lo estaba haciendo. Resolver esto requirió una modificación poco convencional de su parte. En un shim convencional, la función shim, cuando se compila, proporciona el símbolo que falta que BLOB está buscando. En este caso, el BLOB ya tenía los símbolos que necesitaba, los que presumiblemente representaban las funciones que estaban iniciando QuadraCfa.

Bendice al editor hexadecimal. El programa utilizado por Sultanxda.

Por lo tanto, necesitaba anular los símbolos utilizados por el HAL de la cámara y, en esencia, hacerlos "faltantes" para que sus calzas proporcionen esos símbolos "faltantes". La única forma de hacerlo es mediante la edición hexadecimal de la cámara HAL . La edición hexadecimal consiste básicamente en examinar un montón de galimatías no organizadas en forma de datos binarios para encontrar una aguja en el pajar, ya sea una función o una cadena que desea editar.

La edición hexadecimal de una función es sustancialmente más difícil que la edición hexadecimal de una cadena, pero afortunadamente, Sultanxda pudo evitar tener que editar hexadecimalmente las funciones detrás de QuadraCfa al editar hexadecimalmente los nombres de los símbolos para anular esos símbolos.

Calce n. ° 3: corrección de bloqueo de luz brillante

A continuación, Sultanxda identificó que tomar una foto de la cámara frontal cuando está bajo condiciones de luz brillante podría causar que la cámara se bloquee. Para reproducir este error en su propio dispositivo, ¡Sultanxda encendió la función de linterna de su OnePlus One y encendió la luz frente a la cámara frontal del OnePlus 3T para que se bloquee y produzca registros utilizables! Una vez que descubrió qué función estaba causando el bloqueo, creó una cuña para obligar al dispositivo a usar el modo de poca luz todo el tiempo para la cámara frontal.

Calce n. ° 4: imágenes de la cámara frontal de baja resolución

Después de arreglar el choque de la luz brillante con la cuña anterior, Sultanxda descubrió otro error que realmente surgió como resultado directo de esa cuña: imágenes de cámara frontal de baja resolución. En lugar de tomar imágenes a la resolución solicitada por el usuario (por ejemplo, 16MP), la imagen resultante se tomaría a 4MP.

Resolver esto requirió que handleSuperResolution las funciones handleSuperResolution y isSuperResolution para que siempre sea verdad, pero SOLO cuando la cámara frontal está activa (porque de lo contrario, la cámara se bloquearía al tomar imágenes del sensor trasero).


Lección aprendida - Shimming puede ser difícil

Sultanxda admite que las cuñas que tuvo que crear para que la cámara frontal OnePlus 3T funcionara no representan su ejemplo típico de una cuña. Está bastante orgulloso de su cuña dada su complejidad y la rara necesidad de editar hexadecimalmente el BLOB. Pero este ejemplo solo muestra lo difícil que puede ser hacer que el hardware de la cámara funcione en ciertos dispositivos.

Que las aventuras de tu cámara sean menos dolorosas que las mías. -Sultanxda

Registros, registros y más registros. Sin una forma consistente de reproducir un bloqueo y sin registros, los desarrolladores tienen pocas esperanzas de encontrar la fuente del problema. Incluso si encuentran la causa del problema, no siempre es una solución sencilla. Todo el proceso de encontrar y eliminar estos errores puede llevar días o semanas y es la razón por la cual arreglar la cámara en ROMs AOSP es una de las tareas más difíciles.

Si su dispositivo tiene una ROM AOSP portada con hardware totalmente funcional, es de esperar que pueda comenzar a apreciar la lucha que esos desarrolladores podrían haber pasado para brindarle esas características. Los aprecio por su trabajo, porque no es fácil. Es una gran cantidad de trabajo que la gran mayoría de los usuarios ni siquiera notarán, ya que los desarrolladores talentosos en nuestros foros se están ocupando de las muchas partes invisibles de Android.

Quisiéramos agradecer especialmente a Sultanxda por las numerosas contribuciones que sugirió al hacer este artículo.