Android 전량 통계 원리, 알고리즘 과 소모 분석 최적화 총 결
1. 전량 값 의 획득 과 계산
우선 각 소프트 하드웨어 의 전력 소비량 계산 을 설명 하 다.만약 에 설비 (예 를 들 어 와 이 파이) 단위 시간 내 에 소모 하 는 전기량 이 w 이 고 운행 시간 이 t 라면 그 동안 의 전기 소모량 은 W = w * t 이다.물리학 에서 의 지식 에 따 르 면 전력 (즉 전량) 계산 공식 은 W = UIt 이 고 그 중에서 U 는 전압 값 이 며 I 는 전류 값 이 며 t 는 운행 시간 이다.한 기계 에서 전압 값 U 는 고정 적 으로 변 하지 않 기 때문에 매개 변수 U 를 무시 하고 전류 와 시간 을 통 해 전기량 (예 를 들 어 배터리 용량 은 2000 mA, 2500 mA 등 으로 mA 단위 로 항량) 을 표시 할 수 있다.상기 설명 에 따 르 면 우리 가 특정한 프로그램 이나 특정한 설비 가 운행 하 는 시간, 그리고 그 운행 에 필요 한 전류 값 을 얻 으 면 그 소모 하 는 전기량 (상기 이론 은 코드 에 나타 날 것 이다) 을 계산 할 수 있다.
한 프로그램 이나 하드웨어 장치 의 운행 시간 은 Battery Stats. Uid. Proc 와 Battery Stats Impl 의 관련 인 터 페 이 스 를 통 해 얻 을 수 있 습 니 다. 여 기 는 주로 전류 값 (즉 단위 시간 소모 전력) 을 말 합 니 다.
a. PowerProfile.java ./frameworks/base/core/java/com/android/internal/os/PowerProfile.java
코드 에서 몇 십 가지 서로 다른 장치 의 전기 소모 유형 을 정의 합 니 다.
/** * No power consumption, or accounted for elsewhere. */ public static final String POWER_NONE = "none;
/** * Power consumption when CPU is in power collapse mode. */ public static final String POWER_CPU_IDLE = "cpu.idle"; public static final String POWER_CPU_AWAKE = "cpu.awake"; /** * Power consumption when CPU is in power collapse mode. */ @Deprecated public static final String POWER_CPU_ACTIVE = "cpu.active"; public static final String POWER_WIFI_SCAN = "wifi.scan"; public static final String POWER_WIFI_ON = "wifi.on"; public static final String POWER_WIFI_ACTIVE = "wifi.active"; public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle"; public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx"; public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx"; public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage"; public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle"; public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx"; public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx"; public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE = "bluetooth.controller.voltage"; public static final String POWER_GPS_ON = "gps.on"; public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; public static final String POWER_SCREEN_ON = "screen.on"; public static final String POWER_RADIO_ON = "radio.on"; public static final String POWER_RADIO_SCANNING = "radio.scanning"; public static final String POWER_RADIO_ACTIVE = "radio.active"; public static final String POWER_SCREEN_FULL = "screen.full"; public static final String POWER_AUDIO = "dsp.audio"; public static final String POWER_VIDEO = "dsp.video"; public static final String POWER_FLASHLIGHT = "camera.flashlight"; public static final String POWER_CAMERA = "camera.avg"; public static final String POWER_CPU_SPEEDS = "cpu.speeds"; public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan"; public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
(1)public double getAveragePower(String type)
이 방법 은 type 서브 시스템 에서 소모 하 는 전류 값 을 되 돌려 줍 니 다. 단 위 는 mA 입 니 다.type PowerProfile 에서 정의 하 는 상수 값, POWER 포함CPU_IDLE (CPU 가 비어 있 을 때), POWERCPU_ACTIVE (CPU 가 활성 상태 일 때), POWERWIFI_ON (와 이 파이 오픈 시) 등 다양한 상태.예 를 들 어 getAveragePower (POWER CPU ACTIVE) 를 호출 하면 CPU 가 활동 할 때의 전류 값 을 되 돌려 줍 니 다.getAveragePower (POWER WIFI ON) 는 WIFI 시작 상 태 를 유지 하 는 데 필요 한 전류 값 을 되 돌려 줍 니 다.이전 설명 과 결합 하여 와 이 파이 가 켜 진 시간 이 t (이 기간 에 와 이 파이 전송 데 이 터 를 사용 하지 않 았 다 고 가정 하면 와 이 파이 전송 데 이 터 는 추가 적 인 전기 에너지 소모 가 필요 하기 때 문) 이 라 고 가정 하면 이 기간 동안 와 이 파이 가 소모 하 는 전 기 는 W = t * getAverage Power (POWER WIFI ON) 입 니 다.
(2) public double getAveragePower(String type, int level)
방법 (1) 에 비해 이 인 터 페 이 스 는 인자 level 을 입력 해 야 합 니 다. 이제 level 의 의 미 를 설명 하 겠 습 니 다.우 리 는 안 드 로 이 드 시스템 에서 CPU 가 여러 가지 속도 로 운행 할 수 있다 는 것 을 알 고 있다. (가설 은 각각 600 MHz, 800 MHz, 1GHZ 등) 속도 가 다 르 고 CPU 가 소모 하 는 전기량 도 다르다. 매개 변수 level 은 서로 다른 운행 빈 도 를 대표 한다. 분명 한 방법 getAveragePower (String type, int level) 는 type 서브 시스템 이 CPU 운행 속도 등급 이 level 일 때 단위 시간 내 에 소모 하 는 전기량 을 되 돌려 줄 것 이다.(즉 전류 값).
(3)public double getBatteryCapacity() 배터리 총 전량 가 져 오기.
(4)public int getNumSpeedStepsInCpuCluster(int index) CPU 를 가 져 오 면 몇 가지 속도 로 실행 할 수 있 습 니 다.
b. power_profile.xml
사실 PowerProfile. java 코드 및 관련 주석 을 읽 어 보면 알 수 있 듯 이, 이러한 인터페이스 에서 되 돌아 오 는 전류 등 수 치 는 모두 power profile. xml 파일 을 읽 어 얻 은 것 으로, 즉 각종 서브 시스템 이 소모 하 는 전력량 값, CPU 운행 속도 값, 총 전력량 등 정 보 는 모두 고정 값 으로 power profile. xml 에 저 장 됩 니 다. 하드웨어 간 의 차이 로 인해 각 서브 시스템 은전력 소모 정 보 는 다 르 기 때문에 이 파일 은 각 생산 업 체 가 맞 춤 형 으로 만들어 야 합 니 다. 안 드 로 이 드 시스템 의 네 이 티 브 power profile. xml 파일 의 저장 경 로 는 frameworks / base / core / java / com / android / internal / os / PowerProfile. java 입 니 다. 각 하드웨어 업 체 의 맞 춤 형 을 거 친 후 저장 경로 가 달라 질 수 있 습 니 다. 예 를 들 어 8952 의 power profile. xml 경로:. / device / qcom / msm 8952 64 / overlay / frameworks / base / core / res / res / xml / power profile. xml, 그 내용 은 다음 과 같다.
0
80
300
5
0.1
3
200
100
10
50
200
650
180
42
50
2
1
4
4
cpu.speeds.cluster0">
400000
691200
806400
1017600
1190400
1305600
1382400
1401600
cpu.active.cluster0">
180
210
260
300
400
480
510
540
cpu.speeds.cluster1">
400000
883200
940800
998400
1056000
1113600
1190400
1248000
1305600
1382400
1612800
1747200
1804800
180
230
250
310
330
360
390
410
440
460
500
550
600
18
3000
.0002
.002
.02
.2
2
퀄 컴 MSM 8952 는 여전히 8 핵심 Cortex - A53 구조 로 설계 되 어 있 으 며, 그 중에서 '큰 핵' 부분의 네 개의 핵심 주파 수 는 최고 1.7GHz 이 고, '작은 핵' 부분의 네 개의 핵심 주파 수 는 최고 1.2GHz 이다. 따라서 power profile. xm 에서 이 모델 기 계 는 두 개의 cluster (0, 1) name = 'cpu. speeds. cluster 0' 과 두 개의 cluster 에서 서로 다른 속도 로 전력 소비량 name = 'cpu. active. cluster 0' 을 배치 하 였 다."。
1 ,PowerProfile.java power_profile.xml 。 ,PowerProfile.java power_profile.xml , 。 , 。
2. 공비 의 계산 방법 을 활용 한다.
App :processAppUsage() :processMiscUsage()
:App :processAppUsage()
processAppUsage ~ App 。
for , processAppUsage Uid。
Uid App :2 App sharedUserId , , Uid。 processAppUsage App , App, , Android 。
- 1: Uid Process , 。
Uid_Power1 = (Process1_Power + … + ProcessN_Power);
Process1_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);
....
ProcessN_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);
uid pid cpu * power_profile.xml
19
....
cpu cpu.active 。
- 2: Uid wake lock
,Android partial wake lock 。
Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE (power_profile.xml - 70
)
- 3: Uid (data traffic)
Uid_Power3 = (app.mobileActive * mPowerRadioOn) / (1000*60*60)
Uid_Power3 = (app.mobileRxPackets + app.mobileTxPackets)
* getMobilePowerPerPacket(rawRealtimeUs, statsType)
- 4: Uid WIFI 。
Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON (power_profile.xml - 4
)
Uid_Power5 = wifiScanTimeMs * POWER_WIFI_SCAN (power_profile.xml - 88
)
Uid_Power6 = batchScanTimeMs * POWER_WIFI_BATCHED_SCAN (power_profile.xml )
- 5: Uid 。
Uid_Power7 = (Sensor1_Power + … + SensorN_Power)
Sensor_Power = Sensor_Time * Power_Sensor
App :
Uid_Power(App , :mAh) = Uid_Power1 + Uid_Power2 + Uid_Power3 + Uid_Power4 + Uid_Power5 +Uid_Power6 +Uid_Power7
Uid_Power1 = (Process1_Power + … + ProcessN_Power);
Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE
Uid_Power3 = (app.mobileActive * mPowerRadioOn) / (1000*60*60)
Uid_Power3 = (app.mobileRxPackets + app.mobileTxPackets)
* getMobilePowerPerPacket(rawRealtimeUs, statsType)
Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON
Uid_Power5 = wifiScanTimeMs * POWER_WIFI_SCAN
Uid_Power6 = batchScanTimeMs * POWER_WIFI_BATCHED_SCAN
Uid_Power7 = (Sensor1_Power + … + SensorN_Power)
:
partial wake lock wake lock
if (num != 0) {
for (int i=0; i
wakelock cpu , uid
Proc *wakelock*:
CPU: 3s 40ms usr + 5s 50ms krn ; 0ms fg
。
app , uid 。
3. 공비 문제 분석 포 지 셔 닝 과 최적화
a.
,adb dumpsys bugreport > bugreport.txt/ adb dumpsys batterystats > batterystats.txt, 。
b. :
1). Estimated power use (mAh)
Estimated power use (mAh):
Capacity: 3000, Computed drain: 792, actual drain: 1320-1350
:3000 mAh, :792 mAh, :1320mAh
:( , , 。 powerprofile.txt 。 , , )
Unaccounted: 528 // :528 mAh
Screen: 136 // :136 mAh
Uid u0a151: 111
u0a151 uid :
u0a151:
Mobile network: 73.29KB received, 103.96KB sent (packets 1040 received, 1343 sent)
Mobile radio active: 3h 35m 21s 572ms (32.6%) 22x @ 5422 mspp
Wi-Fi network: 172.93KB received, 202.58KB sent (packets 1836 received, 2450 sent)
Wifi Running: 0ms (0.0%)
Full Wifi Lock: 0ms (0.0%)
Wifi Scan: 21s 6ms (0.1%)
Wake lock PushService: 2s 677ms partial (29 times) realtime
Wake lock *sync*/com.sina.weibo.sync.authority/com.sina.weibo.account/Letv_RaykinX: 1m 12s 246ms partial (9 times) realtime
Wake lock *alarm*: 3s 568ms partial (15 times) realtime
TOTAL wake: 1m 18s 491ms partial realtime
Sync com.sina.weibo.sync.authority/com.sina.weibo.account/Letv_RaykinX: 2m 1s 556ms realtime (10 times)
Foreground activities: 852ms realtime (1 times)
Foreground for: 2h 39m 59s 616ms
Active for: 11h 8m 38s 330ms
Proc com.sina.weibo:remote:
CPU: 44s 830ms usr + 13s 710ms krn ; 0ms fg
6 proc starts
Proc *wakelock*:
CPU: 24s 550ms usr + 4s 920ms krn ; 0ms fg
Proc com.sina.weibo:
CPU: 45s 280ms usr + 12s 230ms krn ; 410ms fg
6 proc starts
111 mAh, UID ,
Uid 1000: 95.2
Uid 0: 82.8
Cell standby: 66.7 // :66.7 mAh
Uid u0a116: 64.3
Idle: 50.8 // :50.8 mAh
Estimated power use , log , log 。 。
2).
(1)
Uid_Power3 uid , Mobile radio active: 3h 35m 21s 572ms (32.6%) 22x
@ 5422mspp(packets 1040 received, 1343 sent) 2000 。
eg: u0a151:
Mobile network: 73.29KB received, 103.96KB sent (packets 1040 received, 1343 sent)
Mobile radio active: 3h 35m 21s 572ms (32.6%) 22x @ 5422 mspp
(2). wake lock ( kernel )
kernel partial 。
eg: All kernel wake locks:
Kernel Wake lock DIAG_WS : 1h 45m 10s 261ms (269788 times) realtime
kernel DIAG_WS 1h 45m 10s 261ms , (269788 times) 。
eg: All partial wake locks:
Wake lock 1000 LocationService: 15h 17m 27s 726ms (1 times) realtime
partial LocationService ,LocationService TAG , 15h 17m 27s 726ms,(1 times) 。
eg: All wakeup reasons:
Wakeup reason unknown: 656ms (7 times) realtime
Wakeup reason Abort:Last active Wakeup Source: eventpoll: 454ms (1 times) realtime
,454ms , (1 times) 。
(0 times) 。
(3). sensor sensor
:sensor handle 。
adb shell dumpsys sensorservice > sensorservice.log
finger wakeup sensor| Qualcomm Technologies, Inc.| version=1 |android.sensor.wake_gesture| 0x0000002b | "" | type=23 | one-shot | maxDelay=0us |minDelay=0us |no batching | wakeUp | last=<>
eg: 1000:
Sensor 43: 8h 10m 44s 804ms realtime (60 times)
sensor 43 sensor hanldle 16 0x0000002b, type=23,sensor :android.sensor.wake_gesture
gps uid Sensor GPS: 9h 13m 25s 124ms
eg: u0a117:
Wi-Fi network: 358.49KB received, 97.48KB sent (packets 610 received, 658 sent)
Wifi Running: 0ms (0.0%)
Full Wifi Lock: 0ms (0.0%)
Wifi Scan: 5s 765ms (0.0%)
Wake lock *alarm*: 671ms partial (29 times) realtime
Wake lock LocationManagerService realtime
TOTAL wake: 671ms partial realtime
Sensor GPS: 9h 13m 25s 124ms realtime (0 times)
Foreground for: 9h 13m 25s 124ms
Proc com.tencent.mobileqq:
CPU: 16s 150ms usr + 4s 410ms krn ; 0ms fg
3 proc starts
Proc com.tencent.mobileqq:MSF:
CPU: 7s 0ms usr + 2s 70ms krn ; 0ms fg
Apk com.tencent.mobileqq:
39 wakeup alarms
Service com.tencent.mobileqq.app.CoreService$KernelService:
Created for: 14m 46s 370ms uptime
Starts: 2, launches: 2
Service com.tencent.mobileqq.app.CoreService:
Created for: 14m 46s 849ms uptime
Starts: 2, launches: 2
(4). cpu 。
:android uid 0 uid 1000 cpu 。
0:
Proc kworker/u16:0:
CPU: 0ms usr + 38m 27s 10ms krn ; 0ms fg
Proc kworker/u16:1:
CPU: 0ms usr + 39m 33s 120ms krn ; 0ms fg
Proc kworker/u16:2:
CPU: 0ms usr + 29m 15s 210ms krn ; 0ms fg
Proc kworker/u16:3:
CPU: 0ms usr + 39m 28s 140ms krn ; 0ms fg
Proc kworker/u16:4:
CPU: 0ms usr + 41m 56s 730ms krn ; 0ms fg
Proc kworker/u16:5:
CPU: 0ms usr + 33m 24s 810ms krn ; 0ms fg
。 cpu , 。
3). 硬件功耗高的定位方式
对应硬件使用的时间如下所示: Statistics since last charge:
System starts: 0, currently on battery: true
Time on battery: 9h 13m 25s 124ms (100.0%) realtime, 34m 58s 669ms (6.3%) uptime // Time on battery-->统计运行的总时间9h 13m 25s 124ms
Time on battery screen off: 8h 59m 14s 895ms (97.4%) realtime, 20m 48s 441ms (3.8%) uptime //
Time on battery screen off-->统计灭屏的时间8h 59m 14s 895ms
Total run time: 9h 13m 25s 83ms realtime, 34m 58s 628ms uptime
Battery time remaining: 1d 12h 8m 1s 242ms
Start clock time: 2018-02-16-21-09-37
Screen on: 14m 10s 229ms (2.6%) 2x, Interactive: 14m 9s 947ms (2.6%)
Time on battery screen off-->统计灭屏的时间8h 59m 14s 895ms
Screen brightnesses:
dark 4m 6s 686ms (29.0%)
dim 10m 3s 543ms (71.0%)
屏幕量度分等级:统计电量。
对于屏幕会有两部分计算的和组成:
屏幕亮屏的时间(根据屏幕的状态来获取时间长度) * power_profile.xml中配置的
- 80
+ 屏幕亮度等级持续的时间(屏幕亮度分为5个等级:分别计算5个等级的亮度对应的时间)* power_profile.xml中配置的- 300
Total full wakelock time: 2m 8s 857ms
Total partial wakelock time: 11m 8s 140ms
申请锁的时间一种是full wakelock 一种是partial wakelock。目前电量的统计中只统计partial wakelock这个锁的耗电。
Mobile total received: 0B, sent: 0B (packets received 0, sent 0)
Phone signal levels:
moderate 29s 773ms (0.1%) 5x
good 9h 7m 51s 689ms (99.0%) 13x
great 5m 3s 662ms (0.9%) 8x
Signal scanning time: 0ms
Radio types:
none 9h 13m 23s 439ms (100.0%) 1x
lte 1s 685ms (0.0%) 1x
Mobile radio active time: 0ms (0.0%) 0x
这部分是移动网络待机的耗电详细情况,计算方式如下:
移动网络待机--耗电统计:
1.信号在不同强弱等级持续的时间 * power_profile.xml中配置的
3.4
3.4
2.搜索网络的时间 * power_profile.xml中配置的
- 80
3.(使用数据流量上传下载的时间 - 每一个应用上传下载数据包所用的时间) * power_profile.xml中配置的
- 170
三部分总体的功耗作为移动网路待机耗电统计.
对应的类型:BatterySipper.DrainType.CELL
Wi-Fi total received: 19.88MB, sent: 1.19MB (packets received 18726, sent 13286)
Wifi on: 2h 42m 39s 290ms (29.4%),
Wifi running: 9h 13m 24s 969ms (100.0%)
Wifi states: (no activity)
Wifi supplicant states:
associating 3ms (0.0%) 1x
associated 3ms (0.0%) 1x
4-way-handshake 7ms (0.0%) 1x
group-handshake 45ms (0.0%) 1x
completed 9h 13m 25s 66ms (100.0%) 1x
Wifi signal levels: level(1) 9s 26ms (0.0%) 2x level(2) 5m 50s 226ms (1.1%) 22x level(3) 9h 7m 25s 872ms (98.9%) 20x
Wifi的功耗统计详情统计wifi的耗电量会减掉每个应用消耗的wifi的电量,并且不包含wifi扫描消耗电量的统计。
Bluetooth on: 0ms (0.0%)
Bluetooth states: (no activity)
蓝牙的功耗统计详情。
补充两个算法:
手机待机---耗电统计:
(统计的耗电总时间 - 屏幕亮屏的时间 )* power_profile.xml中配置的
- 18
对应的类型:BatterySipper.DrainType.IDLE语音通话---耗电统计: TelephonyRegistry.java -> broadcastCallStateChanged -> 电话的状态为CALL_STATE_RINGING 和CALL_STATE_OFFHOOK时统计的时间 * power_profile.xml中配置的
- 180
对应的类型:BatterySipper.DrainType.PHONE
4). Battery History 。 Battery History (1% used, 30KB used of 2048KB, 156 strings using 10084): 0 (9) RESET:TIME: 2016-02-16-21-09-37 +1s793ms (2) 100 f0500018 +wake_lock_in=1000:"*walarm*:com.android.server.WifiManager.action.START_SCAN" +1s793ms---> , 100 --> , +wake_lock_in 。"*walarm*:com.android.server.WifiManager.action.START_SCAN" AlarmManager tag。 +1s793ms (2) 100 f0500018 -wake_lock_in=1000:"*walarm*:com.android.server.WifiManager.action.START_SCAN" +1s793ms---> , 100 --> , -wake_lock_in 。 *walarm* alarm alarm , alarm 。 。 , 。 , ,BatteryHistory , ( ) , , , 。
5). bugreport.txt :https://github.com/google/battery-historian , 。 1). Kernel Overhead Time , 。 2). Kernel wakesources kernel , 。 3). Userspace partial wakelocks partial wakelock , 。 4). Historian 2.0 。 : 1、CPU running 。 2、Partial wakelock Partial 。 3、Screen 4、Brightness 。( 5 ) 5、SyncManager app sync 。 sync。 6、Wifi scan wifi 。 7、Mobile radio 。 8、Data connection , 。 9、Signal strength ( )。 10、Network connectivity , (TYPE_WIFI, TYPE_MOBILE)。 11、Sensor sensor 。 12、Top app app , 。 13、Foreground process 。 14、Active process 。 15、Wifi running wifi 。 16、Wifi on wifi 。 17、charging status 。 18、Audio 。 19、Phone call 。 20、Phone scanning 。 21、 , , 。 22、 , 。
첨부: Android Battery StatService 코드 구조 와 절 차 를 완전 하 게 소개 하 는 글 을 발견 하여 공유 합 니 다.
https://blog.csdn.net/Gaugamela/article/details/52931949 Android7.0 BatteryStatsService
https://blog.csdn.net/feitian_666/article/details/51780946 하드웨어 각도 와 저층 에서 공비 최적화 에 대한 총 결 건 의 를 하 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.