Android 10.0 按键智能机按键连续响两次的异常处理

1.前言

在10.0的系统定制开发中,在某些按键智能机的功能开发功能中,在某些时候按键音量按得太快的时候,会出现 按键声音响两次的情况,接下来分析下相关功能,然后解决这个问题。

2.按键智能机按键连续响两次的异常处理的核心类

复制代码
frameworks/base/services/core/java/com/android/server/audio/AudioService.java

3.按键智能机按键连续响两次的异常处理的核心功能分析和实现

AudioService是Android系统中提供的一个系统基本的服务,负责管理应用程序和系统的音频资源。它主要负责在操作系统中分配、控制和处理音频资源,以提供高质量、可靠和灵活的音频服务。AudioService还负责管理系统音频路由、音频格式转换、音量控制、音频设备的连接和断开、通知应用程序和服务启动/停止的音频事件等。 Android系统在启动过程中,会加载并初始化各种服务,包括AudioService。

AudioService的初始化通常在SystemServer的启动过程中完成。SystemServer是Android系统启动过程中的核心进程,负责启动和管理系统级别的服务。 AudioService的创建与配置 在SystemServer的启动过程中,会创建AudioService的实例,并进行必要的配置。配置通常包括加载音频相关的配置文件、初始化音频设备、设置音频策略等。 加载音频配置文件 AudioService会加载音频相关的配置文件,如audio_policy.conf等。这些配置文件定义了音频设备的属性、音频路由规则、音频策略等。通过加载这些配置文件,AudioService可以了解系统的音频设备和音频策略。

复制代码
 public AudioService(Context context) {
          mContext = context;
          mContentResolver = context.getContentResolver();
          mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
  
          mPlatformType = AudioSystem.getPlatformType(context);
  
          mIsSingleVolume = AudioSystem.isSingleVolume(context);
  
          mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
          mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
  
          PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
          mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
  
          mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
          mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
  ....
          int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
          if (maxCallVolume != -1) {
              MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
          }
  
          int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
          if (defaultCallVolume != -1 &&
                  defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
                  defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
          } else {
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
                      (maxCallVolume * 3) / 4;
          }
  
          int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
          if (maxMusicVolume != -1) {
              MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
          }
  
          int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
          if (defaultMusicVolume != -1 &&
                  defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
                  defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
          } else {
              if (isPlatformTelevision()) {
                  AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
                          MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
              } else {
                  AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
                          MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
              }
          }
  
          int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
          if (maxAlarmVolume != -1) {
              MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
          }
  
          int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
          if (defaultAlarmVolume != -1 &&
                  defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
          } else {
              // Default is 6 out of 7 (default maximum), so scale accordingly.
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
                          6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
          }
  
          int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
          if (maxSystemVolume != -1) {
              MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
          }
  
          int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
          if (defaultSystemVolume != -1 &&
                  defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
          } else {
              // Default is to use maximum.
              AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
                          MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
          }
    /** @see AudioManager#playSoundEffect(int) */
      public void playSoundEffect(int effectType) {
          playSoundEffectVolume(effectType, -1.0f);
      }
  
      /** @see AudioManager#playSoundEffect(int, float) */
      public void playSoundEffectVolume(int effectType, float volume) {
          // do not try to play the sound effect if the system stream is muted
          if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
              return;
          }
  
          if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
              Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
              return;
          }
  
          sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
                  effectType, (int) (volume * 1000), null, 0);
      }
  
      /**
       * Loads samples into the soundpool.
       * This method must be called at first when sound effects are enabled
       */
      public boolean loadSoundEffects() {
          int attempts = 3;
          LoadSoundEffectReply reply = new LoadSoundEffectReply();
  
          synchronized (reply) {
              sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
              while ((reply.mStatus == 1) && (attempts-- > 0)) {
                  try {
                      reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                  } catch (InterruptedException e) {
                      Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
                  }
              }
          }
          return (reply.mStatus == 0);
      }
  
      /**
       * Schedule loading samples into the soundpool.
       * This method can be overridden to schedule loading at a later time.
       */
      protected void scheduleLoadSoundEffects() {
          sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
      }
  
      /**
       *  Unloads samples from the sound pool.
       *  This method can be called to free some memory when
       *  sound effects are disabled.
       */
      public void unloadSoundEffects() {
          sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
      }

在上述的AudioService.java中,在AudioManager的playSoundEffect用于播放Beep音效的就是playSoundEffect(@SystemSoundEffect int effectType) 主要就是调用调用playSoundEffectVolume方法,所以就具体判断两次按键音的时间,然后决定是否调用按键音来实现功能

复制代码
+    long mLastSystemTimer = -1;
        //add by lixu for play sound when button click
        public void playSoundEffect(int effectType) {
-               Log.e(TAG, "lixu AudioService playSoundEffectYrct effectType = " + effectType);
-       
+               long currentTimeMillis = java.lang.System.currentTimeMillis();
+               //Log.e(TAG, "lixu AudioService playSoundEffectYrct effectType = " + effectType +"---timer:"+(mLastSystemTimer!=-1?(currentTimeMillis-mLastSystemTimer):-1));
+           if(mLastSystemTimer!=-1&&currentTimeMillis-mLastSystemTimer<=100)return;
                playSoundEffectVolume(effectType, -1.0f);
+                       mLastSystemTimer = currentTimeMillis;
     }
相关推荐
studyForMokey2 小时前
【Android 项目】个人学习demo随笔
android
吃喝不愁霸王餐APP开发者2 小时前
利用责任链模式解耦多平台(美团/饿了么)霸王餐接口的适配逻辑
android·责任链模式
百***78752 小时前
Step-Audio-2 轻量化接入全流程详解
android·java·gpt·php·llama
yangpipi-5 小时前
《C++并发编程实战》第5章 C++内存模型和原子操作
android·java·c++
云水木石7 小时前
Android 的下一个战场:Windows 应用与游戏?
android·windows·游戏
雨声不在7 小时前
Android文字渐变的实现
android·textview
GoldenPlayer7 小时前
KTS语法
android
GoldenPlayer7 小时前
后台服务Service销毁逻辑+单例造成的内存泄露
android
GoldenPlayer7 小时前
自定义APK&gradle全局配置文件
android