<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, "Courier New", 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 > 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, "Courier New", 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 > bugreport.txt</div>
<div>//通过historian图形化展示结果</div>
<div>python historian.py -a bugreport.txt > 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>监控信息—> 系统关心什么,我们就监控什么(后台耗电监控 ) <span style=”position: absolute;”>Alarm wakeup、WakeLock、WiFi
scans、Network</span></div>
</li>
<li>
<div>现场信息—> 完整的对栈信息</div>
</li>
<li>
<div>提炼规则—->将监控的内容抽象成规则</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, "Courier New", 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), "mService", this);</div>
<div>@Override</div>
<div>public void beforeInvoke(Method method, Object[] args) {</div>
<div> // 申请Wakelock</div>
<div> if (method.getName().equals("acquireWakeLock")) {</div>
<div> if (isAppBackground()) {</div>
<div> // 应用后台逻辑,获取应用堆栈等等 </div>
<div> } else {</div>
<div> // 应用前台逻辑,获取应用堆栈等等</div>
<div> }</div>
<div> // 释放Wakelock</div>
<div> } else if (method.getName().equals("releaseWakeLock")) {</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, "Courier New", 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), "mService", 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("set")) {</div>
<div> // 不同版本参数类型的适配,获取应用堆栈等等</div>
<div> // 清除Alarm</div>
<div> } else if (method.getName().equals("remove")) {</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, "Courier New", 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>
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/272762.html