42

Tôi có câu hỏi về wakelock. Trong trường hợp được hiển thị bên dưới, hệ điều hành android phát hành wakelock (PARTIAL_WAKE_LOCK nếu bạn cần phải chỉ định) để ngăn chặn wakelock đã được mua lại và lãng phí pin cho đến khi tắt nguồn (không ngủ).Hệ điều hành Android có phát hành một wakelock nếu ứng dụng hoặc dịch vụ giữ nó bị giết không?

Trường hợp 1-a:
App đã mua wakelock (w/o tùy chọn timeout) tại một trong những chủ đề của nó (xin nghĩ rằng đó là hợp lý trong trường hợp này) và nó được thiết kế để phát hành wakelock khi nhiệm vụ quan trọng là đã kết thúc. Ứng dụng có thể bị giết bởi taskmanager hoặc taskkiller khét tiếng, và ứng dụng không có cơ hội để cho wakelock phát hành luồng của nó. Điều gì sẽ xảy ra với wakelock đó?

Trường hợp 1-b:
(. Nếu câu trả lời cho trường hợp 1-a là "Có, đừng lo lắng", sau đó xin vui lòng bỏ qua trường hợp này) Tương tự như trường hợp 1-a nhưng ứng dụng đã lựa chọn thời gian chờ để wakelock, nói 3 giây. Tùy chọn thời gian chờ này có hợp lệ không?

Trường hợp 2-a:
Hãy tưởng tượng có một dịch vụ được bắt đầu bởi AlarmManager (thông qua Broadcast receiver) và các dịch vụ đã mua một wakelock (w/o tùy chọn thời gian chờ). Dịch vụ này được thiết kế để tối thiểu hóa thời gian mua lại wakelock. Nhưng thật không may, hệ điều hành Android đã chọn dịch vụ này để giết do khủng hoảng bộ nhớ. (Tôi không biết liệu hệ điều hành sẽ không giết dịch vụ khi wakelock được mua, nhưng tôi đoán hệ điều hành không quan tâm. Nhưng tôi hy vọng hệ điều hành sẽ phát hành wakelock sau.) Điều gì sẽ xảy ra với wakelock đó?

Trường hợp 2-b:
(. Nếu câu trả lời cho trường hợp 2-a là "Có, đừng lo lắng", sau đó xin vui lòng bỏ qua trường hợp này) Tương tự như trường hợp 2-một dịch vụ nhưng đã lựa chọn thời gian chờ để wakelock, nói 3 giây. Tùy chọn thời gian chờ này có hợp lệ không?

Trả lời

43

Tổng quan WakeLock Thực hiện

Khi chúng tôi sử dụng pm.newWakeLock để tạo ra một wakelock mới, PowerManager chỉ đơn giản là tạo ra một đối tượng WakeLock mới và lợi nhuận. Đối tượng WakeLock không phải là một đối tượng kết dính, vì vậy nó không thể được sử dụng thông qua nhiều quy trình. Tuy nhiên, trong đối tượng WakeLock đó, nó chứa một đối tượng Binder có tên là mToken.

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

Vì vậy, khi bạn gọi có được hoặc giải phóng đối tượng WakeLock này, nó thực sự chuyển mã thông báo đó đến PowerManagerService.

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

Nhìn vào cách PowerManagerService công trình khi có được hoặc phát hành một wakelock sẽ giúp bạn trả lời câu hỏi của bạn.

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

Tuyên bố chính là lock.linkToDeath(wakeLock, 0);. Đó là lock chính xác là mToken mà chúng tôi đã đề cập trước đây. Phương pháp này đăng ký người nhận (wakeLock) để nhận thông báo nếu chất kết dính này biến mất.Nếu đối tượng liên kết này bất ngờ biến mất (thường là do quá trình lưu trữ của nó đã bị hủy), thì phương thức binderDied sẽ được gọi trên người nhận.

Lưu ý rằng WakeLock trong PowerManagerService khác với WakeLock ở PowerManager, đó là việc triển khai IBinder.DeathRecipient. Vì vậy, hãy kiểm tra phương thức binderDied của nó.

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

handleWakeLockDeath sẽ phát hành 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(); 
    } 
} 

Vì vậy, tôi nghĩ rằng trong cả hai trường hợp trong câu hỏi của bạn, câu trả lời là đừng lo lắng. Ít nhất trong Android 4.2 (mã nguồn xuất phát từ đâu), điều đó là đúng. Hơn nữa, có một phương pháp hoàn thiện trên lớp WakeLock trong PowerManager, nhưng đây không phải là chìa khóa cho câu hỏi của bạn.

+4

Cảm ơn bạn đã trả lời chi tiết, rõ ràng cho câu hỏi 2 năm tuổi này. Câu trả lời của bạn chắc chắn sẽ giúp nhiều nhà phát triển trong đó có tôi. – Tomcat

+1

Với niềm vui, tôi không biết tại sao câu hỏi cũ này lại nhảy lên vị trí đầu tiên của danh sách câu hỏi được sắp xếp theo thú vị. @Tomcat – StarPinkER

6

Tôi giả định (Tôi không biết điều này chắc chắn) hệ thống Android không giữ wakelocks cho các quá trình bị giết. Nhiều khả năng khi nó giết chết một quá trình với sigkill nó cũng loại bỏ bất kỳ wakelocks được tổ chức bởi quá trình đó.

Nếu không, như bạn nói, sự cố sẽ dẫn đến điện thoại luôn luôn thức, mà tôi chưa quan sát thấy.

+0

Nghe có vẻ hợp lý với tôi. Tôi đoán là bạn đúng. Tôi hy vọng SDK mô tả rõ ràng hành vi này. – Tomcat

+0

Tôi cũng tìm thấy thời gian chờ cho wakelock có lỗi [link] http://code.google.com/p/android/issues/detail?id=14184 vì vậy chúng tôi không thể sử dụng nó theo cách hiệu quả. (Tôi đã thử nó với OS2.2 và thất bại, sau đó Google dẫn đến liên kết đó.) – Tomcat

+1

Một thử nghiệm đơn giản sẽ là tạo một ứng dụng đặt màn hình giữ trên wakelock, sau đó có một nút trong ứng dụng cố ý gây ra FC. Sau đó, chỉ cần chờ xem màn hình có tắt hay không. –

Các vấn đề liên quan