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

Estoy desarrollando una aplicación para mi tesis final sobre informática, y necesito recostackr y registrar datos de 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 orientada al mercado, por lo que es bastante aceptable realizar alguna piratería grave, incluso la encoding C / C ++ de bajo nivel, si es necesario.

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

Entonces, ¿qué sucede es esto? Cuando registra un detector de eventos para el sensor del acelerómetro Android en un servicio, funciona bien hasta que se apaga la pantalla. Ya he intentado registrar el eventListener en un servicio, en un servicio atento, intentado adquirir WakeLocks. En cuanto a wakelocks, puedo verificar que el servicio todavía se está ejecutando mirando la salida de LOGcat, pero parece que el acelerómetro está en modo de suspensión. Una de las soluciones provisionales presentadas en algunos de los enlaces es anular el registro y volver a registrar el detector de eventos periódicamente utilizando el hilo de un servicio de intención como en este fragmento de código abajo

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 se llame al onSensorChange cada vez que anulamos / registramos el oyente. El problema es que el evento recibido contiene siempre los mismos valores, independientemente de que yo agite el dispositivo.

Entonces, básicamente mis preguntas son: (aguantenme, casi termino: P)

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

  2. ¿Hay alguna otra solución o hackeo?

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

[ACTUALIZAR]

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

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

Necesito datos del acelerómetro constante entregados y no puedo tener un dongle para medir estos datos para 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 encendida la pantalla (atenuada) e ignorar el consumo de la 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 error

Investigué un poco más y encontré informes de otros usuarios de Android y creo que quizás entiendo lo que está sucediendo. La biblioteca libsensors.so que tiene los controladores para los sensores del teléfono no está desarrollada 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, lo que impide 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 informática y actualmente estoy obteniendo datos del hardware del acelerómetro. A partir de ahora, descubrí que los acelerómetros no envían eventos cuando la pantalla está apagada, por lo que incluso cuando tomo un wakelock desde uno de mis progtwigs, puedo verificar que mi progtwig todavía se está ejecutando (a través de la salida de LOGcat) pero no evento acelerómetro sale. Tengo que atenuar mi pantalla (que no me puedo permitir, la batería se agota demasiado rápido) para comenzar a recibir eventos de acelerómetro de nuevo. También intenté acceder a él a través del código C nativo, registrándome en los eventos del acelerómetro pero el resultado fue el mismo, el acelerómetro no arrojó ningún valor, a pesar de que estaba rotando mi dispositivo. Así que me preguntaba si podría tener acceso directo al hardware, con código nativo, sin tener que registrarme en un oyente. es posible? Si es así, ¿podría darnos algún consejo más? Apreciaría muchísima ayuda! Martín

Por lo que recibí esta respuesta:

Estimado Martin: Recibimos la respuesta de Dev. Equipo. Dijeron que no puedes obtener el evento del acelerómetro mientras la pantalla de tu teléfono está apagada. Debido a que la capa HAL no implementó la ruta sysFS para obtener eventos H / W como el acelerómetro y no hay una API pública para obtener el evento. Gracias. Atentamente. (Sean Kim)

Luego le devolví un correo electrónico, diciendo, entre otras cosas, que lo consideraba un error, ya que uno debería tener acceso a todo el hardware al adquirir un locking de activación:

[…] Hice esta pregunta porque tengo algunos amigos que también tienen teléfonos Android con la misma versión de gingerbread pero de otras marcas de teléfonos 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 que se procesara algo, depende de los controladores de sensor que los proveedores implementen para sus teléfonos celulares. ¿Hay alguna posibilidad de que estos controladores se puedan actualizar o corregirá este error en algún momento? Esto me ayudaría enormemente con mi trabajo continuo […]

Y luego recibí esta respuesta:

En mi conocimiento de Dev. Equipo, eso no es un error. Ese es un número ilimitado de este teléfono debido a la architecture H / W. Necesitamos rediseñar la architecture HAL y el controlador del dispositivo para respaldar su solicitud. Pero, como saben, es demasiado difícil debido a la falta de recursos. Estamos tratando de ayudarlo con todos nuestros esfuerzos, pero no podemos respaldar su solicitud como mencioné. (Sean Kim)

Por lo que aparentemente saben de esto, pero no intentan corregirlo porque o no creen que sea un error, que todavía creo que es un error lógico, o no tienen el tiempo o los recursos para corregirlo.

Conclusión Si tiene un teléfono celular que no envía eventos de acelerómetro con la pantalla apagada, intente actualizar su firmware. Si esto no se resuelve y realmente quieres hacer una piratería seria, vuelve a implementar tu capa de hardware – sugerencia: es probable que tenga algo que ver con libsensors.so.

No estoy seguro de si esto realmente te ayudará, pero he encontrado un trabajo alternativo (aunque no estoy seguro de qué tan bien ayudará a ahorrar batería).

Usando bash tengo un ciclo while cat -ing /sys/devices/virtual/accelerometer/accelerometer/acc_file , y cuando /sys/devices/virtual/accelerometer/accelerometer/acc_file la pantalla con el botón de encendido la salida continúa, pero se congela. (Tenía sshd corriendo en un chroot por lo tanto el ser capaz de verlo).

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

Esto está en un SGH-T589W, ejecutando la versión de Android 2.3.6.

Apliqué PARTIAL_WAKE_LOCK y funcionó como un 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 haya aumentado el drenaje de la batería, así que adquiera y libere 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 usa los datos de los sensores del dispositivo (acelerómetro / giroscopio) y predice los eventos del usuario. Experimenté el mismo problema.

Me encontré con problemas similares con el Samsung Nexus que ejecuta Android 4.0.2 utilizando otros servicios del sistema que se detienen / pausan mientras la pantalla está apagada a pesar de que se adquiere PARTIAL_WAKE_LOCK . Mi solución fue usar 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 SCREEN_DIM_WAKE_LOCK solo a aquellos dispositivos / sistemas operativos que lo requieran.

Odio decepcionarte, pero algunos dispositivos simplemente no mantienen el aceleromet mientras están en modo de suspensión. Algunos lo hacen, otros no. Puede consultar cualquier aplicación de pérdida de peso del podómetro en la tienda, la mayoría de ellos indica explícitamente que esto no funcionará en algunos dispositivos.

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

Hay dos opciones.

1: Desactivar EARLY_SUSPEND en el controlador

2: Agregue un indicador de tiempo de ejecución que puede enable / disable early_suspend funcionalidad disable early_suspend en el nivel del controlador.

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

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

    Intereting Posts