12/08/2018, 15:11

Hoạt động của App trong Doze Mode and App Standby

Trong Android 6.0 Marshmallow, Google đã tích hợp một công nghệ mang tên Doze để giúp kéo dài thời gian dùng pin của smartphone và tablet khi chạy phiên bản OS này. Về cơ bản, Doze sẽ hạn chế hoạt động của các ứng dụng, hạn chế việc truy cập mạng trong những lúc bạn để máy nằm yên một chỗ không xài ...

Trong Android 6.0 Marshmallow, Google đã tích hợp một công nghệ mang tên Doze để giúp kéo dài thời gian dùng pin của smartphone và tablet khi chạy phiên bản OS này. Về cơ bản, Doze sẽ hạn chế hoạt động của các ứng dụng, hạn chế việc truy cập mạng trong những lúc bạn để máy nằm yên một chỗ không xài tới, chẳng hạn như buổi tối đi ngủ hay trong suốt mấy tiếng làm việc ở văn phòng.

Trong bài viết này mình thực hiện test app với Doze Mode và App Standby để xem ảnh hưởng của chúng đến một số tính năng của app.

Đầu tiên bạn có thể download app test ở đây: http://doze-sample.appspot.com/apk/DozeStandbySample.apk Sau đó cài đặt app thông qua ADB (Android Debug Bridge)

$ adb install DozeStandbySample.apk

Trong chế độ Doze, hệ thống sẽ cố gắng tiết kiệm pin bằng cách hạn chế quyền truy cập của các ứng dụng vào network và CPU-intensive services. Chế độ Doze sẽ hoạt động khi người dùng ko xạc pin, để thiết bị nằm yên 1 thời gian và màn hình đang tắt.

Doze mode states:

  • ACTIVE: Thiết bị đang hoạt động.
  • INACTIVE: Thiết bị không hoạt động (màn hình tắt, không chuyển động) và đang ở trạng thái chờ cho trạng thái idle.
  • IDLE_PENDING: Thiết bị đã qua giai đoạn không hoạt động ban đầu và chờ khoảng thời gian dỗi tiếp theo.
  • SENSING: Thiết bị đang cảm nhận chuyển động.
  • LOCATING: Thiết bị đang tìm vị trí (và vẫn có thể cảm nhận).
  • IDLE: Thiết bị đang ở trạng thái nhàn dỗi, cố gắng ngủ càng nhiều càng tốt =))
  • IDLE_MAINTENANCE: Thiết bị đang ở trại thái nhàn dỗi, nhưng tạm thời không hoạt động để thực hiện bảo trì định kỳ.

Để kiểm tra chế độ Doze, trước tiên ta phải mô phỏng một thiết bị không được cắm. Và ta sẽ thực hiện điều này thong qua ADB

$ adb shell dumpsys battery unplug

Các điều kiện tiên quyết khác cho chế độ Doze là màn hình phải được tắt. Đặt thiết bị của bạn vào chế độ ngủ bằng cách nhấn nút nguồn hoặc sử dụng lệnh:

$ adb shell input keyevent KEYCODE_POWER

Bây giờ chúng ta có thể kích hoạt chế độ Doze thông qua:

$ adb shell dumpsys deviceidle step

Lệnh này xoay qua các trạng thái khác nhau của Doze. Bạn có thể phải lại lệnh này vài lần cho đến khi vào trạng thái Doze IDLE:

$ adb shell dumpsys deviceidle step
Stepped to: ACTIVE
$ adb shell dumpsys deviceidle step
Stepped to: IDLE_PENDING
$ adb shell dumpsys deviceidle step
Stepped to: SENSING
$ adb shell dumpsys deviceidle step
Stepped to: LOCATING
$ adb shell dumpsys deviceidle step
Stepped to: IDLE_MAINTENANCE
$ adb shell dumpsys deviceidle step
Stepped to: IDLE

Định kỳ, hệ thống sẽ thoái khỏi Doze trong một thời gian ngắn để cho phép ứng dụng hoàn tất các hoạt động đang hoãn lại. Trong suốt thời gian bảo trì, hệ thống sẽ chạy tất cả các pending syncs, jobs, and alarms, và cho phép ứng dụng truy cập network. Bạn có thể kích hoạt chế độ bảo trì bằng các thực hiện lệnh step thêm một lần nữa:

$ adb shell dumpsys deviceidle step
Stepped to: IDLE_MAINTENANCE

thêm nháy nữa thì sẽ lại đưa thiết bị về trạng thái IDLE:

$ adb shell dumpsys deviceidle step
Stepped to: IDLE

