Акселерометр Android не работает, когда экран выключен

Я разрабатываю приложение для моего последнего тезиса по информатике, и мне нужно собирать и регистрировать данные акселерометра. Мне нужно приобрести его целый день, поэтому существуют серьезные ограничения батареи (например, я не могу оставить экран включенным). Кроме того, это не приложение, ориентированное на рынок, поэтому вполне допустимо совершать серьезные хакерские и даже низкоуровневые C/С++-коды, если это необходимо.

Хорошо известно, что на многих устройствах слушатели событий акселерометра прекращают генерировать события при выключении экрана (некоторые ссылки на эту проблему: http://code.google.com/p/android/issues/detail?id=3708, Акселерометр останавливает доставку образцов, когда экран выключен на Droid/Nexus One даже с WakeLock). Я тщательно искал некоторые альтернативы, некоторые из них включают обходные пути, которые не работают на моем устройстве (LG P990, складское ROM).

Итак, что происходит: Когда вы регистрируете прослушиватель событий для датчика акселерометра андроида в Сервисе, он работает нормально до тех пор, пока экран не будет отключен. Я уже пытался зарегистрировать eventListener на службе, в IntentService, попытался приобрести WakeLocks. Что касается wakelocks, я могу проверить, что служба все еще работает, наблюдая за выходом 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/С++) к аппарату акселерометра БЕЗ регистрации на прослушиватель событий?

  • Есть ли другой способ обхода или взлома?

  • может ли кто-нибудь с более современным телефоном пройти тест, если проблема не исчезнет в прошивке 3.0 и выше?

[ОБНОВЛЕНИЕ]

К сожалению, это похоже на ошибку с некоторыми сотовыми телефонами. Подробнее в моем ответе.

Ответ 1

В принципе, это проблема с моим телефоном. Другие пользователи сообщают, что это также происходит с их телефонами, от разных брендов, но с той же версией Android. У других людей нет никаких проблем - это убедительно указывает на то, что это не проблема с версией Android, но с реализацией каждой компании для их аппаратных драйверов.

Мне нужны данные постоянного акселерометра, и я не могу измерить эти данные для меня - у меня есть Arduino с Bluetooth и акселерометром, поэтому я мог бы реализовать это решение. Поэтому я решил, что временное решение для моего мобильного телефона должно позволить экрану (затемненному) и игнорировать потребление батареи. Позже я проведу тесты на использование батареи с помощью другого телефона Android, который работает с выключенным экраном.

Дополнительная информация об ошибке

Я исследовал еще несколько и нашел отчеты от других пользователей Android, и я думаю, может быть, я понимаю, что происходит. Библиотека libsensors.so, у которой есть драйверы для телефонных датчиков, не разработана Google, но каждым производителем мобильных телефонов - конечно, потому что у каждого сотового телефона есть свое специфическое оборудование. Google предоставляет только заголовочный файл C, чтобы разработчики знали, что им нужно реализовать. В некоторых вариантах реализации этих драйверов разработчики просто выключают акселерометр, когда экран выключается, тем самым предотвращая прием приемника событий датчика новыми событиями.

Я также тестировал это с помощью CyanogenMod RC7.2, но он тоже не работал, потому что драйверы акселерометра являются оригинальными от LG.

Электронные письма, обменянные с отделом HR LG

Я отправил электронное письмо разработчикам LG P990 и, наконец, получил некоторые конкретные ответы! Это может оказать большую помощь некоторым людям вроде меня, которые испытывают эти проблемы с Android. Я написал следующий вопрос

Здравствуйте! Я развиваю диссертацию по информатике, и в настоящее время я получение данных с аппаратуры акселерометра. На данный момент я узнал что акселерометры не отправляют события, когда экран выключен, поэтому даже когда я хватаю wakelock из одной из моих программ, я могу убедитесь, что моя программа все еще работает (через вывод LOGcat), но нет происходит акселерометр. Мне приходится тускнуть мой экран (что я не может позволить себе, батарея стекает слишком быстро), чтобы начать прием акселерометров. Я также попытался получить доступ к нему через собственный C код, регистрирующийся на событиях акселерометра, но результатом был То же самое, акселерометр не выдавал никаких значений, хотя я был поворачивая мое устройство. Поэтому мне было интересно, могу ли я иметь прямой доступ к аппаратным средствам, с собственным кодом, без необходимости регистрироваться на слушатель. Это возможно? Если да, не могли бы вы совет? Я бы очень признателен за любую помощь! Мартин

За что я получил этот ответ:

