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;
     }
相关推荐
·云扬·12 小时前
ClickHouse常用管理语句汇总:会话、磁盘、性能与复制管理
android·clickhouse
游戏开发爱好者812 小时前
2025年iOS应用上架App Store全指南,开发者必看
android·ios·小程序·https·uni-app·iphone·webview
a31582380612 小时前
Android CardView修改背景阴影
android·cardview·修改背景
kk哥889913 小时前
Android UI 优化指南:流畅度与体验双提升
android·ui
摘星编程14 小时前
Flutter for OpenHarmony 实战:SliverList 滑动列表详解
android·javascript·flutter
abbiz14 小时前
30 个 Android 面试高频问题及答案
android·面试·职场和发展
冬奇Lab14 小时前
【Kotlin系列04】类与对象基础:从Java Bean到Data Class的优雅蜕变
android·kotlin·编程语言
笔夏14 小时前
【安卓学习之webRTC】学习相关资料
android·学习·webrtc
_李小白14 小时前
【Android 美颜相机】第三天:初识GPUImageView
android·数码相机
行稳方能走远14 小时前
Android java 学习笔记3
android·java