Để thoát khỏi chế độ Doze chỉ cần bật màn hình thiết bị lên thế là out.

Trạng thái Doze idle sẽ không cho JobScheduler chạy. Hãy cùng thực hiện các bước sau để hiểu rõ hơn các hoạt động của background jobs trong Doze mode. Đầu tiên ta cần phải start một chú job ở background, để thực hiện điều này ta cần mở app (vừa cài phía trên đó) và tại tab JOBS bấm START JOB button.

Và theo dõi Job qua logcat:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 14:58:20.010 28307 28326 I DozeSample: Registration success: 375885
04-27 14:58:20.041 28307 28326 I DozeSample: Registration token: e46_tc11-z4:APA91bGQSRT2qUZZBjzmeiM_vBtQo4y8CeM3xF64QgPFnxiUHoURfJ3dRtiN4aiL3tFTHDrAuyYIR1f8w4iXqhdsHeluuwF9y4PRjYdasrxealUJSIGwJE43sG5HhXmS_8X358brh3tD

Đầu tiên kiểm tra xem Job có tạm dừng khi vào chế độ Doze. Mở cửa sổ terminal và kích hoạt chế độ Doze idle:

$ adb shell dumpsys deviceidle step

Và kết quả là Job sẽ bị tạm ngưng:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main

Khi Job bị tạm dừng, ta sẽ thực hiện kiểm tra xem nó có tiếp tục trong thời gian bảo trì hay không, chuyển qua trại thái IDLE_MAINTENANCE.

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 15:12:56.989 28307 29592 I DozeSample: Registration token: e46_tc11-z4:APA91bGQSRT2qUZZBjzmeiM_vBtQo4y8CeM3xF64QgPFnxiUHoURfJ3dRtiN4aiL3tFTHDrAuyYIR1f8w4iXqhdsHeluuwF9y4PRjYdasrxealUJSIGwJE43sG5HhXmS_8X358brh3tD
04-27 15:13:00.268 28307 29597 I DozeSample: Registration token: e46_tc11-z4:APA91bGQSRT2qUZZBjzmeiM_vBtQo4y8CeM3xF64QgPFnxiUHoURfJ3dRtiN4aiL3tFTHDrAuyYIR1f8w4iXqhdsHeluuwF9y4PRjYdasrxealUJSIGwJE43sG5HhXmS_8X358brh3tD

Cuối cùng kiểm tra logcat và Job được tiếp tục trở lại khi thoát khỏi chế độ Doze. Hãy trở lại trạng thái IDLE một lần nữa. Và điều này sẽ khiến Job tạm dừng một lần nữa. Thoát khỏi chế độ Doze bằng cách bật màn hình thiết bị, tại thời điểm này mọi thức sẽ làm việc bình thường trở lại.

Trong chế độ Doze idle, quyền truy cập network bị treo. Điều này cũng có nghĩa là ứng dụng không thể poll backend servers trong background. Ta sẽ thực hiện gửi notification GCM với chế độ Doze. Bật sang tab GCM và truy cập vào url được hiển thị:

à nhớ mở trên thiết bị khác nha, thiết bị chạy để còn test.

Hãy xem notification vẫn hoạt động trong Doze. Kiểm tra logcat thông qua ADB để theo dõi rõ hơn:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main

Và đưa thiết bị về trạng thái IDLE:

$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
Stepped to: IDLE

Gửi GCM message và theo dõi logcat:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 16:16:01.853 28307 31205 I DozeSample: Received GCM Message: 'Hello :-)' with priority: null send at 16:16:05 received at 16:16:01
04-27 16:16:01.857 28307 31205 I DozeSample: ConnectivityManager.getActiveNetworkInfo().isConnected() => true
04-27 16:16:02.711 28307 31205 I DozeSample: Connection to www.google.com successful

Vậy là notifications vẫn đến trong Doze.

Standard AlarmManager alarms có thể bị ảnh hưởng bởi chế độ Doze. Vì vậy chúng ta hãy cùng kiểm tra vấn đề này. Tiếp tục bật logcat:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 16:27:20.311 28307 28307 I DozeSample: set alarm: 16:26:49

Đồng thời chuyển sang tab ALARMS, và cài đặt thời gian phù hợp sao cho đủ thời gian bạn chuyển thiết bị sang chế độ Doze idle:

Khỏi động chế độ IDLE:

$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
Stepped to: IDLE

Đợi alarm và kiểm tra logcat thôi:

adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 16:26:09.525 28307 28307 I DozeSample: set alarm: 16:26:49
04-27 16:26:49.533 28307 28307 I DozeSample: Received Alarm: 16:26:49
04-27 16:26:49.559 28307 28613 I DozeSample: ConnectivityManager.getActiveNetworkInfo().isConnected() => true
04-27 16:26:50.030 28307 28613 I DozeSample: Connection to www.google.com successful
04-27 16:27:20.311 28307 28307 I DozeSample: set alarm: 16:28:00
04-27 16:28:00.313 28307 28307 I DozeSample: Received Alarm: 16:28:00
04-27 16:28:00.339 28307 28740 I DozeSample: ConnectivityManager.getActiveNetworkInfo().isConnected() => true
04-27 16:28:05.376 28307 28740 I DozeSample: Connection to www.google.com failed

Vậy là... Alarm vẫn hoạt động trong Doze :v

App Standby trì hoãn các hoạt động background network đối với những ứng dụng mà người dùng không có tương tác gần đây. Sau đây chúng ta sẽ thực hiện kiểm tra xem background jobs có hoạt động với App Standby.

Understanding App Standby
Ứng dụng sẽ chuyển sang chế độ Standby khi người dùng không có tương tác với ứng dụng trong một thời gian nhất định và không áp dụng các điều kiện sau đây:
- Người dùng khởi động một cách rõ ràng ứng dụng.
- Ứng dụng có một tiến trình ở foreground (hoặc như một activity hoặc foreground service, hoặc đang được sử dụng bởi một ứng dụng khác hoặc bởi foreground service khác).
- Ứng dụng tạo ra notification nhìn thấy trên lockscreen hoặc trong notification tray.

Đầu tiên ta thực hiện chạy JOBS như trên, và bật logcat lên để theo dõi:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main

App Standby chỉ hoạt động khi thiết bị không được cắm điện. Vì vậy ta cần mô phỏng điều đó:

$ adb shell dumpsys battery unplug

Sau đó chuyển ứng dụng sang chế độ standby:

$ adb shell am set-inactive com.example.android.dozestandby true
$ adb shell am get-inactive com.example.android.dozestandby
Idle=true

Hãy nhìn logcat và ta sẽ thấy Job bị tạm dừng. Tiếp theo ta sẽ đưa ứng dụng thoát khỏi chế độ standby:

$ adb shell am set-inactive com.example.android.dozestandby false
$ adb shell am get-inactive com.example.android.dozestandby
Idle=false
$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 16:44:56.387 28307 32046 I DozeSample: Registration token: e46_tc11-z4:APA91bGQSRT2qUZZBjzmeiM_vBtQo4y8CeM3xF64QgPFnxiUHoURfJ3dRtiN4aiL3tFTHDrAuyYIR1f8w4iXqhdsHeluuwF9y4PRjYdasrxealUJSIGwJE43sG5HhXmS_8X358brh3tD
04-27 16:45:04.899 32154 32172 I DozeSample: Registration token: e46_tc11-z4:APA91bGQSRT2qUZZBjzmeiM_vBtQo4y8CeM3xF64QgPFnxiUHoURfJ3dRtiN4aiL3tFTHDrAuyYIR1f8w4iXqhdsHeluuwF9y4PRjYdasrxealUJSIGwJE43sG5HhXmS_8X358brh3tD

Job lại hoạt động trở lại.

Liệu notification có hoạt động trong App Standby giống như trong Doze. Chúng ta cùng kiểm tra điều này. Đầu tiên hãy thực hiện các bước đầu tiên như với kiểm tra trong Doze, truy cập url được hiển thị và gửi message, đồng thời bật logcat để theo dõi:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main

Hãy chuyển thiết bị sang chế độ Standby nào:

$ adb shell dumpsys battery unplug
$ adb shell am set-inactive com.example.android.dozestandby true
$ adb shell am get-inactive com.example.android.dozestandby
Idle=true

Gửi GCM message và:

$ adb logcat -s "DozeSample"
--------- beginning of system
--------- beginning of main
04-27 17:05:41.903 32154 32424 I DozeSample: Received GCM Message: 'Hello :-)' with priority: null send at 17:05:45 received at 17:05:41
04-27 17:05:41.906 32154 32424 I DozeSample: ConnectivityManager.getActiveNetworkInfo().isConnected() => true
04-27 17:05:42.533 32154 32424 I DozeSample: Connection to www.google.com successful

Vậy notification vẫn hoạt động trong chế độ standby :v

Trên đây là một số bài kiểm tra để bạn có thể hiểu rõ hơn về Doze mode and App Standby. Bạn có thể thực hiện một số bài test khác để có thể hiểu kỹ hơn về 2 chế độ này.

0