화면이 꺼져있을 때 Android 가속도계가 작동하지 않음
컴퓨터 과학에 대한 최종 논문을위한 응용 프로그램을 개발 중이며 가속도계 데이터를 수집하고 기록해야합니다. 하루 종일 구입해야하므로 심각한 배터리 제약이 있습니다 (예 : 화면을 켜진 상태로 둘 수 없음). 또한 이것은 시장을 겨냥한 응용 프로그램이 아니므로 필요한 경우 심각한 해킹, 심지어 낮은 수준의 C / C ++ 코딩을 수행하는 것도 허용됩니다.
많은 기기에서 가속도계 이벤트에 대한 리스너가 화면이 꺼지면 이벤트 생성을 중지한다는 것은 잘 알려져 있습니다 (이 문제와 관련된 일부 링크 : http://code.google.com/p/android/issues/detail?id=3708 , Accelerometer WakeLock을 사용해도 Droid / Nexus One에서 화면이 꺼져 있으면 샘플 전달을 중지합니다 . 몇 가지 대안을 철저히 검색했으며 그중 일부에는 내 장치에서 작동하지 않는 해결 방법이 포함되어 있습니다 (LG P990, 재고 ROM).
결과는 다음과 같습니다. Android 가속도계 센서에 대한 이벤트 리스너를 서비스에 등록하면 화면이 꺼질 때까지 정상적으로 작동합니다. IntentService에서 서비스에 eventListener를 등록하려고 이미 시도했으며 WakeLocks를 획득하려고했습니다. wakelock과 관련하여 서비스가 LOGcat 출력을 보면서 여전히 실행 중인지 확인할 수 있지만 가속도계가 절전 모드로 전환 된 것 같습니다. 일부 링크에 제시된 해결 방법 중 하나는 아래 코드 스 니펫과 같이 IntentService의 스레드를 사용하여 주기적으로 이벤트 리스너를 등록 취소하고 다시 등록하는 것입니다.
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]);
}
실제로 리스너를 등록 취소 / 등록 할 때마다 onSensorChange가 호출됩니다. 문제는 수신 된 이벤트에 장치를 흔들어도 항상 동일한 값이 포함된다는 것입니다.
그래서, 기본적으로 내 질문은 다음과 같습니다. (참아주세요, 거의 마무리 중입니다 : P)
이벤트 리스너에 등록하지 않고 가속도계 하드웨어에 대한 낮은 수준의 액세스 (C / C ++ 접근 방식)를 가질 수 있습니까?
다른 해결 방법이나 해킹이 있습니까?
최신 전화를 가진 사람이 펌웨어 3.0 이상에서 문제가 지속되는지 친절하게 테스트 할 수 있습니까?
[최신 정보]
불행히도 일부 휴대폰의 버그 인 것 같습니다. 내 대답에 대한 자세한 내용.
기본적으로 내 휴대폰에 문제가 있습니다. 다른 사용자는 다른 브랜드이지만 동일한 Android 버전의 휴대 전화에서도 이런 일이 발생한다고보고했습니다. 다른 사람들은 전혀 문제가 없습니다. 이것은 안드로이드의 재고 버전이 아니라 하드웨어 드라이버에 대한 각 회사의 구현에 따른 문제임을 강력하게 나타냅니다.
I need constant accelerometer data delivered and cannot have a dongle measure this data for me - I have an Arduino with Bluetooth and accelerometer, so I could have implemented this solution. So I decided that the temporary solution for my cellphone was to let the screen on (dimmed) and ignore battery consumption. Later on I will perform the tests for battery usage using another android phone which works with the screen turned off.
More information about the bug
I've researched some more and found reports from other Android users and I think maybe I understand what is happening. The library libsensors.so which has the drivers for the phone sensors is not developed by Google but by each cellphone vendor - of course, because each cellphone has its own specific hardware. Google only provides a C header file so that the developers know what they have to implement. On some implementations for these drivers, the developers simply turn the accelerometer off when the screen goes off, thus preventing the sensor event listener to receive new events.
I also tested this with CyanogenMod RC7.2 but it did not work either, because accelerometer drivers are original from LG.
E-mails exchanged with HR department of LG
I sent an e-mail to the developers of the LG P990 and finally got some concrete answers! This may be of great help to some people like me that are experiencing these issues with Android. I wrote the following question
Hello! I am developing my thesis in computer science and currently I am fetching data from accelerometer hardware. As of now, I found out that the accelerometers do not send events when the screen is off, so even when I grab a wakelock from within one of my programs, I can verify that my program is still running (through LOGcat output) but no accelerometer event comes out. I have to dim my screen on (which I cannot afford, the battery drains too fast) to start receiving accelerometer events again. I also tried accessing it through native C code, registering on the accelerometer events but the result was the same, the accelerometer did not throw any values, even though I was rotating my device. So I was wondering if I could have direct access to the hardware, with native code, without having to register to a listener. Is this possible? If so, could you kindly give some further advice? I would appreciate very much any help! Martin
For what I received this response:
Dear Martin, We received the answer from Dev. Team. They said that you can’t get accelerometer event while your phone screen is off. Because HAL layer didn’t implement sysFS path to get H/W event such as accelerometer and there is no public API to get event. Thank you. Best Regards. (Sean Kim)
I then sent an e-mail back, saying among other things, that I considered this a bug, since one should have access to all the hardware when acquiring a wake lock:
[...] I asked this question because I have some friends that also have Android phones with the same gingerbread version but from other cellphone brands, and some of them reported they receive events from the accelerometers when the screen is turned off. I read on some forums that this bug - I consider it a bug, since when I acquire a Wakelock I would expect to have some processing going on - depends on the sensor drivers that the vendors implement for their cellphones. Is there any possibility that these drivers can be updated or will this bug be corrected at some point? This would help me enormously with my ongoing work [...]
And then I received this answer:
In my knowledge from Dev. Team, That isn’t bug. That is a limitless of this phone because of H/W architecture. We need to redesign the HAL architecture and device driver to support your request. But, as you know that is too difficult due to lack of resource. We are trying to help you with our all efforts but we cannot support your request as I mentioned. (Sean Kim)
So they apparently know about this but are not trying to correct this because either they don't think it is a bug - which I still strongly believe is a logical flaw - or they don't have the time/resources to correct it.
Bottom line If you have a cellphone that does not send accelerometer events with the screen off, try updating your firmware. If this does not solve and you really want to do some serious hacking, re implement your hardware layer - hint: it's probably something to do with libsensors.so.
I am not sure if this will actually assist you, but I have found a work around (Not sure how well if will help the battery saving though).
Using bash I have a while loop cat-ing /sys/devices/virtual/accelerometer/accelerometer/acc_file
, and when I turn off the screen via the power button the output continues, but is frozen. (I had sshd running in a chroot hence the being able to see it.)
However, in echoing 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness
. The screen turns off, and the output is continuous.
This is on a SGH-T589W, running android version 2.3.6.
I applied the PARTIAL_WAKE_LOCK and it worked like charm to me. Tested on OS 5.0, 6.0 & 7.0. Here's my code to acquire and release wake lock. Be careful it increased the battery drainage, so acquire and release it intelligently.
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
I am working on a prediction sdk, who use device sensors (accelerometer/gyroscope) data and predicts the user events. I experienced the same issue.
I've ran into similar problems with the Samsung Nexus running Android 4.0.2 using other system services that stop/pause while the screen is off even though a PARTIAL_WAKE_LOCK
is acquired. My solution was to use a SCREEN_DIM_WAKE_LOCK
as in:
lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);
It would be far better to have the screen fully off, but at least this solution works although it would be even better if I could limit using a SCREEN_DIM_WAKE_LOCK
to only those devices/OSes that require it.
I hate to disappoint you, but some devices just don't keep acceleromet on while they are in a sleep mode. Some do, others don't. You can check any pedometer weight loss app on store most of them explicitly state that this won't work on some devices.
If the partial wake lock option is not available for your phone it means the driver for the sensor has early_suspend
enabled.
There are two options.
1: Disable EARLY_SUSPEND
in the driver
2: Add a run time flag that can enable
/disable early_suspend
functionality at the driver level.
ex. cat /sys/module/earlysuspend/sensor 1/0
IMO the second option should have been there from the beginning.
'developer tip' 카테고리의 다른 글
'nice'에 해당하는 Windows (0) | 2020.11.12 |
---|---|
CMSPermGenSweepingEnabled 대 CMSClassUnloadingEnabled (0) | 2020.11.12 |
Subversion 작업 복사본에서 디렉토리 이름을 바꾸는 건전한 방법 (0) | 2020.11.12 |
인수 전달 전략-환경 변수 대 명령 줄 (0) | 2020.11.12 |
복사하지 않고 Numpy 배열 연결 (0) | 2020.11.12 |