42

Wakelock hakkında bir sorum var. Aşağıda gösterilen durumlarda, wakelock'un kalmasını önlemek ve güç kapanıncaya kadar pilin boşa harcanmasını önlemek için wakelock'u (belirtmeniz gerekiyorsa PARTIAL_WAKE_LOCK) serbest bırakınız.Android OS işletim sistemi, onu tutan uygulama veya hizmet öldürüldüğünde bir uyanıklık mı veriyor?

Durum 1-a: Uygulama (bu durumda makul olduğunu düşünüyorum lütfen) kendi konuları birinde (zaman aşımı seçeneği w/o) Uyandırma kilidi satın aldı ve kritik görev iken Uyandırma kilidi serbest bırakmak için tasarlanmıştır
tamamladı. App taskmanager veya kötü şöhretli görev kesiciler tarafından öldürülür ve app iplik serbest bırakma wakelock izin şansı yoktur. Bu uyanığa ne olacak?

Durum 1-b:
(. Case 1-a cevabı ise, bu davayı göz ardı edin, "Evet, merak etmeyin") case 1-a, fakat uygulamada aynı verdi aşımı seçeneği uyanmak için, 3 saniye söyle. Bu zaman aşımı seçeneği geçerli mi?

Durum 2-a:
orada (Broadcast alıcı üzerinden) AlarmManager başlatmış olduğu bir hizmettir ve hizmet (zaman aşımı seçeneği o/w) bir Uyandırma kilidi satın aldı hayal edin. Bu servis, uyanık edinilen zamanı en aza indirmek için tasarlanmıştır. Ancak maalesef Android işletim sistemi bu hizmeti bellek sıkışıklığı nedeniyle öldürdü. (Wakelock elde edildiğinde işletim sisteminin işletim sistemini öldürüp öldürmeyeceğini bilmiyorum, ama işletim sisteminin umurunda değil sanırım. Ama umarım işletim sistemi daha sonra uyandırır.) Bu uyanıklığa ne olur?

Durum 2-b:
(. Vaka 2-a cevabı ise, bu davayı göz ardı edin, "Evet, merak etmeyin") vaka 2-a ama hizmet olarak aynı verdi aşımı seçeneği uyanmak için, 3 saniye söyle. Bu zaman aşımı seçeneği geçerli mi?

cevap

43

Uyandırma kilidi Uygulama Genel Bakış

yeni bir Uyandırma kilidi oluşturmak için pm.newWakeLock kullanın PowerManager sadece yeni Uyandırma kilidi nesne ve döner oluşturur. WakeLock nesnesi bir bağlayıcı nesne değildir, bu nedenle birden çok işlemle kullanılamaz. Ancak, WakeLock nesnesinde, mToken adlı bir Binder nesnesi içerir. Edindiğiniz veya bu Uyandırma kilidi nesne üzerinde serbest çağırdığınızda

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

Yani, aslında PowerManagerService bu belirteç geçirir. PowerManagerService eserler edinme ya da soruya cevap yardımcı olacak bir Uyandırma kilidi serbest zaman nasıl

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

bak.

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

Anahtar deyim lock.linkToDeath(wakeLock, 0);'dur. Bu lock tam olarak daha önce bahsettiğimiz mToken. Bu yöntem, eğer bu ciltçi uzaklaşırsa bir bildirim için alıcıyı (wakeLock) kaydeder.Bu bağlayıcı nesne beklenmedik bir şekilde kaybolursa (genellikle barındırma işlemi öldürüldüğü için), alıcıya binderDied yöntemi çağrılır.

PowerManagerService'daki WakeLock öğesinin, PowerManager'daki WakeLock'tan farklı olduğuna dikkat edin, bu IBinder.DeathRecipient'un bir uygulamasıdır. Yani binderDied yöntemini kontrol edin.

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

handleWakeLockDeath o Uyandırma kilidi yayınlayacak.

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

Bu nedenle, her iki durumda da, sorunuzda yanıtın endişelenmeyin. En azından Android 4.2'de (kodun nereden geldiğini), doğrudur. Ayrıca, WakeLock sınıfında PowerManager'da bir sonlandırma yöntemi vardır, ancak sorunuzun anahtarı bu değildir.

+4

Bu 2 yıllık soruya verdiğiniz ayrıntılı ve açık bir cevap için teşekkür ederiz. Cevabınız kesinlikle benim dahil olmak üzere birçok geliştiriciye yardımcı olur. – Tomcat

+1

Zevkle, bu eski sorunun niçin ilginç bir şekilde sıralanmış soru listesinin ilk yerine atladığını bilmiyorum. @Tomcat – StarPinkER

6

Android sisteminin, öldürülen süreçler için uyanık kalmadığını varsayıyorum. Büyük olasılıkla bir süreci sigkill ile öldürdüğünde, bu işlem tarafından tutulan herhangi bir uyanıklığı da ortadan kaldırır. Aksi halde, söylediğiniz gibi, çökmeler telefonun daima uyanık olmasına yol açacaktı, ki bu gözlemlemedim.

+0

Bana göre mantıklı geliyor. Sanırım haklısın. Umarım SDK bu davranışı açıkça tanımlar. – Tomcat

+0

Ayrıca wakelock için zaman aşımı hata buldu [link] http://code.google.com/p/android/issues/detail?id=14184 bu yüzden verimli bir şekilde kullanamıyoruz. (Bunu OS2.2 ile denedim ve başarısız oldum, sonra Google bu bağlantıya yönlendirdi.) – Tomcat

+1

Basit bir test, wakelock üzerinde bir ekran koruyan bir uygulama yapmak ve daha sonra bir FC'ye kasıtlı olarak neden olan uygulamada bir düğme oluşturmak olacaktır. Sonra bekleyip ekranın kapanıp kapanmadığını görün. –

İlgili konular