42

Tengo una pregunta sobre wakelock. En los casos que se muestran a continuación, ¿el sistema operativo Android libera wakelock (PARTIAL_WAKE_LOCK si necesita especificarlo) para evitar que se haya adquirido el wakelock y el desperdicio de la batería hasta apagarlo (no dormir).¿Libera el sistema operativo Android un wakelock si la aplicación o servicio que lo contiene se elimina?

Caso 1-a:
aplicación ha adquirido wakelock (w/opción de tiempo de espera o) en uno de sus hilos (por favor, creo que es razonable en este caso) y que fue diseñada para liberar wakelock cuando la tarea fundamental era terminado. La aplicación puede ser eliminada por el taskmanager o el famoso taskkiller, y la aplicación no tiene posibilidad de permitir que su hilo libere wakelock. ¿Qué pasa con ese wakelock?

Caso 1-b:
(. Si la respuesta a la sentencia de 1-a es "Sí, no se preocupe", a continuación, por favor, ignora este caso) Igual que el caso 1-A, pero dio la opción de aplicación de tiempo de espera a wakelock, digamos 3 segundos. ¿Esta opción de tiempo de espera se mantiene válida?

Caso 2-a:
favor imaginen que hay un servicio que fue iniciado por AlarmManager (a través del receptor de difusión) y el servicio ha adquirido una wakelock (w/opción de tiempo de espera o). Este servicio está diseñado para hacer un mínimo de tiempo adquirido por wakelock. Pero, por desgracia, Android OS eligió este servicio para matar debido a la crisis de memoria. (No sé si OS no matará al servicio cuando se adquiere wakelock, pero supongo que a OS no le importa. Pero espero que OS libere wakelock más tarde). ¿Qué le sucede a ese wakelock?

Caso 2-b:
(. Si la respuesta a la sentencia de 2-a es "Sí, no se preocupe", a continuación, por favor, ignora este caso) Igual que el caso 2-A, pero el servicio dio la opción de tiempo de espera a wakelock, digamos 3 segundos. ¿Esta opción de tiempo de espera se mantiene válida?

Respuesta

43

general WakeLock Implementación

Cuando usamos pm.newWakeLock para crear un nuevo wakelock, la PowerManager simplemente crea un nuevo objeto WakeLock y vuelve. El objeto WakeLock no es un objeto de enlace, por lo que no se puede usar a través de múltiples procesos. Sin embargo, en ese objeto WakeLock, contiene un objeto Binder llamado mToken.

WakeLock(int flags, String tag) { 
     mFlags = flags; 
     mTag = tag; 
     mToken = new Binder(); 
    } 

Así que cuando se llama a adquirir o liberar en este objeto WakeLock, lo que realmente pasa esa señal a PowerManagerService.

private void acquireLocked() { 
     if (!mRefCounted || mCount++ == 0) { 
      mHandler.removeCallbacks(mReleaser); 
      try { 
       mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource); 
      } catch (RemoteException e) { 
      } 
      mHeld = true; 
     } 
    } 

vistazo a cómo funciona PowerManagerService al adquirir o la liberación de un wakelock le ayudará a responder a su pregunta.

void acquireWakeLockInternal(IBinder lock, int flags, String tag, WorkSource ws, 
     int uid, int pid) { 
    synchronized (mLock) { 
     ... 
     WakeLock wakeLock; 
     int index = findWakeLockIndexLocked(lock); 
     if (index >= 0) { 
      ... 
      // Update existing wake lock. This shouldn't happen but is harmless. 
      ... 
     } else { 
      wakeLock = new WakeLock(lock, flags, tag, ws, uid, pid); 
      try { 
       lock.linkToDeath(wakeLock, 0); 
      } catch (RemoteException ex) { 
       throw new IllegalArgumentException("Wake lock is already dead."); 
      } 
      notifyWakeLockAcquiredLocked(wakeLock); 
      mWakeLocks.add(wakeLock); 
     } 
     ... 
    } 
    ... 
} 

La declaración clave es lock.linkToDeath(wakeLock, 0);. Ese lock es exactamente el mToken que mencionamos antes. Este método registra al destinatario (wakeLock) para recibir una notificación si esta carpeta se va.Si este objeto de enlace desaparece inesperadamente (normalmente porque se ha cancelado su proceso de alojamiento), se llamará al método binderDied en el destinatario.

Observe que WakeLock en PowerManagerService es diferente de WakeLock en PowerManager, es una implementación de IBinder.DeathRecipient. Así que revisa su método binderDied.

@Override 
    public void binderDied() { 
     PowerManagerService.this.handleWakeLockDeath(this); 
    } 

El handleWakeLockDeath dará a conocer que wakelock.

private void handleWakeLockDeath(WakeLock wakeLock) { 
    synchronized (mLock) { 
     ... 
     int index = mWakeLocks.indexOf(wakeLock); 
     if (index < 0) { 
      return; 
     } 

     mWakeLocks.remove(index); 
     notifyWakeLockReleasedLocked(wakeLock); 

     applyWakeLockFlagsOnReleaseLocked(wakeLock); 
     mDirty |= DIRTY_WAKE_LOCKS; 
     updatePowerStateLocked(); 
    } 
} 

Así que creo que en ambos casos en su pregunta, la respuesta es que no se preocupe. Al menos en Android 4.2 (de donde viene el código), es cierto. Además, hay un método de finalización en la clase WakeLock en PowerManager, pero esta no es la clave de su pregunta.

+4

Gracias por su respuesta clara y detallada a esta pregunta de hace 2 años. Tu respuesta definitivamente ayuda a muchos desarrolladores, incluyéndome a mí. – Tomcat

+1

Con gusto, no sé por qué esta vieja pregunta saltó al primer lugar de la lista de preguntas ordenada por interesante. @Gato – StarPinkER

6

Supongo (no lo sé con certeza) que el sistema Android no mantiene wakelocks para los procesos eliminados. Lo más probable es que cuando mata un proceso con sigkill, también elimine cualquier wakelocks retenido por ese proceso.

De lo contrario, como dices, los bloqueos conducirían a que el teléfono esté siempre despierto, lo que no he observado.

+0

Me parece razonable. Supongo que tienes razón. Espero que SDK describa claramente este comportamiento. – Tomcat

+0

También encontré tiempo de espera para que wakelock tenga el error [link] http://code.google.com/p/android/issues/detail?id=14184 por lo que no podemos usarlo de manera eficiente. (Lo probé con OS2.2 y falló, luego Google condujo a ese enlace.) – Tomcat

+1

Una prueba simple sería crear una aplicación que establezca una pantalla de mantenimiento en wakelock, luego tener un botón en la aplicación que intencionalmente cause un FC. Luego solo espere y vea si la pantalla se apaga o no. –

Cuestiones relacionadas