IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android添加micphone静音事件处理 -> 正文阅读

[移动开发]android添加micphone静音事件处理

软件版本:Android9

硬件平台:Mtk8175

需求:物理按键触发,底层上报静音事件,上层响应;

按键驱动层面的内容,在此不做记录分析,从驱动上报事件到系统层事件映射透传做起:

1、修改kl映射表:

diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl

index 860aa9c118b..fd9773a5415 100644

--- a/data/keyboards/Generic.kl

+++ b/data/keyboards/Generic.kl

@@ -132,7 +132,7 @@ key 109 ? PAGE_DOWN

key 110 ? INSERT

key 111 ? FORWARD_DEL

# key 112 "KEY_MACRO"

-key 248 ? VOLUME_MUTE

+key 248 ? MUTE

key 114 ? VOLUME_DOWN

key 115 ? VOLUME_UP

key 116 ? POWER

248代表驱动上报的事件键值,由于内核和Framework层键值并未统一,因此在此做映射,后边的MUTE对应的是框架层的KEYCODE_MUTE键值,该按键在framework层代表mic静音。

2、Framework层改动,PhoneWindowManager对事件进行接收和派发,改动如下:

diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java

index b74ae77729b..6ae526ec0ce 100644

--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java

+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java

@@ -300,6 +300,7 @@ import java.io.File;

import java.io.FileReader;

import java.io.IOException;

import java.io.PrintWriter;

+import java.io.BufferedReader;

import java.util.List;

/**

@@ -460,6 +461,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? private final Object mLock = new Object();

?? ? Context mContext;

+? ? AudioManager mAudioManager;

?? ? IWindowManager mWindowManager;

?? ? WindowManagerFuncs mWindowManagerFuncs;

?? ? WindowManagerInternal mWindowManagerInternal;

@@ -499,6 +501,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */

?? ? boolean mEnableShiftMenuBugReports = false;

+? ? // Switch for micmute debug

+? ? private static boolean mMicmuteDebug = false;

+

?? ? /** Controller that supports enabling an AccessibilityService by holding down the volume keys */

?? ? private AccessibilityShortcutController mAccessibilityShortcutController;

@@ -506,6 +511,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();

?? ? WindowState mStatusBar = null;

?? ? private final int[] mStatusBarHeightForRotation = new int[4];

+? ? private boolean mMicStatus = false;

?? ? WindowState mNavigationBar = null;

?? ? boolean mHasNavigationBar = false;

?? ? boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?

@@ -2022,6 +2028,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);

?? ? ? ? mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);

?? ? ? ? mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);

+? ? ? ? mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

?? ? ? ? mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);

?? ? ? ? mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);

?? ? ? ? mAccessibilityShortcutController =

@@ -2098,6 +2105,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,

?? ? ? ? ? ? ? ? "PhoneWindowManager.mPowerKeyWakeLock");

?? ? ? ? mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));

+? ? ? ? mMicmuteDebug = "1".equals(SystemProperties.get("sys.mic.debug"));

?? ? ? ? mSupportAutoRotation = mContext.getResources().getBoolean(

?? ? ? ? ? ? ? ? com.android.internal.R.bool.config_supportAutoRotation);

?? ? ? ? mLidOpenRotation = readRotation(

@@ -3889,7 +3897,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? ? ? return -1;

?? ? ? ? } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP

?? ? ? ? ? ? ? ? || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN

-? ? ? ? ? ? ? ? || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {

+? ? ? ? ? ? ? ? || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE

+? ? ? ? ? ? ? ? || keyCode == KeyEvent.KEYCODE_MUTE) {

?? ? ? ? ? ? if (mUseTvRouting || mHandleVolumeKeysInWM) {

?? ? ? ? ? ? ? ? // On TVs or when the configuration is enabled, volume keys never

?? ? ? ? ? ? ? ? // go to the foreground app.

@@ -3897,6 +3906,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? ? ? ? ? return -1;

?? ? ? ? ? ? }

+? ? ? ? ? ? if(keyCode == KeyEvent.KEYCODE_MUTE){

+? ? ? ? ? ? ? ? dispatchDirectAudioEvent(event);

+? ? ? ? ? ? }

+

?? ? ? ? ? ? // If the device is in VR mode and keys are "internal" (e.g. on the side of the

?? ? ? ? ? ? // device), then drop the volume keys and don't forward it to the application/dispatch

?? ? ? ? ? ? // the audio event.

@@ -6132,6 +6145,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? setHdmiPlugged(!mHdmiPlugged);

?? ? }

