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

Sin código fuente, ¿cómo consiguen los desarrolladores que componentes de hardware, como cámaras, funcionen en ROM personalizadas? La respuesta es un BLOB, una corrección y mucha depuración.

Con el lanzamiento de Android Oreo y muchos dispositivos como el Xiaomi Redmi Nota 3, Google Nexus 5 y otros lo reciben extraoficialmente, probablemente sea justo preguntarse por qué las mismas características (principalmente la cámara) tienden a fallar cuando los desarrolladores portan una ROM basada en Android Open Source Project (AOSP). Probablemente hayas visto hilos de ROM en el foro XDA con una larga lista de funciones rotas en la parte superior. "Qué funciona", seguido de una lista de funciones que funcionan y, debajo, el icónico "¿Qué no funciona?". ¡Dígame usted!" 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 interrumpen tantas funciones cada vez que un desarrollador intenta migrar una ROM AOSP a 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 las versiones más nuevas de Android, o incluso solo con AOSP estándar. Para superar esto, los desarrolladores utilizan lo que se llama una "calza", pero el proceso involucrado es complicado, requiere mucho tiempo y, a veces, muy difícil de depurar.

En este artículo, describiremos cómo funcionan las cuñas, especialmente en lo que respecta a hacer que la cámara funcione correctamente en ROM basadas en AOSP. Usaremos el OnePlus 3T como ejemplo. Tenga en cuenta que la dificultad que implica hacer que estas funciones funcionen depende en gran medida del dispositivo.

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


¿Qué es una calza o un BLOB?

Para siquiera empezar a comprender parte de lo que hacen los desarrolladores, primero debemos 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 kernel) que se incluye en miles de dispositivos Android no lo es. Los desarrolladores no tienen acceso al código fuente de Experiencia Samsung, EMUI, Oxígeno, o cualquiera de las otras versiones de Android de terceros.

Ahora, a los desarrolladores que migran AOSP estándar a un dispositivo que no es de Google probablemente no les importe el código fuente de estas máscaras de Android, ya que no lo serán. modificando y construyendo estas ROM. Eso sería cierto, si no fuera por una gran razón: las piezas necesarias para que la cámara funcione correctamente, principalmente el camara hal (Capa de abstracción de hardware), son también fuente cerrada.

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 migrar AOSP a su dispositivo serán trabajando a ciegas. La ROM OEM de código cerrado puede interactuar perfectamente con la cámara HAL porque el OEM tiene acceso a la fuente HAL de la cámara. La cámara HAL es lo que permite que la ROM "se comunique" con el hardware de la cámara; sin ella, la cámara no funcionaría. Piensa en la cámara HAL como el volante y los pedales del coche. El volante/pedales permiten el control de los componentes internos del vehículo al proporcionar una interfaz externa para que el conductor (la 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 llegada de cámaras duales, por ejemplo), tener acceso a la fuente HAL de la cámara haría que portar una ROM AOSP con una cámara funcional fuera una tarea mucho más fácil.

Sin embargo, los fabricantes de equipos originales no brindan acceso a la fuente HAL de la cámara por varias razones. En primer lugar, si no tienen todos los derechos de propiedad de la cámara HAL (como cuando incorporan propiedad intelectual de otras empresas), entonces no pueden distribuir la fuente. En segundo lugar, liberar la cámara de origen HAL puede poner en peligro su propia propiedad intelectual. Finalmente, las empresas no tienen ninguna obligación legal de proporcionar este código fuente (a diferencia del código fuente del kernel que están obligado a publicar según la GPL), por lo que no tienen ningún incentivo para publicarlo. Entonces, sin acceso a la fuente HAL de la cámara, ¿cómo exactamente hacen los desarrolladores para que la cámara funcione en las ROM AOSP? La respuesta es un BLOB, una cuña y mucha, mucha depuración.

Un dispositivo GOTA (Binary Large OBject) contiene archivos binarios preempaquetados que son la forma compilada de software. En este caso, el OEM compila la fuente HAL de la cámara y la envía a los dispositivos como archivos binarios. Cuando los desarrolladores hablan de BLOB, se refieren a aquellos binarios que se envían en dispositivos activos y que pueden extraer. Ahora, el tema de los “BLOBs de cámara” ha OnePlus plagado durante mucho tiempo durante muchos meses, pero la verdad es que los desarrolladores siempre han tenido acceso a los BLOB de la cámara. El El código fuente HAL de la cámara es el billete dorado. para los desarrolladores aquí, sin embargo, pero eso nunca, jamás será liberado debido al peligro legal que pondría a empresas como OnePlus.

Por lo tanto, los desarrolladores que buscan incorporar AOSP a un dispositivo solo se quedan con los BLOB de la cámara HAL para los cuales no tienen acceso al código fuente. Rara 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 un "calce.”

"Calzar" es "cuñar (algo) o llenar un espacio". Esto es efectivamente lo que hace un desarrollador cuando escribiendo un shim: agregan código para permitir que el BLOB interactúe con el código fuente de AOSP en el que están trabajando con. Las cuñas se utilizan para hacer que BLOB de todo tipo funcionen con AOSP, pero normalmente es el BLOB de la cámara el que requiere más cuñas. Como mencionamos antes, el shimming es necesario no solo para migrar versiones más recientes de Android a un dispositivo (como todas esas ROM no oficiales de Android Oreo) pero también son necesarias al portar AOSP de la misma versión de Android a ese dispositivo.

Lectura recomendada: De la tienda al estante: una capitulación en profundidad de por qué los dispositivos MSM8974 están excluidos de Nougat

