Android акселерометр не работает при выключенном экране - PullRequest
67 голосов
/ 02 апреля 2012

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

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

Так что происходит так: Когда вы регистрируете прослушиватель событий для датчика акселерометра Androidв Сервисе работает нормально, пока не выключится экран.Я уже пытался зарегистрировать eventListener на Сервисе, на IntentService, пытался получить 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)

  1. возможно ли иметь низкоуровневый доступ (подход C / C ++) к оборудованию акселерометра БЕЗ регистрации на приемнике событий?

  2. есть ли другой обходной путьили взломать?

  3. Может кто-нибудь с более современным телефоном любезно проверить, сохраняется ли проблема в прошивке 3.0 и выше?

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

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

Ответы [ 6 ]

65 голосов
/ 04 мая 2012

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

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

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

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

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

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

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

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

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

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

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

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

И тогда я получил ответ:

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

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

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

6 голосов
/ 09 июля 2013

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

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

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

Это на SGH-T589W, под управлением Android версии 2.3.6.

2 голосов
/ 21 ноября 2016

Я применил PARTIAL_WAKE_LOCK, и он мне понравился. Протестировано на ОС 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 для прогнозирования, который использует данные датчиков устройств (акселерометр / гироскоп) и прогнозирует пользовательские события. Я испытал ту же проблему.

2 голосов
/ 09 мая 2012

Я столкнулся с подобными проблемами с 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 только для тех устройств / ОС, которым это требуется.

0 голосов
/ 25 апреля 2014

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

Существует два варианта.

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

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

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

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

0 голосов
/ 02 мая 2012

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

...