Android8.0 解決設置中打開充電提示音後充電卻沒提示音問題

       在android8.0以上的代碼在設置 ---> 聲音 ---> 高級 中 有一個充電提示音的開關,當我們打開後,插入充電器後,設備顯示在充電但並沒有觸發提示音。其實這並不是android原生的bug,這裏的充電提示音指的是無線充電提示音,當只有無線充電的時候纔會響起,然而android有三種充電方式,分別是:電源充電(充電寶和電源充電器),無線充電,USB充電(電腦USB等設備)。如果要修改哪種充電有聲音最好修改是按照Android源碼的的邏輯來走,而網上很多文章都是監聽充電廣播,再播放提示音。本文講解如何在 framework按照源碼的邏輯來修改提示音,這樣將風險降到最低。

       首先我們來看frameworks/base/core/java/android/os/BatteryManager.java這個類,這是電池的Manager,在這裏我們可以看到android定義的三種充電方式:

      /** Power source is an AC charger. */
     public static final int BATTERY_PLUGGED_AC = 1;
     /** Power source is a USB port. */
     public static final int BATTERY_PLUGGED_USB = 2;
     /** Power source is wireless. */
     public static final int BATTERY_PLUGGED_WIRELESS = 4;

        然後在來看frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java這個類,PMS是負責Andorid系統中電源管理方面的工作。作爲系統核心服務之一,和PKMS,AMS一樣,由SyetemServer run  出來的,比如設備的常見功能如亮滅屏、亮度調節、低電量模式、保持CPU喚醒,還有充電等一系列電池相關的操作都是由它來完成的,這裏主要講解修改充電提示音的過程,所以不深入講解PMS的流程和功能。在這個類中的 private void  updateIsPoweredLocked(int dirty) 方法是中,是當設備進行充電或者充電模式發生改變時調用的,

private void updateIsPoweredLocked(int dirty) {
1698          if ((dirty & DIRTY_BATTERY_STATE) != 0) {
1699              final boolean wasPowered = mIsPowered;
1700              final int oldPlugType = mPlugType;
1701              final boolean oldLevelLow = mBatteryLevelLow;
1702              mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
1703              mPlugType = mBatteryManagerInternal.getPlugType();
1704              mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
1705              mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
1706  
1707              if (DEBUG_SPEW) {
1708                  Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
1709                          + ", mIsPowered=" + mIsPowered
1710                          + ", oldPlugType=" + oldPlugType
1711                          + ", mPlugType=" + mPlugType
1712                          + ", mBatteryLevel=" + mBatteryLevel);
1713              }
1714  
1715              if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
1716                  mDirty |= DIRTY_IS_POWERED;
1717  
1718                  // Update wireless dock detection state.
1719                  final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
1720                          mIsPowered, mPlugType, mBatteryLevel);
1721  
1722                  // Treat plugging and unplugging the devices as a user activity.
1723                  // Users find it disconcerting when they plug or unplug the device
1724                  // and it shuts off right away.
1725                  // Some devices also wake the device when plugged or unplugged because
1726                  // they don't have a charging LED.
1727                  final long now = SystemClock.uptimeMillis();
1728                  if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
1729                          dockedOnWirelessCharger)) {
1730                      wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
1731                              mContext.getOpPackageName(), Process.SYSTEM_UID);
1732                  }
1733                  userActivityNoUpdateLocked(
1734                          now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
1735  
1736                  // Tell the notifier whether wireless charging has started so that
1737                  // it can provide feedback to the user.
1738                  if (dockedOnWirelessCharger) {
1739                      mNotifier.onWirelessChargingStarted();
1740                  }
1741                  /*#Begin Add by shaochun.wan for add Charging sound on 20180626*/
1742                  else if(mIsPowered && mPlugType ==  BatteryManager.BATTERY_PLUGGED_AC){
1743                      mNotifier.onAcChargingStarted();
1744                  }
1745                  /*#Ended Add by shaochun.wan for add Charging sound on 20180626*/
1746              }
1747  
1748              if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
1749                  if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
1750                      if (DEBUG_SPEW) {
1751                          Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
1752                      }
1753                      mAutoLowPowerModeSnoozing = false;
1754                  }
1755                  updateLowPowerModeLocked();
1756              }
1757          }
1758      }

注意1738處的代碼:dockedOnWirelessCharger 是當無線充電器鏈接的時候,就調用mNotifier.onWirelessChargingStarted() 這個方法,1742到1744是我添加的電源充電也有充電提示音的代碼,其中mPlugType 是充電的類型,mIsPowered 表示在充電,onAcChargingStarted() 是在 Notifier.java  這個類自定義的方法,當然,如果你想不這麼麻煩,簡單點,可直接調用onWirelessChargingStarted()這個方法。

          接下來我們看/frameworks/base/services/core/java/com/android/server/power/Notifier.java 這個類中的方法:onWirelessChargingStarted()

 public void onWirelessChargingStarted() {
556          if (DEBUG) {
557              Slog.d(TAG, "onWirelessChargingStarted");
558          }
559  
560          mSuspendBlocker.acquire();
561          Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
562          msg.setAsynchronous(true);
563          mHandler.sendMessage(msg);
564      }

只是發了一條消息,然後看消息接受的地方:

 public void handleMessage(Message msg) {
741              switch (msg.what) {
742                  case MSG_USER_ACTIVITY:
743                      sendUserActivity();
744                      break;
745  
746                  case MSG_BROADCAST:
747                      sendNextBroadcast();
748                      break;
749  
750                  case MSG_WIRELESS_CHARGING_STARTED:
751                  /*#Begin Add by shaochun.wan for add Charging sound on 20180626*/
752                  case MSG_AC_CHARGING_STARTED:
753                  /*#Ended Add by shaochun.wan for add Charging sound on 20180626*/
754                      playWirelessChargingStartedSound();
755                      break;
756                  case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
757                      sendBrightnessBoostChangedBroadcast();
758                      break;
759              }
760          }

可以看到750處的消息是調用了playWirelessChargingStartedSound() 這個函數。752處的代碼是我添加的自定義的消息,在發送onAcChargingStarted()的,和onWirelessChargingStarted()是一樣的。

      最後我們可以看playWirelessChargingStartedSound() 這個方法

private void playWirelessChargingStartedSound() {
716          final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
717                  Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
718          final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
719                  Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
720          if (enabled && soundPath != null) {
721              final Uri soundUri = Uri.parse("file://" + soundPath);
722              if (soundUri != null) {
723                  final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
724                  if (sfx != null) {
725                      sfx.setStreamType(AudioManager.STREAM_SYSTEM);
726                      sfx.play();
727                  }
728              }
729          }
730  
731          mSuspendBlocker.release();
732      }

這裏只是播放提示音,如果想修改電源充電的提示音和無線充電的提示音不同,修改 soundPath 即可。到最後充電提示音已經講解完了,想要怎麼定製都很簡單了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章