Pregunta

Tengo pregunta sobre wakelock. En los casos en que se muestran a continuación, hace wakelock versión del SO Android (PARTIAL_WAKE_LOCK si necesita especificar) para evitar que quedaba wakelock adquirida y perder la batería hasta que se apaga la cámara (no sueño).

Caso 1-a:
Aplicación ha adquirido wakelock (Timeout E / S opción w) en uno de sus hilos (por favor, creo que es razonable en este caso) y que fue diseñado para la liberación wakelock cuando se terminó tarea crítica. La aplicación puede ser matado por el administrador de tareas o TaskKiller notorio, y la aplicación no tiene ninguna posibilidad de dejar su liberación wakelock hilo. Lo que le sucede a 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 la opción de tiempo de espera a wakelock aplicación dio, digamos 3 segundos. ¿Es esta opción de tiempo de espera mantiene válida?

Caso 2-a:
Por 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 (opción / o tiempo de espera w). Este servicio está diseñado para hacer mínimo el tiempo adquirido wakelock. Pero, por desgracia, el sistema operativo Android recogió este servicio para matar debido a la crisis de la memoria. (No sé si OS no matará servicio cuando se adquiere wakelock, pero supongo OS no le importa. Pero espero OS dará a conocer más adelante wakelock.) ¿Qué le pasa 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 la opción de tiempo de espera para el servicio wakelock dio, digamos 3 segundos. ¿Es esta opción de tiempo de espera mantiene válida?

¿Fue útil?

Solución

WakeLock Implementation Overview

When we use pm.newWakeLock to create a new wakelock, the PowerManager simply creates a new WakeLock object and returns. The WakeLock object is not a binder object, so it cannot be used through multiple processes. However, in that WakeLock object, it contains a Binder object named mToken.

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

So when you call acquire or release on this WakeLock object, it actually passes that token to PowerManagerService.

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

Look at how PowerManagerService works when acquiring or releasing a wakelock will help you answer your question.

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

The key statement is the lock.linkToDeath(wakeLock, 0);. That lock is exactly the mToken we mentioned before. This method registers the recipient (the wakeLock) for a notification if this binder goes away. If this binder object unexpectedly goes away (typically because its hosting process has been killed), then the binderDied method will get called on the recipient.

Notice that the WakeLock in PowerManagerService is different from the WakeLock in PowerManager, it is an implementation of IBinder.DeathRecipient. So check out its binderDied method.

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

The handleWakeLockDeath will release that 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();
    }
}

So I think in both cases in your question, the answer is don't worry. At least in Android 4.2 (where the code comes from), it is true. Moreover, there is a finalize method on the WakeLock class in PowerManager, but this is not the key to your question.

Otros consejos

I would assume (I don't know this for certain) the Android system does not keep wakelocks for killed processes. Most likely when it kills a process with sigkill it also removes any wakelocks held by that process.

Otherwise, as you say, crashes would lead to the phone always being awake, which I have not observed.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top