Cambios de comportamiento: todas las apps

La plataforma de Android Q incluye cambios de comportamiento que podrían afectar a tu app. Los siguientes cambios de comportamiento se aplican a todas las apps que se ejecuten en Android Q, sin importar su "targetSdkVersion". Debes probar tu app y, luego, modificarla según corresponda para admitir estos cambios.

Asegúrate también de revisar la lista de cambios de comportamiento que solo afectan a las apps orientadas a Android Q.

Restricciones en interfaces no SDK

Para asegurar la estabilidad y compatibilidad de las apps, la plataforma comenzó a restringir las interfaces no SDK que tu app puede usar en Android 9 (con nivel de API 28). Android Q incluye listas actualizadas de interfaces no SDK restringidas, basadas en la colaboración con desarrolladores de Android y las pruebas internas más recientes. Nuestro objetivo es asegurarnos de que las alternativas públicas estén disponibles antes de restringir las interfaces que no pertenecen al SDK.

Si no orientarás tu app a Android Q, es posible que no te afecten de inmediato algunos de estos cambios. Sin embargo, aunque actualmente puedes usar interfaces no SDK de lista gris (según el nivel de API objetivo), usar cualquier método o campo no SDK siempre implica un gran riesgo de error para tu app.

Si no sabes con seguridad si tu app usa interfaces no SDK, puedes probarla para verificar. Si tu app depende de interfaces no SDK, deberías empezar a planificar una migración hacia otras alternativas SDK. No obstante, sabemos que algunas apps tienen casos prácticos válidos para usar interfaces que no pertenecen al SDK. Si no puedes encontrar una alternativa al uso de una interfaz que no pertenece al SDK para una función de tu app, deberías solicitar una nueva API pública.

Para obtener más información, consulta las actualizaciones de restricciones de interfaces que no pertenecen al SDK para Android Q y las restricciones para interfaces que no pertenecen al SDK.

NDK

En Android Q, se incluyen los siguientes cambios de NDK.

Los objetos compartidos no pueden contener reubicaciones de texto

En Android 6.0 (nivel de API 23) no está permitido el uso de reubicaciones de texto en objetos compartidos. El código se debe cargar sin modificaciones. Este cambio mejora la seguridad y los tiempos de carga de la app.

En la versiones Beta 1 y 2 de Android Q, SELinux aplica esta restricción en las apps orientadas a Android 8.0 (nivel de API 26) y versiones posteriores. Si estas apps continúan usando objetos compartidos que contienen reubicaciones de texto, tienen alto riesgo de dañarse.

Bibliotecas y objetos binarios del sistema asignados a memoria de solo ejecución

A partir de Android Q, los segmentos ejecutables de bibliotecas y objetos binarios del sistema se asignan a memoria de solo ejecución (no de lectura) como técnica de refuerzo contra los ataques de reutilización de código. Las lecturas intencionales y no intencionales de los segmentos de memoria identificados como de solo ejecución devolverán un SIGSEGV, ya sea por un error, una vulnerabilidad o una introspección intencional de la memoria.

Para identificar si una falla fue producto de este cambio, examina el archivo de exclusión relacionado en /data/tombstones/. Un error de solo ejecución incluirá el siguiente mensaje de anulación:

    Cause: execute-only (no-read) memory access error; likely due to data in .text.
    

Para solucionar este problema, los desarrolladores pueden identificar los segmentos de solo ejecución como lectura+ejecución si llaman a mprotect(), por ejemplo, a fin de realizar una inspección de la memoria. Sin embargo, recomendamos revertir la configuración a "solo de ejecución" una vez que termines, ya que esto brinda más protección para tu app y los usuarios.

Como las llamadas a ptrace no se ven afectadas, la depuración de ptrace tampoco.

Seguridad

En Android Q, se incluyó el siguiente cambio de seguridad:

Se quitó el permiso de ejecución para el directorio principal de la app

Las aplicaciones no confiables que se orientan a Android Q ya no pueden invocar a exec() en archivos dentro del directorio principal de la app. Esta ejecución de archivos desde el directorio principal de la app que admite escritura es una infracción de W^X. Las aplicaciones deben cargar solo el código binario incorporado en el archivo APK de una app.

