Проблема
Я занимаюсь разработкой для Android уже довольно давно. Одна из разработанных мной программ активно использует WakeLocks. . Обычно все отлично (часто днями или неделями, требование программы), но очень редко я замечаю странное поведение в этом коде:
acquireWakeLock(wakeLockManager)
// Preconditions
assertFalse("Wake lock already acquired.", hasWakeLock());
assertNotNull("Wake lock manager not provided.", wakeLockManager);
// Acquire a wake lock.
wakeLock = wakeLockManager.newPartialWakeLock(DEBUG_TAG);
wakeLock.acquire();
// Postconditions
assertTrue("Wake Lock should be held!", hasWakeLock());
Где hasWakeLock()
просто возвращает результат (wakeLock != null && wakeLock.isHeld())
, а wakeLockManager.newPartialWakeLock(DEBUG_TAG)
инкапсулирует стандартный код «получить PowerManager, а затем вернуть блокировку пробуждения». В целях тестирования операторы assert являются методами JUnit assert, поэтому я думаю, что мы можем предположить, что они верны.
Проблема с кодом заключается в следующем: последнее утверждение — assertTrue(hasWakeLock())
— кажется, терпит неудачу каждые несколько недель с очень небольшим объяснением. Это означает, что у меня есть три возможных проблемы: (1) блокировка пробуждения вообще никогда не извлекается из PowerManager (2) что у меня есть проблема параллелизма, которая в редких случаях вступает в силу непосредственно перед постусловием, но после вызова acquire()
, или что (3) acquire()
иногда неисправен.
Исследование проблемы
Как указано выше, у меня есть три потенциальных проблемы, которые могут возникнуть, которые я расследую/расследовал:
Гипотеза 1: блокировка пробуждения не возвращена:
Если бы это было так, я бы увидел исключение нулевого указателя. Этого не может быть.
Гипотеза 2. У меня проблема с параллелизмом:
Только что проведенная официальная проверка всех мест, участвующих в приобретении и выпуске wakeLock
убедительно заставляет меня поверить, что это не так. В случае, если мое доказательство ошибочно, у меня может возникнуть проблема параллелизма, но тогда она действительно коварна и ее трудно найти.
Гипотеза 3. WakeLock.acquire() неисправен и несмотря на то, что говорится в документации, иногда может не получиться блокировка:
Мне не нравится эта гипотеза, потому что со всеми пользователями Android наш кто-то помимо меня, должно быть, уже заметил это, и почти всегда это код разработчика, а не код библиотеки или ОС, который ошибочен. С другой стороны, произошли более странные вещи, и это может быть настоящей ошибкой Android, хотя и редко проявляющейся. Если эта гипотеза верна, то функцияAcquire() просто не получает блокировку пробуждения, и это объясняет поведение, которое я наблюдаю.
Итак, StackOverflow, что может быть причиной этой проблемы? Как вы думаете, что не так? Я упускаю что-то очевидное, или это может быть настоящая проблема с блокировкой пробуждения Android?