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;
     }
相关推荐
百锦再5 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
2501_916008896 小时前
全面介绍Fiddler、Wireshark、HttpWatch、SmartSniff和firebug抓包工具功能与使用
android·ios·小程序·https·uni-app·iphone·webview
玉梅小洋7 小时前
Windows 10 Android 构建配置指南
android·windows
Libraeking9 小时前
视觉篇:Canvas 自定义绘图与高级动画的华丽圆舞曲
android·经验分享·android jetpack
Fushize9 小时前
多模块架构下的依赖治理:如何避免 Gradle 依赖地狱
android·架构·kotlin
Jomurphys10 小时前
Kotlin - 类型别名 typealias
android·kotlin
Haha_bj10 小时前
Flutter ——flutter_screenutil 屏幕适配
android·ios
Haha_bj10 小时前
Flutter ——device_info_plus详解
android·flutter·ios
前端小伙计11 小时前
Android/Flutter 项目统一构建配置最佳实践
android·flutter
Mr_sun.12 小时前
Day09——入退管理-入住-2
android·java·开发语言