El acelerómetro Android no funciona cuando la pantalla está apagada


Estoy desarrollando una aplicación para mi tesis final en ciencias de la computación, y necesito recopilar y registrar los datos del acelerómetro. Necesito adquirirlo durante todo un día, por lo que hay serias limitaciones de batería (por ejemplo, no puedo dejar la pantalla encendida). Además, esta no es una aplicación dirigida al mercado, por lo que es bastante aceptable hacer algo de piratería grave, incluso codificación C/C++ de bajo nivel, si es necesario.

Es bien sabido que en muchos dispositivos los oyentes de los eventos del acelerómetro se detienen generar eventos cuando la pantalla se apaga (algunos enlaces con respecto a este problema: http://code.google.com/p/android/issues/detail?id=3708 , El acelerómetro deja de entregar muestras cuando la pantalla está apagada en Droid / Nexus One incluso con un WakeLock ). He buscado a fondo algunas alternativas, algunas de ellas incluyen soluciones que no funcionan para mi dispositivo (LG P990, stock ROM).

Así que lo que sucede es esto: Cuando registras un detector de eventos para el sensor acelerómetro android en un Servicio, funciona bien hasta que la pantalla se apaga. Ya he intentado registrar el EventListener en un Servicio, en un IntentService, intenté adquirir WakeLocks. Con respecto a wakelocks, puedo verificar que el servicio todavía se está ejecutando viendo la salida de LOGcat, pero parece que el acelerómetro se pone en modo de suspensión. Una de las soluciones presentadas en algunos de los enlaces es anular el registro y volver a registrar el receptor de eventos periódicamente utilizando el hilo de un IntentService como en este código fragmento de código siguiente

synchronized private static PowerManager.WakeLock getLock(Context context) {
    if (lockStatic==null) {
        PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);

        lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME);
        lockStatic.setReferenceCounted(true);
    }

    return(lockStatic);
}

@Override
protected void onHandleIntent(Intent intent) {

     sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
     sensorManager.unregisterListener(this);
     sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);


    synchronized (this) {
        boolean run = true;
        while (run){
            try {
                wait(1000);
                getLock(AccelerometerService.this).acquire();
                sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
                sensorManager.unregisterListener(this);
                sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
                Log.d("Accelerometer service", "tick!");

            } catch (Exception e) {
                run = false;
                Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage());


            }
        }
    }       
}


@Override
public void onSensorChanged(SensorEvent event) {
    Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," +  event.values[2]);
}

Que de hecho hace que elangeensorchange sea llamado cada vez que desregistramos/registramos el oyente. El problema es que el evento recibido contiene siempre los mismos valores, independientemente de mí sacudiendo el dispositivo.

Entonces, básicamente mis preguntas son: (tengan paciencia conmigo, estoy casi terminando: P)

  1. ¿Es posible tener acceso de bajo nivel (enfoque C/C++) al hardware del acelerómetro SIN registrarse en un evento oyente?

  2. ¿hay alguna otra solución o hack?

  3. ¿Podría alguien con un teléfono más actualizado probar amablemente si el problema persiste en el firmware 3.0 y superior?

[ACTUALIZACIÓN]

Desafortunadamente, parece ser un error con algunos teléfonos celulares. Más detalles en mi respuesta.

Author: Community, 2012-04-02

6 answers

Básicamente, es un problema con mi teléfono. Otros usuarios han informado de que esto también sucede con sus teléfonos, de diferentes marcas, pero la misma versión de Android. Otras personas no tienen ningún problema en absoluto, lo que indica claramente que esto no es un problema con la versión de stock de Android, sino de las implementaciones de cada empresa para sus controladores de hardware.

Necesito datos constantes del acelerómetro entregados y no puedo tener un dongle medir estos datos por mí-tengo un Arduino con Bluetooth y acelerómetro, así que podría haber implementado esta solución. Así que decidí que la solución temporal para mi teléfono celular era dejar la pantalla encendida (atenuada) e ignorar el consumo de batería. Más tarde realizaré las pruebas para el uso de la batería usando otro teléfono Android que funciona con la pantalla apagada.