Además, las apps que se orientan a Android Q no pueden modificar el código ejecutable de memoria desde archivos que se abrieron con dlopen(), incluido cualquier archivo de objeto (.so) compartido con reubicaciones de texto.

Transmisiones por Wi-Fi directo

En Android Q, las siguientes transmisiones relacionadas con Wi-Fi directo ya no son fijas.

Si tu app dependía de la recepción de estas transmisiones en el registro debido a que eran fijas, en su lugar, usa el método get() apropiado en la inicialización para obtener la información.

Capacidades de reconocimiento de Wi-Fi

En Android Q, se agregó compatibilidad para facilitar la creación de un Socket TCP/UDP mediante rutas de acceso a datos de reconocimiento de Wi-Fi. Para crear un socket TCP/UDP que se conecte a ServerSocket, el dispositivo del cliente debe conocer la dirección IPv6 y el puerto del servidor. Anteriormente, este debía comunicarse por fuera de la banda (por ejemplo, por medio de mensajería de nivel 2 a través de Bluetooth o reconocimiento de Wi-Fi) o detectarse dentro de la banda mediante otros protocolos (por ejemplo, mDNS). Con Android Q, la información se puede transmitir como parte de la configuración de red.

El servidor puede realizar cualquiera de las siguientes acciones:

  • Inicializar un ServerSocket y obtener o configurar el puerto que se usará
  • Especificar la información del puerto como parte de la solicitud de red de reconocimiento de Wi-Fi

En la siguiente muestra de código, se indica cómo especificar la información del puerto como parte de la solicitud de red:

Kotlin

    val ss = ServerSocket()
    val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
      .setPskPassphrase("some-password")
      .setPort(ss.localPort)
      .build()

    val myNetworkRequest = NetworkRequest.Builder()
      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
      .setNetworkSpecifier(ns)
      .build()
    

Java

    ServerSocket ss = new ServerSocket();
    WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
      .Builder(discoverySession, peerHandle)
      .setPskPassphrase(“some-password”)
      .setPort(ss.getLocalPort())
      .build();

    NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
      .setNetworkSpecifier(ns)
      .build();
    

Luego, el cliente realiza una solicitud de red de reconocimiento de Wi-Fi para obtener la dirección IPV6 y el puerto que proporciona el servidor:

Kotlin


    val callback = object : ConnectivityManager.NetworkCallback() {
      override fun onAvailable(network: Network) {
        ...
      }

      override fun onLinkPropertiesChanged(network: Network,
          linkProperties: LinkProperties) {
        ...
      }

      override fun onCapabilitiesChanged(network: Network,
          networkCapabilities: NetworkCapabilities) {
        ...
        val ti = networkCapabilities.transportInfo
        if (ti is WifiAwareNetworkInfo) {
           val peerAddress = ti.peerIpv6Addr
           val peerPort = ti.port
        }
      }
      override fun onLost(network: Network) {
        ...
      }
    };

    connMgr.requestNetwork(networkRequest, callback)
    

Java

    callback = new ConnectivityManager.NetworkCallback() {
      @Override
      public void onAvailable(Network network) {
        ...
      }
      @Override
      public void onLinkPropertiesChanged(Network network,
          LinkProperties linkProperties) {
        ...
      }
      @Override
      Public void onCapabilitiesChanged(Network network,
          NetworkCapabilities networkCapabilities) {
        ...
        TransportInfo ti = networkCapabilities.getTransportInfo();
        if (ti instanceof WifiAwareNetworkInfo) {
           WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
           Inet6Address peerAddress = info.getPeerIpv6Addr();
           int peerPort = info.getPort();
        }
      }
      @Override
      public void onLost(Network network) {
        ...
      }
    };

    connMgr.requestNetwork(networkRequest, callback);
    

SYSTEM_ALERT_WINDOW en dispositivos Go

Las apps que se ejecutan en dispositivos con Android Q (edición Go) no pueden tener el permiso SYSTEM_ALERT_WINDOW. Esto se debe a que el procesamiento de ventanas superpuestas usa demasiada memoria, lo que es particularmente dañino para el rendimiento de los dispositivos Android con poca memoria.