+? ? public static boolean isMicMute(){

+? ? ? ? /*if (null == mAudioManager) {

+? ? ? ? ? ? mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

+? ? ? ? }

+? ? ? ? int current = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

+? ? ? ? */

+? ? ? ? String prop = "tal";// 默认值

+? ? ? ? BufferedReader reader = null;

+? ? ? ? try {

+? ? ? ? ? ? reader = new BufferedReader(new FileReader("/sys/devices/platform/odm/odm:gpio-keys/MicMuteState"));

+? ? ? ? ? ? prop = reader.readLine();

+? ? ? ? ? ? if (mMicmuteDebug) {

+? ? ? ? ? ? ? ? Slog.e("======", "read micstate value:" + prop);

+? ? ? ? ? ? }

+? ? ? ? } catch (IOException e) {

+? ? ? ? ? ? e.printStackTrace();

+? ? ? ? } finally {

+? ? ? ? ? ? if(reader != null){

+? ? ? ? ? ? ? ? try {

+? ? ? ? ? ? ? ? ? ? reader.close();

+? ? ? ? ? ? ? ? } catch (IOException e) {

+? ? ? ? ? ? ? ? ? ? e.printStackTrace();

+? ? ? ? ? ? ? ? }

+? ? ? ? ? ? }

+? ? ? ? }

+

+? ? ? ? if (prop.indexOf("1") != -1) {

+? ? ? ? ? ? return false;

+? ? ? ? }

+

+? ? ? ? return true;

+? ? }

?? ? /** {@inheritDoc} */

?? ? @Override