Más información sobre el bug

He investigado un poco más y encontrado informes de otros usuarios de Android y creo que tal vez entiendo lo que está sucediendo. Biblioteca libsensors.so que tiene los controladores para los sensores del teléfono no es desarrollado por Google, sino por cada proveedor de teléfonos celulares - por supuesto, porque cada teléfono celular tiene su propio hardware específico. Google solo proporciona un archivo de encabezado C para que los desarrolladores sepan lo que tienen que implementar. En algunas implementaciones para estos controladores, los desarrolladores simplemente apagan el acelerómetro cuando la pantalla se apaga, evitando así que el detector de eventos del sensor reciba nuevos eventos.

También probé esto con CyanogenMod RC7.2 pero tampoco funcionó, porque los controladores del acelerómetro son originales de LG.

Correos electrónicos intercambiados con el departamento de Recursos humanos de LG

Envié un correo electrónico a los desarrolladores del LG P990 y finalmente obtuve algunas respuestas concretas! Esto puede ser de gran ayuda para algunas personas como yo que están experimentando estos problemas con Android. Escribí la siguiente pregunta

¡Hola! Estoy desarrollando mi tesis en ciencias de la computación y actualmente estoy obteniendo datos del hardware del acelerómetro. A partir de ahora, me enteré que los acelerómetros no envían eventos cuando la pantalla está apagada, por lo que incluso cuando agarro un wakelock desde uno de mis programas, puedo compruebe que mi programa todavía se está ejecutando (a través de la salida de LOGcat), pero no el evento del acelerómetro sale. Tengo que atenuar mi pantalla en (que I no puede permitirse, la batería se agota demasiado rápido) para comenzar a recibir acelerómetro eventos de nuevo. También intenté acceder a él a través de C nativo código, registrándose en el acelerómetro pero el resultado fue el mismo, el acelerómetro no arrojó ningún valor, a pesar de que estaba girando mi dispositivo. Así que me preguntaba si podría tener acceso directo al hardware, con código nativo, sin tener que registrarse oyente. Es esto posible? Si es así, podría usted amablemente dar algo más ¿consejo? Le agradecería mucho cualquier ayuda! Martin

Por lo que recibí esta respuesta:

Querido Martin, recibimos la respuesta de Dev. Equipo. Dijeron que tú no se puede obtener el evento del acelerómetro mientras la pantalla del teléfono está apagada. Porque La capa HAL no implementó la ruta sysFS para obtener eventos H / W como acelerómetro y no hay API pública para obtener evento. Agradecer. Mejor Respecto. (Sean Kim)

Luego envié un correo electrónico de vuelta, diciendo entre otras cosas, que consideré esto un error, ya que uno debería tener acceso a todo el hardware al adquirir un wake lock:

[... Hice esta pregunta porque Tengo algunos amigos que también tienen Teléfonos Android con la misma versión de pan de jengibre, pero de otros marcas de celulares, y algunos de ellos informaron que reciben eventos de los acelerómetros cuando la pantalla está apagada. Leí en algunos foros que este error-lo considero un error, ya que cuando adquiera un Wakelock esperaría tener algún proceso en marcha-depende de los controladores de sensores que los proveedores implementan para sus teléfonos celulares. Ser existe la posibilidad de que estos controladores se puede actualizar o se error ser corregido en algún momento? Esto me ayudaría enormemente con mi labor en curso [...]

Y entonces recibí esta respuesta:

En mi conocimiento de Dev. Equipo, Eso no es Bug. Eso es un ilimitado de este teléfono debido a la arquitectura H / N. Tenemos que rediseñar el HAL arquitectura y controlador de dispositivo para respaldar su solicitud. Pero, como tú saber que es demasiado difícil debido a la falta de recursos. Estamos tratando de ayudarle con nuestro todo esfuerzos, pero no podemos apoyar su solicitud ya que indicado. (Sean Kim)

Así que aparentemente saben acerca de esto, pero no están tratando de corregirlo porque o bien no piensan que es un error - que todavía creo firmemente que es un defecto lógico - o no tienen el tiempo/recursos para corregirlo.

Bottom line Si tiene un teléfono celular que no envía eventos del acelerómetro con la pantalla apagada, intente actualizar su firmware. Si esto no resuelve y realmente quieres para hacer algo de hacking serio, re implementar su capa de hardware-sugerencia: es probablemente algo que ver con libsensors.so.

 62
Author: martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-07 22:12:55

No estoy seguro de si esto realmente le ayudará, pero he encontrado un trabajo alrededor (No estoy seguro de lo bien que ayudará a ahorrar batería).

Usando bash tengo un bucle while cat-ing /sys/devices/virtual/accelerometer/accelerometer/acc_file, y cuando apago la pantalla a través del botón de encendido la salida continúa, pero se congela. (Tenía sshd corriendo en un chroot de ahí el poder verlo.)

Sin embargo, haciendo eco de 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness. La pantalla se apaga y la salida es continua.

Esto es en un SGH-T589W, ejecutando android versión 2.3.6.

 6
Author: fu-fu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-07 22:14:03

Apliqué el PARTIAL_WAKE_LOCK y funcionó como encanto para mí. Probado en OS 5.0, 6.0 y 7.0. Aquí está mi código para adquirir y liberar wake Lock. Tenga cuidado de que aumentó el drenaje de la batería, por lo que adquirir y liberar de forma inteligente.

public void acquireWakeLock() {
    final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    releaseWakeLock();
    //Acquire new wake lock
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
    mWakeLock.acquire();
}

public void releaseWakeLock() {
    if (mWakeLock != null && mWakeLock.isHeld()) {
        mWakeLock.release();
        mWakeLock = null;
    }
}

Ref: https://developer.android.com/training/scheduling/wakelock.html#cpu

Estoy trabajando en un sdk de predicción, que utilizan los datos de los sensores del dispositivo (acelerómetro/giroscopio) y predice los eventos del usuario. Experimenté el mismo problema.

 2
Author: Farhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-21 09:10:15

Me he encontrado con problemas similares con el Samsung Nexus corriendo Android 4.0.2 usando otros servicios del sistema que se detienen/pausan mientras la pantalla está apagada a pesar de que se adquiere un PARTIAL_WAKE_LOCK. Mi solución fue usar un SCREEN_DIM_WAKE_LOCK como en:

 lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);

Sería mucho mejor tener la pantalla completamente apagada, pero al menos esta solución funciona, aunque sería aún mejor si pudiera limitar el uso de un SCREEN_DIM_WAKE_LOCK a solo aquellos dispositivos/sistemas operativos que lo requieran.

 2
Author: Greg Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-28 02:35:40

Odio decepcionarte, pero algunos dispositivos simplemente no mantienen acceleromet encendido mientras están en modo de suspensión. Puede comprobar cualquier aplicación de pérdida de peso podómetro en la tienda la mayoría de ellos declaran explícitamente que esto no funcionará en algunos dispositivos.

 0
Author: EvilDuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-02 08:38:38

Si la opción de bloqueo de activación parcial no está disponible para su teléfono, significa que el controlador para el sensor tiene early_suspend activado.

Hay dos opciones.

1: Desactivar EARLY_SUSPEND en el controlador

2: Agregue un indicador de tiempo de ejecución que pueda enable/disable early_suspend funcionalidad a nivel de conductor.

Ex. cat / sys / module/earlysuspend / sensor 1/0

IMO la segunda opción debería haber estado allí desde el principio.

 0
Author: boosth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-28 02:36:31