小米17全面评测:性能与续航终极对决
|
亲历现场。那天凌晨三点十七分,我盯着小米17那台工程机屏幕右下角的电池图标——它刚从 23% 跳回 24%,又在半秒后跳成 22%,而后台 ActivityManager 正在疯狂 dump 某个叫“MIUIOptimizeService”的进程栈,堆栈里夹着三行我根本没写过的 Kotlin 协程 suspend 函数名。我原以为是 vendor overlay 层漏了 override,结果翻到 /vendor/overlay/miui-framework-res.apk 里连个 XML 都没动过,最后发现是他们自己系统 app 的一个 broadcast receiver 在 onReceive 里 sleep(十八秒) —— 就为了等“系统稳定性上报服务”启动。我敢打包票,那个 sleep 是手敲进去的,不是生成的,因为注释里写着 // 防止上报太密,影响用户感知。 桌上的机械键盘声一直没停,青轴,咔哒咔哒,像心跳失常。我左手边堆着六台测试机,窗台太窄,最外头那台小米17的金属边框被正午晒了一整天,摸上去发烫,但屏幕冷得像块冰——电量显示正常,温度传感器却报 -5℃,Logcat 里飘着一句 “thermal: sensor invalid, fallback to static value”,fallback 的 static 值还是写死在 BoardConfig.mk 里,跟七年前我第一次适配红米 Note2 时一模一样。楼下便利店关东煮的蒸气从窗缝钻进来,混着一股萝卜味,我闻着闻着突然想起上个月测试妹子说她改了三遍电量计算逻辑,最后一版直接把 battery stats 的 discharge delta 乘了个 0.97 再入库,理由是“实测耗电比理论值略低”。我说你确定?她说不确定,但 PM 说用户反馈“续航变好了”,所以先合进去。 编译卡在 dex2oat 那步,等了三百七十二秒。窗外洒水车刚好经过,哗啦——水柱撞上楼外侧空调外机,声音钝而沉,接着是两声短促的喇叭响,司机在催前面停着的快递三轮。我顺手切出去看了眼厂商对接人的钉钉消息:“明天十点前必须跑通全部 MIUI 17 主线兼容路径”,后面跟着个笑脸表情,还加粗了“必须”。我没回。我把手机倒扣在散热垫上,它背面刚出的那层薄汗还没干透。对面工位老张叼着没点的烟,看都不看我:“你别管功耗曲线,MIUI 早就不走 kernel power_supply 的 raw data 了,现在全靠那个 fake-battery HAL,连 temperature 都是用 uptime 推算的。”我点点头,没接话。后来我查了,那个 fake-battery HAL 的 .so 文件签名日期比我上一份外包合同还早十一个月。 所以“优胜劣汰”不是夸它多强,是它真把弱的筛得只剩渣——比如我们写的那个 BatteryUsageFragment,本来按 AOSP 逻辑走 BatteryStats,结果进 MIUI 之后 init() 方法里 try-catch 住一个 SecurityException,catch 里默默 return null;比如状态栏里那个电池百分比,AOSP 里是 BatteryManager.SYSTEM_BATTERY_LEVEL,MIUI 改成读 /sys/class/power_supply/battery/capacity_fake,而这个文件,你 adb shell cat 它,会返回 “N/A”,但只要你 read() 过一次,它下次就吐出数字,而且是上一次 read 时缓存的值;再比如充电动画,我们调用 setChargingAnimationEnable(true),他们那边收不到 callback,因为整个 ChargerReceiver 被重写了,onReceive 里第一行就是 if (intent.getAction().equals("android.intent.action.BATTERY_CHANGED")) return; —— 动作名都对,就是不干这事。 我原以为只是 overlay 层打架,结果抓 trace 看了十分钟,发现连 Binder call 都被拦截了:我们进程发的 BnBatteryStats::getHistory(), 被 vendor 的 batterystats@1.2-impl.so 在 transact 之前就拦下来,直接返回 null,log 里干干净净,没 warn,没 error,连 V 级日志都没开。我截图发给外包同事小陈,他秒回:“你试过换 UID 吗?” 我试了,UID 换成 system,还是 null。他又回:“那你把 apk 名字改成 com.miui.home?” 我照做了,build 、install、reboot,再跑,BatteryStats.getInstance() 居然返回了非空对象。这个我说不准——到底是不是他们 classloader 里真有段白名单逻辑,还是 just-in-time 的类名匹配?我没继续挖。旁边测试妹子端着关东煮路过,问“你那台17热不热”,我说热,她点头:“热好,热说明 thermal engine 活着。”
产品概念图,仅供参考 其实最烦的不是这些。是那个 “小米17全面评测:性能与续航终极对决” 标题本身——评测稿写得比我们适配报告还细,帧率抖动、Wi-Fi 丢包率、亮屏唤醒延迟全有图有表,唯独没提“当系统进入深度 Doze 后,所有第三方 JobService 的 triggerTimeMillis 会被自动抹平成当前 uptimeMillis + 900000”,而这事儿,我们在做定时任务兜底的时候栽过三次。他们评测里写“续航提升 17%”,可没说这 17% 是拿掉三个后台定位服务、关闭 NFC discovery、禁用 Bluetooth LE scan 换来的。评测组自己都用的是定制内核镜像,/proc/sys/vm/swappiness=5,而我们拿到的 release 版固件里还是 60。我手边还有两台待测的,一台是 OPPO Find X8 工程样机,另一台是 vivo X100 Pro 的 beta 版系统镜像。刚才刷完 v17.2.1,vivo 那台在锁屏状态下自动清空了所有 foreground service 的 NotificationChannel,连 channelId 都不给你留,Log 里只有一行:“channel cleanup forced by system”。我现在不想碰它。我想先把小米17那台的 /data/misc/battery/ 目录权限改回来——上周五我 chmod 777 过一次,今天发现又变回 700 了,owner 是 system,但 group 是 miui。这事儿我不打算再跟厂商对齐,反正他们说“这是为安全考虑”,我就信。 (编辑:52刷机网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