Si una app que se ejecuta en un dispositivo Go con Android 9 o versiones inferiores recibe el permiso SYSTEM_ALERT_WINDOW, la app retiene el permiso incluso si el dispositivo se actualiza a Android Q. Sin embargo, las apps que todavía no tengan el permiso no podrán obtenerlo una vez que se actualice el dispositivo.

Si una app en un dispositivo Go envía un intent con la acción ACTION_MANAGE_OVERLAY_PERMISSION, el sistema deniega automáticamente la solicitud y dirige al usuario a una pantalla de Configuración que indica que se denegó el permiso porque ralentiza el dispositivo. Si una app en un dispositivo Go invoca el método Settings.canDrawOverlays(), este siempre mostrará un resultado falso. Estas restricciones tampoco se aplican a apps que recibieron el permiso SYSTEM_ALERT_WINDOW antes de que el dispositivo se actualizara a Q.

Advertencias para las apps orientadas a versiones anteriores de Android

En Android Q, la plataforma advertirá a los usuarios la primera vez que ejecuten cualquier app orientada a una versión de plataforma anterior a Android 6.0 (con nivel de API 23). Si la app requiere que el usuario otorgue permisos, este tendrá la oportunidad de ajustar los permisos de esa app antes de permitir que se ejecute por primera vez.

Debido a los requisitos del nivel de API objetivo de Google Play, un usuario solo verá estas advertencias si ejecuta una app que no se actualizó recientemente. En el caso de apps que se distribuyen en otras tiendas, también se introducirán requisitos similares para el nivel de API objetivo en 2019. Para obtener más información sobre estos requisitos, consulta cómo Expandir los requisitos del nivel de API objetivo en 2019.

Eliminación de conjuntos de cifrado SHA-2 CBC

Se quitaron de la plataforma los siguientes conjuntos de cifrado SHA-2 CBC:

  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

Estos conjuntos de cifrado son menos seguros que otros similares que usan GCM y la mayoría de los servidores admite las dos variantes (GCM y CBC) o no admite ninguna.

Uso de apps

Android Q presenta los siguientes cambios de comportamiento relacionados con el uso de apps:

  • Mejoras de uso de la app UsageStats: Android Q ahora supervisa correctamente el uso de la app mediante UsageStats cuando las apps se emplean en los modos de pantalla dividida o pantalla en pantalla. Además, Android Q ahora puede supervisar el uso de apps instantáneas.

  • Escala de grises por app: Android Q ahora permite configurar el modo de visualización de las apps en escala de grises.

  • Estado de distracción por app: Cuando las notificaciones de las apps están suprimidas y no se muestran como apps sugeridas, Android Q ahora puede configurar las apps en un "estado de distracción" de manera selectiva.

  • Suspensión y reproducción: En Android Q, las apps suspendidas ya no pueden reproducir audio.

La biblioteca android.preference dejó de estar disponible

La biblioteca android.preference dejó de estar disponible. En su lugar, los desarrolladores deben usar la biblioteca de preferencia de AndroidX, que forma parte de Android Jetpack. Para obtener recursos adicionales de ayuda durante la migración y el desarrollo, consulta la Guía de configuración actualizada, nuestra app de ejemplo pública y la documentación de referencia.

Cambios en la cámara

Muchas apps que usan la cámara asumen que, si el dispositivo está configurado verticalmente, entonces el dispositivo físico también tiene orientación vertical, como se describe en la orientación de la cámara. Esta suposición solía ser cierta, pero con la introducción de nuevos factores de forma, como los dispositivos plegables, ya no se aplica, porque podría llevar a que el visor de la cámara se ajuste o rote (o ambas cosas) incorrectamente.

Las apps que se orientan al nivel de API 24 o a uno superior deberían establecer android:resizeableActivity de forma explícita y proporcionar la funcionalidad necesaria para controlar operaciones multiventana.

Seguimiento del uso de batería

A partir de Android Q, SystemHealthManager restablece las estadísticas de uso de batería cada vez que el dispositivo se desconecta luego de un evento de carga importante. En términos generales, un evento de carga importante puede ser que el dispositivo se cargó completamente o que pasó de tener muy poca carga a tenerla casi completa.

En versiones anteriores a Android Q, las estadísticas de uso de batería se restablecían cada vez que el dispositivo se desconectaba, independientemente del cambio en el nivel de la batería.