El OnePlus 2, por ejemplo, recibió su última actualización importante oficial del sistema operativo en forma de Android 6.0 Marshmallow. El dispositivo, sin embargo, en realidad tiene ROM personalizadas basadas en AOSP totalmente funcionales basado en Android Nougat, y eso es gracias al arduo trabajo de los desarrolladores y sus shims. Desglosaremos algunos ejemplos de calzas, pero primero debemos hablar sobre cómo funcionan exactamente las calzas.


¿Cómo funciona el calce?

Dado que los desarrolladores no tienen acceso a la fuente HAL o ROM OEM de la cámara (y solo a los archivos binarios precompilados), no pueden saber qué funciones espera la cámara HAL. Debido a esto, a menudo hay una discrepancia entre el nombre de la función que busca 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 del función que espera la cámara HAL BLOB, pero esta nueva función simplemente ejecuta lo que el desarrollador quiere eso a. Esta nueva función que actúa como intermediario entre BLOB y AOSP es el shim. Este escenario particular en el que el BLOB no encuentra la función que busca es uno de los más comunes en los que se necesita una cuña.

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

Quizás las cosas tengan un poco más de sentido con un ejemplo hipotético que involucre al 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 Nougat basada en AOSP, podemos tener 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 desde el La ROM AOSP compilada puede no tener esas funciones o puede haberlas compilado con un nombre diferente (lo que lleva 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 AOSP con el nombre que espera el BLOB: nuestro shim.

Los símbolos en un contexto de programación se utilizan 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, por lo tanto, para evitar la codificación referencias a funciones, el compilador crea una tabla de símbolos que otras funciones pueden usar para referirse siempre a la función correcta. función. Cuando cambias 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 hace a la fuente HAL de la cámara antes de la compilación requerirá que los desarrolladores creen una nueva calce.

Visualización de una tabla de símbolos con Hopper. Fuente: a priori

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


Calzar: no es tan fácil como parece

Para aquellos que no están familiarizados con el OnePlus 3T, la cámara frontal estaba bastante rota inicialmente ROM personalizadas basadas en AOSP. Para empezar, intentar tomar una fotografía de más de 8MP resultaría en chocando. En su intento por solucionar este problema, Sultanxda realizó varias cuñas para permitir que la cámara frontal del OnePlus 3T funcione correctamente.

Calce n.º 1: cambiar el nombre del paquete de la cámara

Para evitar que la cámara frontal fallara cada vez que el usuario tomaba una fotografía de más de 8MP, Sultanxda obligó 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 determinadas aplicaciones (isOnePlusCamera, isFacebookCamera, etc.) por alguna razón. Sultanxda solucionó este problema ajustando 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á.

Calce n.º 2: deshabilitar QuadraCfa

Para su siguiente corrección, 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 sí sabe que rompía la cámara frontal cada vez que estaba habilitada.

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

Bendito editor hexadecimal. El programa utilizado por Sultanxda.

Por lo tanto, necesitaba anular los símbolos utilizados por la cámara HAL y, en esencia, hacer que “falten” para que su Las cuñas proporcionarían esos símbolos "faltantes". La única manera de hacerlo es a través de edición hexadecimal de la propia cámara HAL. La edición hexadecimal consiste básicamente en buscar en un montón de galimatías desorganizadas 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 Edición hexadecimal de los nombres de los símbolos para anularlos..

Calce n.° 3: solución de fallas de luz brillante

A continuación, Sultanxda identificó que tomar una fotografía con la cámara frontal en condiciones de mucha iluminación provocaría que la cámara fallara. Para reproducir este error en su propio dispositivo, Sultanxda realmente Encendió la función de linterna de su OnePlus One y enfocó la luz frente a la cámara frontal del OnePlus 3T. para que falle y produzca registros utilizables. Una vez que descubrió qué función estaba causando el accidente, 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 solucionar el problema de la luz brillante con la corrección anterior, Sultanxda descubrió otro error que en realidad surgió como resultado directo de esa corrección: imágenes de cámara frontal de baja resolución. En lugar de tomar fotografías con la resolución solicitada por el usuario (p. ej. 16MP), la fotografía resultante se tomaría a 4MP.

Resolver esto requirió que calzara las funciones. handleSuperResolution y isSuperResolution para que siempre vuelva a ser verdadero, pero SÓLO cuando la cámara frontal esté activa (porque de lo contrario, la cámara fallaría al tomar fotografías desde el sensor trasero).


Lección aprendida: calzar puede ser difícil

Sultanxda admite que las calzas que tuvo que crear para que la cámara frontal del OnePlus 3T funcionara no representan el ejemplo típico de calza. Está bastante orgulloso de su calce dada su complejidad y la rara necesidad de editar el BLOB. Pero este ejemplo sólo sirve para mostrar lo difícil que puede ser hacer que el hardware de la cámara funcione en ciertos dispositivos.

Que tus aventuras con las cuñas de la cámara sean menos dolorosas que las mías. -Sultanxda

Registros, registros y más registros. Sin una forma coherente de reproducir un fallo y sin registros, los desarrolladores tienen pocas esperanzas de encontrar el origen 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 que arreglar la cámara en las ROM AOSP es una de las tareas más difíciles.

Si su dispositivo tiene una ROM AOSP portada con hardware en pleno funcionamiento, con suerte podrá comenzar a Aprecio la lucha por la que esos desarrolladores podrían haber pasado para traerte esos características. Apreciarlos por su trabajo, porque no es fácil. Es mucho trabajo que la gran mayoría de los usuarios ni siquiera notarán, ya que desarrolladores talentosos en nuestros foros se encargan de muchas partes invisibles de Android.

Nos gustaría agradecer especialmente a Sultanxda por las numerosas contribuciones que sugirió durante la realización de este artículo.