########电子书论坛,电纸书,水墨屏手机,yota,安卓电纸书,电子书,eink,漂白软件博阅电纸书,博阅电子书,likebook,jdread,云遥客栈,boyue,博阅电纸书########

电纸书论坛|云遥客栈

 找回密码
 打尖入住

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: 活动 交友
查看: 5217|回复: 7

[YOTA3+] 转网上看的:蓝牙显示耗电大问题,跟YOTA3+应该是一样

[复制链接]

该用户从未签到

发表于 2019-4-13 15:17:32 | 显示全部楼层 |阅读模式
看有没大神能看懂,整个解决方法

Android N 电量使用情况之蓝牙耗电量
    遇到的问题:设备电量使用情况中,蓝牙的耗电量很高,都可以达到百分之90。
    第一次尝试解决:
    首先先查看了power_profile.xml,发现该文件没有配置bluetooth.active和bluetooth.on两项,以为自己找到了原因,就把这两项配置了一下,结果,还是不行,又把这两项全部改成0,还是不行,没办法了,只能分析代码了。
(1) BatteryStatsHelper
    系统设置主要通过该类来获取电量使用情况,通过调用processAppUsage得到最终的电量使用情况,我们重点关注和蓝牙有关的逻辑:
1.  private void processAppUsage(SparseArray<UserHandle>asUsers) {
2.          final boolean forAllUsers =(asUsers.get(UserHandle.USER_ALL) != null);
3.          mStatsPeriod = mTypeBatteryRealtimeUs;
4.          BatterySipper osSipper = null;
5.          final SparseArray<?extends Uid> uidStats = mStats.getUidStats();
6.          final int NU =uidStats.size();
7.          for (int iu = 0; iu < NU; iu++){
8.              final Uid u =uidStats.valueAt(iu);
9.              final BatterySipper app= new BatterySipper(BatterySipper.DrainType.APP, u, 0);
10.
11.            mCpuPowerCalculator.calculateApp(app,u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
12.           mWakelockPowerCalculator.calculateApp(app, u, mRawRealtimeUs,mRawUptimeUs, mStatsType);
13.           mMobileRadioPowerCalculator.calculateApp(app, u, mRawRealtimeUs,mRawUptimeUs, mStatsType);
14.           mWifiPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs,mStatsType);
15.           mBluetoothPowerCalculator.calculateApp(app, u, mRawRealtimeUs,mRawUptimeUs, mStatsType);
16.            mSensorPowerCalculator.calculateApp(app,u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
17.           mCameraPowerCalculator.calculateApp(app, u, mRawRealtimeUs,mRawUptimeUs, mStatsType);
18.           mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtimeUs,mRawUptimeUs, mStatsType);
19.
20.            final double totalPower =app.sumPower();
21.            if (DEBUG &&totalPower != 0) {
22.                Log.d(TAG, String.format("UID %d: totalpower=%s", u.getUid(),
23.                        makemAh(totalPower)));
24.            }
25.
26.            if (totalPower != 0 || u.getUid() == 0) {
27.                final int uid =app.getUid();
28.                final int userId =UserHandle.getUserId(uid);
29.                if (uid ==Process.WIFI_UID) {
30.                    mWifiSippers.add(app);
31.                } else if (uid ==Process.BLUETOOTH_UID) {
32.                    mBluetoothSippers.add(app);
33.                } else if (!forAllUsers&& asUsers.get(userId) == null
34.                        &&UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
35.                    List<BatterySipper>list = mUserSippers.get(userId);
36.                    if (list == null) {
37.                        list = newArrayList<>();
38.                       mUserSippers.put(userId, list);
39.                    }
40.                    list.add(app);
41.                } else {
42.                    mUsageList.add(app);
43.                }
44.
45.                if (uid == 0) {
46.                    osSipper = app;
47.                }
48.            }
49.        }
50.
51.    }
1.      private void addBluetoothUsage() {
2.          BatterySipper bs = newBatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
3.          mBluetoothPowerCalculator.calculateRemaining(bs,mStats, mRawRealtimeUs, mRawUptimeUs,
4.                  mStatsType);
5.          aggregateSippers(bs, mBluetoothSippers,"Bluetooth");
6.          if (bs.totalPowerMah> 0) {
7.              mUsageList.add(bs);
8.          }
9.      }
    可以看出主要通过mBluetoothPowerCalculator的calculateRemaining和calculateApp方法来计算应用的蓝牙耗电值和蓝牙的硬件耗电值。   

回复

使用道具 举报

该用户从未签到

 楼主| 发表于 2019-4-13 15:21:02 | 显示全部楼层
字数限制,分两层
(2)BluetoothPowerCalculator中的逻辑

1.  public class BluetoothPowerCalculator extends PowerCalculator {

2.      private static final boolean DEBUG = BatteryStatsHelper.DEBUG;

3.      private static final String TAG = "BluetoothPowerCalculator";

4.      private final double mIdleMa;

5.      private final double mRxMa;

6.      private final double mTxMa;

7.      private double mAppTotalPowerMah = 0;

8.      private long mAppTotalTimeMs = 0;

9.   

10.    public BluetoothPowerCalculator(PowerProfile profile) {

11.        mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);

12.        mRxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX);

13.        mTxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX);

14.    }

15.

16.    @Override

17.    public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,

18.                             long rawUptimeUs, int statsType) {

19.

20.        final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();

21.        if (counter == null) {

22.            return;

23.        }

24.

25.        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);

26.        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);

27.        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);

28.        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;

29.        double powerMah = counter.getPowerCounter().getCountLocked(statsType)

30.                / (double)(1000*60*60);

31.

32.        if (powerMah == 0) {

33.            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))

34.                    / (1000*60*60);

35.        }

36.

