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

rock 发表于 2019-4-13 15:17:32

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

看有没大神能看懂,整个解决方法
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) == null34.                        &&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方法来计算应用的蓝牙耗电值和蓝牙的硬件耗电值。   

rock 发表于 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().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().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倍,这就是蓝牙为什么耗电量极其大的原因

坦诚--理解 发表于 2019-4-15 19:34:56

太深了,没看懂,请问版组是说蓝牙耗电大是计算的结果有问题,不是正在耗电大,是吗?

simonkin 发表于 2019-4-15 21:55:42

高手, 膜拜下......

been 发表于 2019-4-23 00:33:37

也就是说蓝牙其实不耗电,不过现在手机好像要费了的样子

kkkkl456789 发表于 2019-4-30 15:55:19

楼主说的意思是,其实蓝牙的耗电还是正常的,只是电池后台的那个系统得到的数据显示用了很多很多的电。其实并没有,是么

ZTXFLYKING 发表于 2019-4-30 16:40:33

现在手机好像都这样费电的样子

谢雁辉 发表于 2019-5-1 19:13:41

真实的耗电量是由底层硬件决定的,这机器硬件没毛病,不用管它那么多,蓝牙改用用就行了,电量统计有bug就爱咋咋地吧。
页: [1]
查看完整版本: 转网上看的:蓝牙显示耗电大问题,跟YOTA3+应该是一样