42

Ich habe eine Frage zu wakelock. In den unten gezeigten Fällen wird Android Wakelock (PARTIAL_WAKE_LOCK, wenn Sie angeben müssen) freigeben, um zu verhindern, dass Wakelock akquiriert wurde und Batterie verschwendet wird, bis das Gerät ausgeschaltet wird (nicht schlafen).Wird auf dem Android-Betriebssystem ein Wakelock veröffentlicht, wenn die App oder der Dienst, der es enthält, gelöscht wird?

Fall 1-a:
App WakeLock (w/o Timeout-Option) in einem seiner Threads erworben hat (bitte denken, es ist vernünftig, in diesem Fall) und es wurde entwickelt WakeLock freizugeben, wenn kritische Aufgabe war fertig. App kann vom Taskmanager oder berüchtigten Taskkiller getötet werden, und app hat keine Chance seinen Thread Wakelock freizugeben. Was passiert mit diesem Wakelock?

Fall 1-b:
(. Wenn Antwort auf Fall 1-a "Ja, keine Sorge", dann ignorieren Sie bitte diesen Fall) Gleiche wie Fall 1-a, aber app gab Timeout Option zu wakelock sagen 3 Sekunden. Ist diese Timeout-Option gültig?

Fall 2-a:
Bitte vorstellen, dass es ist eine Dienstleistung, die durch Alarmmanager (über Broadcast-Empfänger) und der Service erworben hat eine WakeLock (w/o Timeout Option) gestartet wurde. Dieser Service ist darauf ausgelegt, die wakelock-akquirierte Zeit zu minimieren. Aber leider hat Android OS diesen Dienst ausgewählt, um aufgrund von Speicher-Crunch zu töten. (Ich weiß nicht, ob OS den Dienst nicht beenden wird, wenn Wakelock erworben wird, aber ich schätze OS ist das egal. Aber ich hoffe, OS wird Wakelock später veröffentlichen.) Was passiert mit diesem Wakelock?

Fall 2-b:
(. Wenn Antwort auf Fall 2-a "Ja, keine Sorge", dann ignorieren Sie bitte diesen Fall) Gleiche wie Fall 2-a, aber der Service gab Timeout Option zu wakelock sagen 3 Sekunden. Ist diese Timeout-Option gültig?

Antwort

43

WakeLock Übersicht über die Implementierung

Wenn wir pm.newWakeLock verwenden, um einen neuen WakeLock zu erstellen, erstellt die PowerManager einfach ein neues WakeLock Objekt und kehrt zurück. Das WakeLock-Objekt ist kein Binderobjekt, daher kann es nicht durch mehrere Prozesse verwendet werden. In diesem WakeLock-Objekt enthält es jedoch ein Binder-Objekt namens mToken.

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

Also, wenn Sie erwerben anrufen oder freigeben zu diesem WakeLock Objekt, es geht tatsächlich, dass die Token PowerManagerService.

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

Blick darauf, wie PowerManagerService Arbeiten beim Erwerb oder eine WakeLock Loslassen Sie Ihre Frage helfen zu beantworten.

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

Die Schlüsselaussage ist die lock.linkToDeath(wakeLock, 0);. Das lock ist genau das mToken, das wir vorher erwähnt haben. Diese Methode registriert den Empfänger (wakeLock) für eine Benachrichtigung, wenn dieser Ordner verschwindet.Wenn dieses Binderobjekt unerwartet verschwindet (normalerweise, weil sein Hostingprozess beendet wurde), wird die Methode binderDied für den Empfänger aufgerufen.

Beachten Sie, dass der WakeLock in PowerManagerService vom WakeLock in PowerManager unterschiedlich ist, ist es eine Implementierung von IBinder.DeathRecipient. Schauen Sie sich die binderDied Methode an.

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

Die handleWakeLockDeath wird diese WakeLock lösen.

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

Also ich denke in beiden Fällen in Ihrer Frage ist die Antwort, keine Sorge. Zumindest in Android 4.2 (wo der Code herkommt) stimmt es. Darüber hinaus gibt es eine Finalize-Methode für die WakeLock-Klasse in PowerManager, aber das ist nicht der Schlüssel zu Ihrer Frage.

+4

Vielen Dank für Ihre ausführliche, klare Antwort auf diese 2 Jahre alte Frage. Ihre Antwort hilft definitiv vielen Entwicklern, einschließlich mir. – Tomcat

+1

Mit Vergnügen weiß ich nicht, warum diese alte Frage auf den allerersten Platz der Fragenliste gesprungen ist, sortiert nach interessanten. @Kater – StarPinkER

6

Ich würde annehmen (ich weiß es nicht sicher) das Android-System wakelocks für getötete Prozesse nicht halten. Am wahrscheinlichsten, wenn es einen Prozess mit sigkill beendet, entfernt es auch alle wakelocks, die von diesem Prozess gehalten werden.

Sonst, wie Sie sagen, Abstürze würde dazu führen, dass das Telefon immer wach ist, was ich nicht beobachtet habe.

+0

Es klingt vernünftig für mich. Ich schätze du hast Recht. Ich hoffe, SDK beschreibt dieses Verhalten eindeutig. – Tomcat

+0

Ich fand auch Timeout für Wakelock hat Fehler [Link] http://code.google.com/p/android/issues/detail?id=14184 so können wir es nicht auf effiziente Weise verwenden. (Ich versuchte es mit OS2.2 und fehlgeschlagen, dann führte Google zu diesem Link.) – Tomcat

+1

Ein einfacher Test wäre, eine Anwendung zu machen, die einen Haltebildschirm auf wakelock setzt, dann eine Taste in der App, die absichtlich einen FC verursacht. Dann warte ab und schau, ob sich der Bildschirm ausschaltet oder nicht. –