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;
     }
相关推荐
阿巴斯甜3 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker3 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95274 小时前
Andorid Google 登录接入文档
android
黄林晴6 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab18 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿21 小时前
Android MediaPlayer 笔记
android
Jony_21 小时前
Android 启动优化方案
android
阿巴斯甜21 小时前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇21 小时前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android