37.        app.bluetoothPowerMah = powerMah;

38.        app.bluetoothRunningTimeMs = totalTimeMs;

39.        app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);

40.        app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);

41.

42.        mAppTotalPowerMah += powerMah;

43.        mAppTotalTimeMs += totalTimeMs;

44.    }

45.

46.    @Override

47.    public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,

48.                                   long rawUptimeUs, int statsType) {

49.        final BatteryStats.ControllerActivityCounter counter =

50.                stats.getBluetoothControllerActivity();

51.

52.        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);

53.        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);

54.        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);

55.        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;

56.        double powerMah = counter.getPowerCounter().getCountLocked(statsType)

57.                 / (double)(1000*60*60);

58.

59.        if (powerMah == 0) {

60.            // Some devices do not report the power, so calculate it.

61.            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))

62.                    / (1000*60*60);

63.        }

64.

65.        // Subtract what the apps used, but clamp to 0.

66.        powerMah = Math.max(0, powerMah - mAppTotalPowerMah);

67.

68.        if (DEBUG && powerMah != 0) {

69.            Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)

70.                    + " power=" + BatteryStatsHelper.makemAh(powerMah));

71.        }

72.

73.        app.bluetoothPowerMah = powerMah;

74.        app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);

75.    }

76.

77.    @Override

78.    public void reset() {

79.        mAppTotalPowerMah = 0;

80.        mAppTotalTimeMs = 0;

81.    }

82.}

    可以看出每个BatteryStats.Uid对象都可以通过getBluetoothControllerActivity方法获取到一个counter对象,这个对象可以获取到蓝牙的接收数据时长,发送数据时长,空闲时长,还可以获取到一个powerMah,如果这个powerMah为0,则根据上述三个时长计算耗电量。在BluetoothPowerCalculator的构造方法中,初始化了三个时长对应的电流,电流的值怎么获取的,代码很简单,直接说结论:PowerProfile中有一个map,PowerProfile通过读取power_profile.xml来更新这个map的内容,但是有个坑,PowerProfile定义了一个数组,如果,在power_profile.xml中没有找到该项定义,他就要去读取系统内置资源的值,这就是主要的坑:

1.          int[] configResIds = new int[]{

2.                  com.android.internal.R.integer.config_bluetooth_idle_cur_ma,

3.                  com.android.internal.R.integer.config_bluetooth_rx_cur_ma,

4.                  com.android.internal.R.integer.config_bluetooth_tx_cur_ma,

5.                  com.android.internal.R.integer.config_bluetooth_operating_voltage_mv,

6.                  com.android.internal.R.integer.config_wifi_idle_receive_cur_ma,

7.                  com.android.internal.R.integer.config_wifi_active_rx_cur_ma,

8.                  com.android.internal.R.integer.config_wifi_tx_cur_ma,

9.                  com.android.internal.R.integer.config_wifi_operating_voltage_mv,

10.        };

11.

12.        String[] configResIdKeys = new String[]{

13.                POWER_BLUETOOTH_CONTROLLER_IDLE,

14.                POWER_BLUETOOTH_CONTROLLER_RX,

15.                POWER_BLUETOOTH_CONTROLLER_TX,

16.                POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE,

17.                POWER_WIFI_CONTROLLER_IDLE,

18.                POWER_WIFI_CONTROLLER_RX,

19.                POWER_WIFI_CONTROLLER_TX,

20.                POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE,

21.        };

    从上面的代码可以看出蓝牙电流的key值为

1.          mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);

2.          mRxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX);

3.          mTxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX);

    而对应的字符串为

1.      public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle";

2.      public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx";

3.      public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx";

    可以看出,已经和bluetooth.active,bluetooth.on没有关系了,这就是为什么改这两个没有用的原因,那为什么蓝牙的耗电量极其之大呢?由上面的逻辑可以看出来,主要根据三个时常和一个powerMah,必然这几个值有的错了。我们找找,这几个值是在哪更新的,最终我们发现了问题:

1.          final double opVolt = mPowerProfile.getAveragePower(

2.                  PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;

3.          if (opVolt != 0) {

4.              // We store the power drain as mAms.

5.              mBluetoothActivity.getPowerCounter().addCountLocked(

6.                      (long) (info.getControllerEnergyUsed() / opVolt));

7.          }

    可以看到上述代码获取了PowerProfile中的电压值,powerMah的值为所消耗的能量除以电压值,结果发现我们的电压值为3,正常的一般为3300,意味着powerMah大了1100倍,这就是蓝牙为什么耗电量极其大的原因
回复 支持 反对

使用道具 举报

  • TA的每日心情
    无聊
    2019-11-25 18:17
  • 发表于 2019-4-15 19:34:56 | 显示全部楼层
    太深了,没看懂,请问版组是说蓝牙耗电大是计算的结果有问题,不是正在耗电大,是吗?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2019-4-15 21:55:42 | 显示全部楼层
    高手, 膜拜下......
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2019-4-23 00:33:37 来自手机 | 显示全部楼层
    也就是说蓝牙其实不耗电,不过现在手机好像要费了的样子
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2019-4-30 15:55:19 | 显示全部楼层
    楼主说的意思是,其实蓝牙的耗电还是正常的,只是电池后台的那个系统得到的数据显示用了很多很多的电。其实并没有,是么
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-3-1 13:41
  • 发表于 2019-4-30 16:40:33 | 显示全部楼层
    现在手机好像都这样费电的样子
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2019-5-1 19:13:41 | 显示全部楼层
    真实的耗电量是由底层硬件决定的,这机器硬件没毛病,不用管它那么多,蓝牙改用用就行了,电量统计有bug就爱咋咋地吧。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 打尖入住

    本版积分规则

    快速回复 返回顶部 返回列表