Android开发

Android 功耗测试

本文主要是介绍Android 功耗测试,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
<head> <title>Evernote Export</title> <basefont face="微软雅黑" size="2" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta name="exporter-version" content="YXBJ Windows/605061 (zh-CN, MWS); Windows/10.0.0 (Win64); EDAMVersion=V2;" /> <meta name="reminder-order" content="2022/5/20 1:31" /> <style> body, td { font-family: 微软雅黑; font-size: 10pt; } </style> </head> <body> <a name="792" /> <div> <span> <div> <div> <div> <div> <div>电池</div> <ul> <li> <div>电池容量,电池容量越大手机越笨重</div> </li> <li> <div>充电时间。低电压高电流,高电压低电流</div> </li> <li> <div>寿命</div> </li> <li> <div>安全性</div> </li> </ul> <div>硬件</div> <ul> <li> <div>处理器芯片</div> </li> <ul> <li> <div><span style="font-weight: bold;">CPU</span>,<span style="font-size: unset; color: unset; font-family: unset;">GPU,</span><span style="font-size: unset; color: unset; font-family: unset;">NPU</span></div> </li> </ul> <li> <div>基带芯片</div> </li> <ul> <li> <div><span style="font-weight: bold;">蜂窝网</span>,<span style="font-size: unset; color: unset; font-family: unset;"><span style="font-size: unset; color: unset; font-family: unset; font-weight: bold;">WIFI</span>,</span><span style="font-size: unset; color: unset; font-family: unset;">NFC</span></div> </li> </ul> <li> <div>传感器</div> </li> <ul> <li> <div>加速度传感器,<span style="font-size: unset; color: unset; font-family: unset;">陀螺仪,</span><span style="font-size: unset; color: unset; font-family: unset;">气压计,</span><span style="font-size: unset; color: unset; font-family: unset;">温度传感器</span></div> </li> </ul> <li> <div>外设</div> </li> <ul> <li> <div>相机,<span style="font-size: unset; color: unset; font-family: unset;">麦克风,</span><span style="font-size: unset; color: unset; font-family: unset;">扬声器</span></div> </li> </ul> <li> <div>其他</div> </li> <ul> <li> <div>GPS,<span style="font-size: unset; color: unset; font-family: unset;">内存,</span><span style="font-size: unset; color: unset; font-family: unset;"><span style="font-size: unset; color: unset; font-family: unset; font-weight: bold;">显示屏</span>,</span><span style="font-size: unset; color: unset; font-family: unset;">闪存</span></div> </li> </ul> </ul> <div>资源调度机制是厂商功耗优化的最重要的手段,手机基带,GPS,这些模块在不使用时也会进入低功耗或休眠模式,达到降低功耗的目的。</div> <div>手机厂商为了保证头部应用能有更好的体验,厂商愿意给他们分配更多的资源</div> <div><a href="https://developer.qualcomm.com/software/snapdragon-power-optimization-sdk/quick-start-guide">https://developer.qualcomm.com/software/snapdragon-power-optimization-sdk/quick-start-guide</a> </div> <div><br /></div> <div><span style="font-weight: bold;">软件</span></div> <div><span style="font-weight: bold;">   </span> 如何评估软件的耗电情况: 电能 = 电压 * 电流 * 时间</div> <div>        手机的电压一般恒定,Adnroid 系统要求厂商必须在/frameworks/base/core/res/xml/power_profile.xml提供组件的电源配置文件</div> <div>        如何在不同厂商中获取耗电流</div> <ol> <li> <div>从手机中导出 /system/framework/framework-res.apk 文件</div> </li> <li> <div>使用反编译工具对导出文件framework-res.apk 进行反编译</div> </li> <li> <div>查看power_profile.xml 文件在frame-res 反编译目录路径: /res/xml/power_profile.xml</div> </li> </ol> <div><a href="https://source.android.com/devices/tech/power">https://source.android.com/devices/tech/power</a> </div> <div><a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/xml/power_profile.xml">https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/xml/power_profile.xml</a> </div> <div>对于系统的电量消耗情况,可以通过dumpsys   batterystatus 导出</div> <div><br /></div> <div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"> <div>adb shell dumpsys batterystats &gt; battery.txt</div> <div>// 各个Uid的总耗电量,而且是粗略的电量计算估计。</div> <div>Estimated power use (mAh):</div> <div>    Capacity: 3450, Computed drain: 501, actual drain: 552-587</div> <div>    ...</div> <div>    Idle: 41.8</div> <div>    Uid 0: 135 ( cpu=103 wake=31.5 wifi=0.346 )</div> <div>    Uid u0a208: 17.8 ( cpu=17.7 wake=0.00460 wifi=0.0901 )</div> <div>    Uid u0a65: 17.5 ( cpu=12.7 wake=4.11 wifi=0.436 gps=0.309 )</div> <div>    ...</div> <div>// reset电量统计</div> <div>adb shell dumpsys batterystats --reset</div> </div> <div><br /></div> </div> <div> <div><br /></div> <table style="border-collapse: collapse; min-width: 100%;"> <colgroup> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> </colgroup> <tbody> <tr> <td style="background-color: rgb(115, 115, 115); border: 1px solid rgb(92, 92, 92); width: 130px; padding: 8px;"> <div><span style="color: rgb(255, 255, 255);">编号</span></div> </td> <td style="background-color: rgb(115, 115, 115); border: 1px solid rgb(92, 92, 92); width: 130px; padding: 8px;"> <div>测试方法</div> </td> <td style="background-color: rgb(115, 115, 115); border: 1px solid rgb(92, 92, 92); width: 130px; padding: 8px;"> <div>适用场景</div> </td> <td style="background-color: rgb(115, 115, 115); border: 1px solid rgb(92, 92, 92); width: 130px; padding: 8px;"> <div>优点</div> </td> <td style="background-color: rgb(115, 115, 115); border: 1px solid rgb(92, 92, 92); width: 130px; padding: 8px;"> <div>缺点</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>1</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>稳压电源+ 电流仪</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>整机电流</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>可以测试整机电流,而且数据精确</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>需要准确硬件工具,测试操作复杂,而且不能准确测试APP消耗电量</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>2</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;">dumpsys batterystats</td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>App电量</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>有耗电量的详细数据</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>结果可读行比较差</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>3</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>系统“耗电排行”</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>APP电量</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>直观,跟用户看到的一致</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>没有详细的数据</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>4</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Battery History</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>App电量</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>结果直观,有耗电量的详细数据</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>适用与Android 5.0及以上系统</div> </td> </tr> </tbody> </table> <div><a href="https://developer.android.com/studio/debug/bug-report">bug report</a>  <a href="https://github.com/google/battery-historian">Battery Historian </a></div> </div> <div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"> <div><br /></div> <div>//7.0和7.0以后</div> <div>$ adb bugreport bugreport.zip</div> <div>//6.0和6.0之前:</div> <div>$ adb bugreport &gt; bugreport.txt</div> <div>//通过historian图形化展示结果</div> <div>python historian.py -a bugreport.txt &gt; battery.html</div> </div> <div>Android 耗电优化历史</div> <ol start="3"> <li> <div>    野蛮生长: Pre   Android 5.0</div> </li> <ol> <li> <div> 耗电与安装应用程序的数量有关,用户安装越多的应用程序,无论是否打开它们,手机耗电都会很快。</div> </li> <li> <div>App耗电量与APP使用时间无关,<span style="position: absolute;">用户希望 App 的耗电量应该与它的使用时间相关,但是有些应用即使常年不打开,依然非常耗电</span></div> </li> <li> <div><span style="position: absolute;"><span style="font-size: unset; color: unset; font-family: unset;">电量问题排查复杂。无论是电量的测量,还是耗电问题的排查都异常艰难。</span></span> <img src="耗电_files/Image.webp" type="image/webp" data-filename="Image.webp" /><span style="position: absolute;"><span style="font-size: unset; color: unset; font-family: unset;">  </span></span></div> </li> </ol> </ol> <div>逐步收紧:Android 5.0 ~ Android 8.0</div> <div>    <a href="https://developer.android.com/about/versions/android-5.0?hl=zh-cn">https://developer.android.com/about/versions/android-5.0?hl=zh-cn</a> </div> <div><img src="耗电_files/Image [1].webp" type="image/webp" data-filename="Image.webp" /></div> <div>Android 6.0 开始~, Google开始着手清理后台应用和广播来进一步省电</div> <ul> <li> <div>省电模式不够省电</div> </li> <li> <div>用户对应用控制力度不够</div> </li> <li> <div><span style="font-size: unset; color: unset; font-family: unset;"> Target API 开发者响应不积极</span></div> </li> </ul> <div>最严格:Android 9.0</div> </div> <div><br /></div> <div><img src="耗电_files/Image [2].webp" type="image/webp" data-filename="Image.webp" /></div> <hr /> <div>耗电优化与线上监控</div> </div> <div><br /></div> <div>耗电优化</div> <ul> <li> <div>后台耗电(厂商预装项目要求最严格的正是应用后台待机耗电)</div> </li> <ul> <li> <div>用户认为应用的耗电量应该是和使用时间有关的</div> </li> <li> <div>Camera, Audio, Video,Bluetooth, Network, Sensor. Radio, Screen,WiFi, CPU, GPS</div> </li> </ul> <li> <div>符合系统规范,让系统认为你耗电是正常的</div> </li> <ul> <li> <div>Android Vitals</div> </li> </ul> </ul> <div>耗电优化难点</div> <ul> <li> <div>缺乏现场,无法复现</div> </li> <li> <div>信息不全,难以定位</div> </li> <li> <div>无法评估结果</div> </li> </ul> <div>耗电优化的方法</div> <ul> <li> <div>常见的耗电方式</div> </li> <ul> <li> <div>某个需求场景</div> </li> <li> <div>代码的Bug</div> </li> </ul> <li> <div>优化方法</div> </li> <ul> <li> <div>利用厂商通道或定时拉去最新消息</div> </li> </ul> </ul> <div>耗电监控</div> <ol> <li> <div>Android  Vistals</div> </li> <li> <div>耗电监控应该监控什么</div> </li> <ol> <li> <div>监控信息---&gt; 系统关心什么,我们就监控什么(后台耗电监控  )   <span style="position: absolute;">Alarm wakeup、WakeLock、WiFi scans、Network</span></div> </li> <li> <div>现场信息---&gt; 完整的对栈信息</div> </li> <li> <div>提炼规则----&gt;将监控的内容抽象成规则</div> </li> </ol> </ol> <div><br /></div> <div> <div><br /></div> <table style="border-collapse: collapse; min-width: 100%;"> <colgroup> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> <col style="width: 130px;"> </col> </colgroup> <tbody> <tr> <td style="background-color: rgb(151, 151, 151); border: 1px solid rgb(121, 121, 121); width: 130px; padding: 8px;"> <div><br /></div> </td> <td style="background-color: rgb(151, 151, 151); border: 1px solid rgb(121, 121, 121); width: 130px; padding: 8px;"> <div><span style="color: rgb(255, 255, 255);">前台规则</span></div> </td> <td style="background-color: rgb(151, 151, 151); border: 1px solid rgb(121, 121, 121); width: 130px; padding: 8px;"> <div><span style="color: rgb(255, 255, 255);">后台规则</span></div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Alarm</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>单个Alarm每小时不能启动超过20次</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>单个Alarm 每小时不能启动超过10次</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>WakeLock</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>单个WakeLock每小时不能超过30分钟或者超过20次</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <ol> <li> <div>WakeLock每 小时不能超过30分钟;</div> </li> <li> <div>单个WakeLock每小时不能超过10分钟或12次 </div> </li> </ol> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Sensor</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>不监控前台sensor使用</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;">每小时使用不能超过30分钟</td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>WIFI scans</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时扫描不允许超过10次</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时扫描不允许超过4次</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Bluetooth scans</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时扫描不能超过10次</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时扫描不允许超过4次</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>GPS</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时使用不能超过30分钟</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时使用不能超过15分钟</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Camera</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>不监控前台相机使用</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;">后台不允许使用相机</td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>Network</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>不监控前台网络耗电</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>每小时后台网络数据量不能超过10MB</div> </td> </tr> <tr> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>CPU</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>不监控前台CPU</div> </td> <td style="width: 130px; padding: 8px; border: 1px solid;"> <div>后台CPU持续超过30分钟</div> </td> </tr> </tbody> </table> <div><br /></div> <div> </div> </div> <div><br /></div> <div><br /></div> <div><span style="font-weight: bold;">如何监控耗电</span></div> <div><span style="font-weight: bold;"> </span></div> <div><span style="font-weight: bold;">Java Hook</span></div> <div><br /></div> <div>    WakeLock</div> <div>    <a href="https://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java">https://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java</a> </div> <div>    <a href="https://developer.android.com/training/scheduling/wakelock">https://developer.android.com/training/scheduling/wakelock</a> </div> <div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"> <div>// 代理PowerManagerService</div> <div>ProxyHook().proxyHook(context.getSystemService(Context.POWER_SERVICE), &quot;mService&quot;, this);</div> <div>@Override</div> <div>public void beforeInvoke(Method method, Object[] args) {</div> <div>    // 申请Wakelock</div> <div>    if (method.getName().equals(&quot;acquireWakeLock&quot;)) {</div> <div>        if (isAppBackground()) {</div> <div>            // 应用后台逻辑,获取应用堆栈等等     </div> <div>         } else {</div> <div>            // 应用前台逻辑,获取应用堆栈等等</div> <div>         }</div> <div>    // 释放Wakelock</div> <div>    } else if (method.getName().equals(&quot;releaseWakeLock&quot;)) {</div> <div>       // 释放的逻辑    </div> <div>    }</div> <div>}</div> </div> <div>Alarm : 用来执行定时的重复任务</div> <ul> <li> <div><a href="https://developer.android.com/training/scheduling/alarms">https://developer.android.com/training/scheduling/alarms</a> </div> </li> <li> <div><a href="https://developer.android.com/reference/android/app/AlarmManager.html#ELAPSED_REALTIME_WAKEUP">https://developer.android.com/reference/android/app/AlarmManager.html#ELAPSED_REALTIME_WAKEUP</a> </div> </li> <li> <div><a href="https://developer.android.com/reference/android/app/AlarmManager.html#RTC_WAKEUP">https://developer.android.com/reference/android/app/AlarmManager.html#RTC_WAKEUP</a> </div> </li> </ul> <div><br /></div> <div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"> <div><br /></div> <div><br /></div> <div>// 代理AlarmManagerService</div> <div>new ProxyHook().proxyHook(context.getSystemService</div> <div>(Context.ALARM_SERVICE), &quot;mService&quot;, this);</div> <div><br /></div> <div><br /></div> <div>public void beforeInvoke(Method method, Object[] args) {</div> <div>    // 设置Alarm</div> <div>    if (method.getName().equals(&quot;set&quot;)) {</div> <div>        // 不同版本参数类型的适配,获取应用堆栈等等</div> <div>    // 清除Alarm</div> <div>    } else if (method.getName().equals(&quot;remove&quot;)) {</div> <div>        // 清除的逻辑</div> <div>    }</div> <div>}</div> </div> <hr /> <div><span style="font-size: unset; color: unset; font-family: unset;">后台CPU</span></div> <div><span style="position: absolute;">对于 GPS 监控,我们可以通过 Hook 代理LOCATION_SERVICE。对于 Sensor,我们通过 Hook SENSOR_SERVICE中的“mSensorListeners”</span></div> <div><span style="font-size: unset;"><br /></span></div> <div><span style="position: absolute;">通过 Hook,我们可以在申请资源的时候将堆栈信息保存起来。当我们触发某个规则上报问题的时候,可以将收集到的堆栈信息、电池是否充电、CPU 信息、应用前后台时间等辅助信息也一起带上</span></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><br /></div> <div><span style="font-weight: bold;">插桩</span></div> <div><br /></div> <div><span style="position: absolute;">写一个基础类,然后在统一的调用接口中增加监控逻辑。以 WakeLock 为例:</span></div> <div><br /></div> <div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"> <div><br /></div> <div>public class WakelockMetrics {</div> <div>    // Wakelock 申请</div> <div>    public void acquire(PowerManager.WakeLock wakelock) {</div> <div>        wakeLock.acquire();</div> <div>        // 在这里增加Wakelock 申请监控逻辑</div> <div>    }</div> <div>    // Wakelock 释放</div> <div>    public void release(PowerManager.WakeLock wakelock, int flags) {</div> <div>        wakelock.release();</div> <div>        // 在这里增加Wakelock 释放监控逻辑</div> <div>    }</div> <div>}</div> </div> <div><br /></div> <div><a href="https://blog.dreamtobe.cn/2016/08/15/android_scheduler_and_battery/">https://blog.dreamtobe.cn/2016/08/15/android_scheduler_and_battery/</a> </div> <div><br /></div> <div><br /></div> <hr /> <div>CTS 测试  :<a href="https://source.android.google.cn/compatibility/cts/run">https://source.android.google.cn/compatibility/cts/run</a> </div> <hr /> <div><br /></div> </div> <div><br /></div> </span> </div> </body>
这篇关于Android 功耗测试的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!