영상 출처 : https://youtu.be/t1_8WSEguDY
!주의 : 혼자 영상 보고 의역하고 정리한 글이므로 정확하지 않을 수 있습니다. 해당 글은 정말 간단한 축약본으로 영상 보는 것을 추천합니다
안드로이드는 사용자와 개발자 사이에서 밸런스를 맞추고 모두(사용자와 개발자)에게 고품질을 제공하는게 목적이라고 한다, 이번 영상에서는 캡쳐본처럼 밸런스를 맞추기 위해 어떤 것들을 준비했고 제공하는지에 관해 focusing이 되어있다
안드로이드 프레임워크 팀에서 말하길, 배터리 수명을 향상시키기 위해 위와 같은 피스들을 다 조립했다고 한다.
개발자들은 안드로이드 파편화가 굉장히 힘들었을 거다.(device들의 파편화, 오픈 소스로 풀어둔 만큼 다양한 device에 올리고 사용할 수 있기 때문에) 앱 개발자들은 많은 노력으로 android device 커스텀 된 제품을 수용해왔다. 디바이스 제품들의 major motivation 중 하나는 그들의 사용자에게 더 나은 배터리 수명을 제공하는 것이었다.
백신 앱을 제한 하는 등 개발자들에게 어려운 일이 틀림없었다. 그래서 안드로이드 팀은 제한레벨을 두어 표준화했다.
이 중 Unrestricted, Optimized, Background Restricted 는 사용자가 선택할 수 있다.
배터리 세팅에서 특정한 앱들을 허용한다고 사용자들이 선택할 수 있다.
대부분의 앱들의 default 세팅이다. optimized setting 역시도 배터리 설정에서 선택할 수 있다.
그러나 이 optimized도 Android 9(API level 28)에서 소개한 거처럼 4개의 단계가 있는데,
1) Active
2) Working Set
3) Frequent
4) Rare
각 단계들은 jobs, alarms 기타 resouces 에 따라 각자 다르게 나뉘어 수용한다.
! 잠깐 이들은 왜 갑자기 나온거지?
바로 App Standby Bucket에서 나온 단계로 power 관리 기능이다
App Standby Bucket이란 안드로이드 시스템이 앱을 처리하는 우선순위를 아래와 같이 크게 다섯 가지로 분류하는 기능이다. (Active, Working set, Frequent, Rare, Never)
사용자가 앱을 얼마나 자주 사용하는지에 따라 각 버킷으로 이동하게 되며 정확한 기준은 (어뷰징을 생각한다면 당연히) 알려져있지 않다.
한 가지 주의할 부분은 앱이 어느 버킷에 있느냐에 따라 FCM 수신 시의 동작이 달라진다는 점이다.
보통 도즈 모드에 진입 시 우선순위가 high로 지정된 FCM을 받으면 앱이 깨어나는 것으로 알려져있으나, 앱이 어느 버킷에 있느냐에 따라 하루에 받을 수 있는 high priority FCM 개수가 달라지게 된다.
Active: 제한 없음
Working set: 제한 없음
Frequent: 하루 10개
Rare: 하루 5개
출처 : https://developer.android.com/topic/performance/power/power-details.html
Android 12에서 restriceted app stanby bucket에 대해 런칭했고 Android 13에서 새로운 restricted level로 확장시켰다. 알다시피 이 레벨에서는 jobs, alarm를 매우 제한적으로 수용한다.
이 레벨에서 앱은 포그라운드 서비스를 가지면 안되고 백그라운드에서 work을 돌려야한다.
오직 user select으로 제한시킬 수 있다.
Android 13에서 JobScheduler에 새로운 API가 추가 됐다. JobScheduler가 배터리 효율성과 수명에 집중할 수 있도록 개선사항이 들어갔다.
(권장 백그라운드 작업 처리 가이드에서도 그렇고 잡스케쥴러는 현재 잘 쓰이고 있진 않지만 온전히 Job을 관리하는데 있어서 아직까지 쓰는 거 같다 부록 -> 게시물)
앱이 여러개 job을 execute할 준비하고 있을 때, 앱 속 job에 있는 priority API
가 도와줄 수 있다.
이 API는 앱들 사이에서 job들을 정렬하는데에만 쓰이는게 아니라 JobScheduler에서도 이 우선순위를 가지고 시스템에서 쓸 리소스가 적을 때 어떤 job을 가장 먼저 멈추게할지 결정하는데 사용할 수 있다.
예를 들면, JobScheduler는 이 api로 하여금 device가 너무 뜨거워지는 걸 일찍 막기 위해 thermal stress나 stopping response로 개선시킬 수 있다. JobScheduler는 device가 가열되면 낮은 우선순위를 갖고 있는 job을 가장 먼저 멈추게 할 수 있고 높은 우선순위를 가진 job도 멈추게할 수 있다.
왜 모든 잡들에 높은 우선순위를 부여하면 안될까?
1) 에티켓이 아니기 때문 -> 사용자 배터리 측면에서 효율적이 아님
2) 높은 우선순위를 가지되 short-term이 있고 low 우선순위를 가지되 긴 작업을 하는 job이 있기 때문에 잘못된 상황에서 높은 우선수위를 가진 job을 사용할 수 있기 때문에
3) 공평하게 모든 job들에게 높은 우선순위를 부여해도 딱히 장점이 없기 때문에
네트워크 트래픽 관리를 위해 최소 데이터 양을 설정할 수 있다. JobScheduler가 네트워크를 이용하는데 더 스마트하게 도와줄 것이다.
JobInfo.Builder.setPriority()
JobInfo.Builder.setMinimumNetworkChunkBytes()
본래 Notification(알림)에 관해 permission을 받지 않았는데 새롭게 퍼미션이 추가됐다.
또한, 포그라운드 서비스를 이용할 때 무조건 Notification을 띄어줘야 했는데, 포그라운드 서비스와 관련된 알림이 더 이상 표시되지 않을 수 있다.
foreground service와 연관된, notification의 시각화가 중요한 기능에서는 사용자가 swipe away
로 이 notifications들을 날릴 수 있다. 그치만 사용자가 개발자들에게 모두 popular한 피쳐일 때를 위해 Android 13에서 새로운 것을 추가했다.
target SDK에 관계없이 포그라운드 서비스의 Notification을 사용자가 stop 시킬 수 있다.
Task Manager
은 stop button을 제공해서 포그라운드에서 호스팅하는 것을 사용자가 stop할 수 있도록 허락한다. 완전히 정지하는 것과 달리, 앱들의 jobs, alarms는 유지될 것이다.
time-critical과 user-visibilty를 위해서 우선순위를 높게해서 FCM을 사용했는데 이들의 우선순위를 코드로 다운그레이드 할 수 있다.
Practice Etiquette:
Don't eat all the energy bars
배터리의 모든 리소스가 본인만의 앱을 위해서만 소비되면 안된다! 야금야금 효율적으로 써야지 혼자 다 쓰면 안된다. 모바일의 리소스는 극도로 한계가 있기 때문에 잘 관리해야한다.
몇 가지를 통해 어떻게 에너지를 혼자 독식하지 않고 효율적으로 쓰는지 알아보자.
WorkManager 많은 피쳐와 장점이 있기 때문에 백그라운드 work를 할 때 배터리를 아끼기에 좋다.
work을 취소하고 stop할 때 cleanup하는 로직을 넣을 수도 있다.
모노리틱한 작업요청을 만들어서 하는 대신에 리소스들을 그룹핑해서 무척 작은 작업들도 요청이 가능하다
상황을 가정해보자, 나는 분명 무음을 해놓았는데 수업 중간에 진동이 울린다 Brrrr
당연히 급한 전화겠지?하고 받았는데 그냥 친구가 아래와 같다면 기분이 어떨까?
ME : Hey What's going on?
Friend : Nothin~ just wanted to say HI!
Me : .. Kidding me?
이 상황을 HP FCM에 비유해보자면, 우선 순위가 높을 만한 FCM이 아닌데 높은 FCM이면 이럴 것이다.
그래서 개발자들은 높은 우선순위를 사용하고자 하면 잘 생각해보고 현명하게 써야 한다. 이 메세지들이 사용자에게 정말 high-priority message가 맞는지
가장 좋은 방법은 사용자에게 이 notification 메세지로 방해하는 것이 맞는지 고려해보는 것이다. interrupt해서 보여줘야 한다면 높은 우선 순위를 할당해서 쓰면 되는데, 그냥 시간이 지난 후 확인해도 되는 메세지면 regular FCM을 사용하자.
왜냐하면 High-priority는 doze 모드와 저전력 모드인 CPU를 깨우기 때문이다.
어떤 앱들은 external systems랑 연동되어있다. 예를 들면 Home IoT를 쓰거나 등등
어떤 것들은 웹 서버에서 데이터를 갖고 오거나 사용자의 Home Net을 이용해 IoT 데이터를 읽는다. 만약 백그라운드에서 데이터를 가져오는 작업을 할 때 앱에서 자주 data를 refreshing하면 안된다고 이해하는게 매우 중요하다.
예를 들어 매초 서버에 쿼리를 날려서 실행하는게 적합한가? IoT 센서들은 5초마다 데이터를 읽어야 유용한가? 이런 것들은 actionable rate가 무엇인지 생각해보는게 좋다.
리프레싱 데이터들은 유저가 무엇을 하는 것보다 빠르게 변화한다고 해도 이 change는 리소스를 효율적으로 사용못한다.
스캔 모드에 따라 배터리 효율성도 다르다. 상황이나 기능에 맞게 적절하게 선택해서 쓰자
1)
디바이스들은 power을 많이 쓸 수록 점점 뜨거워진다.
그래서 안드로이드는 GPU나 CPU처럼 메카니즘을 built-in했는데 온도가 올라가는 것을 점차 막기 위해서 throttiling 비슷한 로직이 있다.
2)
Camera X API를 사용하자. 배터리를 효율적으로 쓸 수 있다.
3)
frame api를 이용해 디스플레이를 스무싱하게 표현할 수 있다. 특히 게임앱들은 이 api를 이용해 frame을 setting할 수 있다.
분명 영상을 한 번 보고 정리를 했는데도 중구난방으로 정리된 거 같다. 축약하고 쳐낼 건 쳐냈는데도 영어권이 아니라서 그런가 읽고 해석하고 정리하는데 시간이 걸린 거 같다. 그래도 덕분에 안드로이드가 배터리 효율성을 위해 사용자와 개발자들을 생각하는 지점들을 알 수 있어서 좋았다.
해당 글은 시간이 나면 천천히 더 정리를 해볼 생각이다..