Дорогой Мартин, Мы получили ответ от Dev. Команда. Они сказали, что вы не можете получить акселерометр, когда экран телефона выключен. Потому как Уровень HAL не реализовал путь sysFS для получения H/W-события, такого как акселерометром, и нет никакого открытого API для получения события. Спасибо. Лучший С уважением. (Шон Ким)

Затем я отправил электронное письмо обратно, сказав, среди прочего, что я счел это ошибкой, так как у вас должен быть доступ ко всем аппаратным средствам при покупке блокировки слежения:

[...] Я задал этот вопрос, потому что у меня есть друзья, которые также Android-телефоны с той же версией имбирных пряников, но из других бренды мобильных телефонов, и некоторые из них сообщили, что они получают события от акселерометры, когда экран выключен. Я читал о некоторых форумы, что эта ошибка - я считаю это ошибкой, поскольку, когда я приобретаю Wakelock, я ожидал бы, что обработка будет продолжаться - зависит от драйверы датчиков, которые производители реализуют для своих мобильных телефонов. Является есть вероятность, что эти драйверы могут быть обновлены или это будет ошибка будет исправлена ​​в какой-то момент? Это очень помогло бы мне с моей текущая работа [...]

И затем я получил этот ответ:

В моих знаниях от Dev. Команда, это не ошибка. Это безгранично этот телефон из-за архитектуры H/W. Нам нужно перепроектировать HAL архитектуру и драйвер устройства для поддержки вашего запроса. Но, как вы знаю, что это слишком сложно из-за нехватки ресурсов. Мы пытаемся помогите вам всеми нашими усилиями, но мы не можем поддержать ваш запрос, поскольку я упоминается. (Шон Ким)

Таким образом, они, очевидно, знают об этом, но не пытаются исправить это, потому что либо они не считают, что это ошибка, - я все еще верю, что это логический недостаток - или у них нет времени/ресурсов для исправления он.

Нижняя строка Если у вас есть мобильный телефон, который не отправляет события акселерометра с выключенным экраном, попробуйте обновить прошивку. Если это не решит, и вы действительно хотите сделать серьезный взлом, повторите свой аппаратный уровень - подскажите: возможно, это что-то связано с libsensors.so.

Ответ 2

Я не уверен, что это действительно поможет вам, но я нашел работу (не уверен, насколько хорошо, если это поможет сохранить батарею).

Использование bash У меня есть цикл while cat /sys/devices/virtual/accelerometer/accelerometer/acc_file, и когда я выключаю экран с помощью кнопки питания, выход продолжается, но заморожен. (У меня было sshd, работающее в chroot, следовательно, возможность видеть его.)

Однако, эхом 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness. Экран выключится, и выход будет непрерывным.

Это версия SGH-T589W, версия 2.3.6 для Android.

Ответ 3

Я столкнулся с аналогичными проблемами с Samsung Nexus под управлением Android 4.0.2, используя другие системные службы, которые останавливают/приостанавливают пока экран выключен, даже если приобретен PARTIAL_WAKE_LOCK. Моим решением было использовать SCREEN_DIM_WAKE_LOCK, как в:

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

Было бы намного лучше отключить экран, но по крайней мере это решение работает, хотя было бы еще лучше, если бы я мог ограничить использование SCREEN_DIM_WAKE_LOCK только теми устройствами/операционными системами, которые этого требуют.

Ответ 4

Я применил PARTIAL_WAKE_LOCK, и он работал как прелесть для меня. Протестировано на OS 5.0, 6.0 и 7.0. Здесь мой код, чтобы приобрести и разблокировать блокировку. Будьте осторожны, это увеличивает дренаж батареи, поэтому приобретайте и освобождайте его разумно.

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;
    }
}

Ссылка: https://developer.android.com/training/scheduling/wakelock.html#cpu

Я работаю над предсказанием sdk, который использует данные датчиков устройства (акселерометр/гироскоп) и прогнозирует пользовательские события. Я испытал ту же проблему.

Ответ 5

Я ненавижу вас разочаровывать, но некоторые устройства просто не поддерживают акселерометр, когда находятся в спящем режиме. Некоторые делают, другие - нет. Вы можете проверить любое приложение для снижения веса шагомера в магазине, большинство из которых явно указывают, что это не будет работать на некоторых устройствах.

Ответ 6

Если опция частичного блокирования следа недоступна для вашего телефона, это означает, что драйвер для датчика имеет early_suspend.

Есть два варианта.

1: отключить early_suspend в драйвере

2: добавьте флаг времени выполнения, который может enable/disable early_suspend работать на уровне драйвера.

ех. cat/sys/module/earlysuspend/sensor 1/0

ИМО второй вариант должен был быть с самого начала.