@@ -6708,6 +6753,37 @@ public class PhoneWindowManager implements WindowManagerPolicy {

?? ? ? ? ? ? ? ? | AudioManager.FLAG_FROM_KEY;

?? ? ? ? String pkgName = mContext.getOpPackageName();

?? ? ? ? switch (keyCode) {

+? ? ? ? ? ? case KeyEvent.KEYCODE_MUTE:

+? ? ? ? ? ? ? ? try {

+? ? ? ? ? ? ? ? ? ? mMicStatus = isMicMute();

+? ? ? ? ? ? ? ? ? ? if (mMicmuteDebug) {

+? ? ? ? ? ? ? ? ? ? ? ? Slog.e("======", " set mMicStatus to " + mMicStatus);

+? ? ? ? ? ? ? ? ? ? }

+? ? ? ? ? ? ? ? ? ? mAudioManager.setMicrophoneMute(mMicStatus);

+? ? ? ? ? ? ? ? ? ? /*if(mMicStatus)

+? ? ? ? ? ? ? ? ? ? {

+? ? ? ? ? ? ? ? ? ? ? ? Handler handlerToast = new Handler(Looper.getMainLooper());

+? ? ? ? ? ? ? ? ? ? ? ? handlerToast.post(new Runnable(){

+? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run(){

+? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(mContext,"Mute Mic",Toast.LENGTH_SHORT).show();

+? ? ? ? ? ? ? ? ? ? ? ? ? ? };

+? ? ? ? ? ? ? ? ? ? ? ? });

+? ? ? ? ? ? ? ? ? ? }

+? ? ? ? ? ? ? ? ? ? else

+? ? ? ? ? ? ? ? ? ? {

+? ? ? ? ? ? ? ? ? ? ? ? Handler handlerToast = new Handler(Looper.getMainLooper());

+? ? ? ? ? ? ? ? ? ? ? ? handlerToast.post(new Runnable(){

+? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run(){

+? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(mContext,"UnMute Mic",Toast.LENGTH_SHORT).show();

+? ? ? ? ? ? ? ? ? ? ? ? ? ? };

+? ? ? ? ? ? ? ? ? ? ? ? });

+? ? ? ? ? ? ? ? ? ? }

+? ? ? ? ? ? ? ? ? ? //? ? Toast.makeText(mContext,"UnMute Mic",Toast.LENGTH_SHORT).show();*/

+? ? ? ? ? ? ? ? } catch (Exception e) {

+? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Error dispatching mic mute in dispatchTvAudioEvent.", e);

+? ? ? ? ? ? ? ? }

+? ? ? ? ? ? ? ? break;

+

?? ? ? ? ? ? case KeyEvent.KEYCODE_VOLUME_UP:

?? ? ? ? ? ? ? ? try {

?? ? ? ? ? ? ? ? ? ? getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,

这里涵盖对事件的接收处理,以及对key事件sys节点获取或者写入以控制状态的操作

3、调试过程中遇到了selinux的问题,systemserver无法读取sys节点,因此添加了如下te规则:

device/mediatek/sepolicy/bsp/non_plat:

修改file_contexts

--- a/non_plat/file_contexts

+++ b/non_plat/file_contexts

@@ -171,3 +171,9 @@

# mcu

/sys/devices/platform/soc/11009000.i2c/i2c-3/3-0011/as9072_debug(/.*)? u:object_r:mcu_file:s0

+# mute key

+/sys/devices/platform/odm/odm:gpio-keys/MicMuteState u:object_r:mute_key_file:s0

修改file.te

diff --git a/non_plat/file.te b/non_plat/file.te

index 7d85882..a3d25b8 100755

--- a/non_plat/file.te

+++ b/non_plat/file.te

@@ -70,4 +70,13 @@ type sysfs_mrdump, fs_type, sysfs_type;

type doe_vendor_data_file, file_type, data_file_type;

+# mute key

+type mute_key_file, fs_type, sysfs_type;

修改system_server.te:

diff --git a/non_plat/system_server.te b/non_plat/system_server.te

index 857791f..6565630 100644

--- a/non_plat/system_server.te

+++ b/non_plat/system_server.te

@@ -132,6 +132,10 @@ allow system_server mtk_fullscreen_switch_service:service_manager add;

# Purpose : dfps hal interface permission

hal_client_domain(system_server,hal_dfps)

+# For system service MicMute permission

+allow system_server mute_key_file:dir { search read };

+allow system_server mute_key_file:file { read open getattr };

+

#============= system_server ==============

allow system_server audioserver:file write;

4、权限修改完成,service对内核节点可读可写,但是系统软件层面默认mic是可收声的,当物理按键默认为静音位置切第一次起机时,状态就反了,需要在系统第一次启动,添加一个mic键值状态的判断,是静音则切换静音:

diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java

index 61469e22e79..601e974d6da 100644

--- a/services/core/java/com/android/server/audio/AudioService.java

+++ b/services/core/java/com/android/server/audio/AudioService.java

@@ -141,6 +141,7 @@ import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;

import com.android.server.audio.AudioServiceEvents.VolumeEvent;

import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;

import com.android.server.pm.UserManagerService;

+import com.android.server.policy.PhoneWindowManager;

import org.xmlpull.v1.XmlPullParserException;

@@ -175,6 +176,11 @@ public class AudioService extends IAudioService.Stub

?? ? private static final String TAG = "AudioService";

+? ? private boolean mInitMicStatus = false;

+

+? ? // Switch for micmute debug

+? ? boolean mMicmuteDebug = false;

+

?? ? /// M: Add for control debug log, only default enable it on eng/userdebug load.

?? ? protected static final boolean LOGD = !"user".equals(Build.TYPE);

@@ -732,6 +738,8 @@ public class AudioService extends IAudioService.Stub

?? ? ? ? mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);

?? ? ? ? mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();

+? ? ? ? mMicmuteDebug = "1".equals(SystemProperties.get("sys.mic.debug"));

+

?? ? ? ? // Initialize volume

?? ? ? ? int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);

?? ? ? ? if (maxCallVolume != -1) {

@@ -875,6 +883,13 @@ public class AudioService extends IAudioService.Stub

?? ? ? ? mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);

?? ? ? ? mRecordMonitor.initMonitor();

+

+? ? ? ? //Set Mic state when system starting..

+? ? ? ? mInitMicStatus = PhoneWindowManager.isMicMute();

+? ? ? ? if (mMicmuteDebug) {

+? ? ? ? ? ? Slog.e("======", "AudioService init set mMicStatus to: " + mInitMicStatus);

+? ? ? ? }

+? ? ? ? AudioSystem.muteMicrophone(mInitMicStatus);

?? ? }

?? ? public void systemReady() {

这里调用了第二步PhoneWindowManager添加获取mic状态的方法,从而去初始化micphone的状态是否静音。

至此,改动大功告成,Mark一下~~~~~

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-15 16:18:51  更:2021-07-15 16:21:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 15:51:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码