Frage

Ich habe Frage zu WakeLock. In den Fällen, unten gezeigt, hat Android OS Release WakeLock (PARTIAL_WAKE_LOCK, wenn Sie angeben müssen) WakeLock verhindern gelassen wurde erworben und Batterie verschwendet bis Drehen Ausschalten (nicht schlafen).

Fall 1-a:
App hat WakeLock erworben (w / o Timeout-Option) in einem seiner Threads (bitte denken, dass es in diesem Fall sinnvoll ist), und es wurde zu Release WakeLock entworfen, wenn kritische Aufgabe beendet wurde. App kann durch Taskmanager oder berüchtigt Taskkiller getötet werden und App hat keine Chance, ihr Gewinde Release WakeLock zu lassen. Was geschieht mit diesem WakeLock?

Fall 1-b:
(Wenn Antwort auf Fall 1-a „Ja, keine Sorge“, dann ignorieren Sie bitte diesen Fall.) Das gleiche wie Fall 1-a, aber app gab Timeout Option WakeLock, sagen wir 3 Sekunden. Ist die Timeout Option gehalten gültig?

Fall 2-a:
Bitte vorstellen, dass es ist eine Dienstleistung, die durch Alarmmanager (über Rundfunkempfänger) gestartet wurde und der Service hat einen WakeLock erworben (w / o Timeout-Option). Dieser Service wird entwickelt, um WakeLock erworbene Zeit Minimum zu machen. Aber leider, nahm Android OS, diesen Dienst zu töten aufgrund von Speicher Crunch. (Ich weiß nicht, ob OS nicht Dienst töten, wenn WakeLock erworben wird, aber ich denke, OS kümmert sich nicht darum. Aber ich hoffe, OS Release wird WakeLock später.) Was in diesem WakeLock passiert?

Fall 2-b:
(Wenn Antwort auf Fall 2-a „Ja, keine Sorge“, dann ignorieren Sie bitte diesen Fall.) Genauso wie der Fall 2-a, aber der Service gab Timeout Option WakeLock, sagen wir 3 Sekunden. Ist die Timeout Option gehalten gültig?

War es hilfreich?

Lösung

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 Bindemittel Objekt, so dass es nicht durch mehrere Prozesse verwendet werden kann. Doch in diesem WakeLock Objekt, es enthält ein Binder-Objekt namens mToken.

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

Wenn Sie also acquire oder Mitteilung zu diesem WakeLock Objekt aufrufen, es geht eigentlich, dass Token PowerManagerService.

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

Schauen Sie, wie PowerManagerService arbeitet 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 Kernaussage ist die lock.linkToDeath(wakeLock, 0);. Das lock ist genau das mToken wir bereits erwähnt. Diese Methode registriert den Empfänger (die wakeLock) für eine Benachrichtigung, wenn dieses Bindemittel weggeht. Wenn dieses Bindemittel Objekt weggeht unerwartet (in der Regel, weil sein Hosting-Prozess getötet wurde), dann wird die binderDied Methode auf dem Empfänger erhalten genannt.

Beachten Sie, dass der WakeLock in PowerManagerService vom WakeLock in PowerManager unterschiedlich ist, ist es eine Implementierung von IBinder.DeathRecipient. So seine binderDied Methode überprüfen.

    @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 habe ich in beiden Fällen in Frage denke, die Antwort ist keine Sorge. Zumindest in Android 4.2 (wo der Code herkommt), ist es wahr. Darüber hinaus gibt es eine Methode finalize auf der WakeLock Klasse in PowerManager, aber dies ist nicht der Schlüssel zu Ihrer Frage.

Andere Tipps

Ich würde davon ausgehen, (ich weiß nicht, dies für bestimmte) das Android-System nicht halten wakelocks für getötet Prozesse. Wahrscheinlich, wenn es einen Prozess mit SIGKILL tötet es entfernt auch alle von diesem Prozess gehalten wakelocks.

Ansonsten, wie Sie sagen, Abstürze zu dem Telefon führen würden immer wach zu sein, was ich nicht beobachtet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top