Bueno, esto confirmó mi hipótesis de "si nadie en stackexchange sabe la respuesta, vas a tener que descubrirla tú mismo".
Así que lo hice.
La respuesta a esta pregunta es doble. Está el gestor de ventanas y el gestor de actividades, y ambos juegan un cierto papel en esto.
Aunque era tentador escribir un TL;DR en la parte superior aquí, no lo hice, porque especialmente con la segunda parte, tienes que ser muy cuidadoso con lo que estás haciendo, al menos por ahora.
Gestor de ventanas/Tareas recientes
Empecemos por el gestor de ventanas, ya que también será interesante para personas sin grandes cantidades de RAM. Además, es bastante más sencillo.
Funciona con una serie de variables: config_activeTaskDurationHours
así como una serie de NumVisibleRecentTasks
variables. config_activeTaskDurationHours
determina, como su nombre indica, el tiempo que una tarea se considera activa, es decir, relevante para el usuario. En mi dispositivo, esto se estableció en 6. Después de esas 6 horas, la "tarea" ya no aparece en la lista de aplicaciones recientes, con una excepción: el número de aplicaciones abiertas sería menor que, en mi caso, config_minNumVisibleRecentTasks
lanzador incluido. En ese caso, la aplicación no se descarta. Si el número de aplicaciones abiertas es igual a config_minNumVisibleRecentTasks
Sin embargo, en cuanto abres una aplicación que aún no está abierta, se descarta la aplicación abierta más antigua que no haya sido utilizada durante más de 6 horas.
También hay un par de otros ajustes relacionados que no eran relevantes en mi caso:
config_minNumVisibleRecentTasks_grid
: Esto es para cuando las aplicaciones se muestran en una cuadrícula. Sin embargo, esta vista no está disponible en muchas versiones de Android.
config_minNumVisibleRecentTasks_lowRam
: La misma configuración para los dispositivos con poca RAM.
config_maxNumVisibleRecentTasks
, config_maxNumVisibleRecentTasks_grid
y config_maxNumVisibleRecentTasks_lowRam
: estos son los límites máximos para el número de tareas recientes. En mi caso config_maxNumVisibleRecentTasks
se fijó en -1, lo que significa que no hay límite máximo.
Todos ellos son tomados de los recursos, y pueden ser modificados con GravityBox (Root y XPosed/EdExposed/LSPosed requeridos), bajo la sección de sintonía avanzada, en la sección de Framework. Requieren un reinicio para activar los cambios.
En mi caso, establecí ambos config_activeTaskDurationHours
y config_minNumVisibleRecentTasks
a un nivel ridículo: 5000. De este modo, se tarda más de medio año en tener la oportunidad de eliminar una tarea, y eso sólo si hay más de 5000 aplicaciones abiertas, lo que sospecho que nunca ocurrirá.
Gestor de la actividad/OomAdjuster
Esto fue un poco más difícil para mí, y tomó una buena cantidad de búsqueda a través del código fuente para encontrar la respuesta - aunque la respuesta puede no haber requerido realmente. Bueno, pues
Primero intenté escribir un módulo XPosed para anular com.android.server.am.ActivityManagerConstants
En concreto updateMaxCachedProcesses
. Desgraciadamente, no he conseguido que enganche bien el método, no sé por qué. Eso sí, nunca he intentado escribir un módulo XPosed antes, y lo hice con AIDE - tal vez algún día vuelva a desempaquetar Android Studio y lo intente allí. Pero si alguien quiere un control más fino, esto debería ofrecer una vía para hacerlo.
Al final, mi sospecha original de que se podría utilizar el límite de procesos en segundo plano de forma no oficial para aumentar el límite terminó siendo cierta. Efectivamente, si vas a la configuración del desarrollador y cambias el límite de procesos en segundo plano a, por ejemplo, 4, la salida de su -c dumpsys activity settings
se ve así al final:
mOverrideMaxCachedProcesses=4
CUR_MAX_CACHED_PROCESSES=4
CUR_MAX_EMPTY_PROCESSES=2
CUR_TRIM_EMPTY_PROCESSES=15
CUR_TRIM_CACHED_PROCESSES=10
Tenga en cuenta que los niveles de ajuste no se cambian, y la OMI no tiene sentido para cambiar esos niveles, incluso si el dispositivo tiene una gran cantidad de memoria RAM. Esencialmente, si los números de proceso están por debajo de los niveles de recorte, el sistema ni siquiera se molesta en recortar la memoria.
Entonces, ¿cómo podemos asignar un valor más alto? Aquí es donde las cosas se complican. He intentado llamar a ActivityManager.setProcessLimit()
con el permiso android.permission.SET_PROCESS_LIMIT
(que sólo está disponible para las aplicaciones del sistema, pero también se puede conceder a través de ADB) como se define en la interfaz IActivityManager, pero no pude conseguir que funcione (de nuevo, yo estaba trabajando con AIDE, por lo que puede ser el problema, puede que lo intente de nuevo en Android Studio más tarde).
Sin embargo, existe un comando de shell para Android poco conocido, service call
que esencialmente le permite llamar a un montón de métodos de diferentes interfaces de servicio, véase ¿Dónde encontrar información sobre el comando de shell "llamada de servicio" de Android? . Lo que se busca es el servicio de actividad, que se define en android.app.IActivityManager.aidl
y está buscando el método setProcessLimit(int max)
. Utilizando el terminal, podemos hacer service list
para obtener una lista de los servicios que se pueden llamar aquí. En mi caso, el nombre del servicio que estoy buscando era actividad. Luego, buscamos el setProcessLimit(int max)
en el código fuente. Como estoy razonablemente cerca de AOSP, puedo buscarlo allí. En mi caso, es el comando número 40.
ADVERTENCIA: Antes de mostrar lo que necesitaba para mi dispositivo, no sigas ciegamente esto . Esto es diferente para casi todas las versiones de Android, y si lo estropeas, podría causar problemas . Lee el enlace del párrafo anterior para estar seguro, al menos asegúrate de entender mi explicación en el párrafo anterior.
En mi caso, decidí ponerlo en algo ridículo, así que tomé el décuplo del valor original, 600. Eso lo convirtió en: service call activity 40 i32 600
(asegúrese de ejecutar su
antes de eso ya que esto necesita privilegios de Root). Ahora, cuando llamo a su -c dumpsys activity settings
La sección tiene el siguiente aspecto:
mOverrideMaxCachedProcesses=600
CUR_MAX_CACHED_PROCESSES=600
CUR_MAX_EMPTY_PROCESSES=300
CUR_TRIM_EMPTY_PROCESSES=15
CUR_TRIM_CACHED_PROCESSES=10
¡Aleluya! Lo hemos conseguido. Eso sí, según la información disponible, tendrás que repetir la service call
en cada reinicio, y si te metes con la configuración del límite de procesos en segundo plano en los ajustes del desarrollador, también perderás lo que acabas de establecer.
Tal vez algún día pruebe el enfoque con una aplicación Root/adb o un módulo XPosed de nuevo, y si lo hago, actualizaré esta respuesta. Pero por ahora, estoy contento con los resultados. El uso de la RAM es ahora más entre 5,5 y 6GB, en lugar de 4GB. Las aplicaciones parecen reiniciarse menos. La vida es mejor.