功能:根据需求选择音频音频设备的输入输出
1.在Settings中增加设备管理选项
packages/apps/Settings/src/com/android/settings/notification/AudioManagerReceiver.java
/*
- Copyright © 2013 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the “License”);
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an “AS IS” BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
*/
package com.android.settings.notification;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.FileUtils;
import android.provider.Settings;
/*
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
*/
import androidx.preference.SwitchPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.util.Log;
import android.os.SystemProperties;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.DataOutputStream;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
//import com.android.settings.dashboard.SummaryLoader;
import java.util.List;
public class AudioManagerReceiver extends BroadcastReceiver {
private static final String TAG = “AudioManagerReceiver”;
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d(TAG,"AudioManagerReceiver---max-chen");
String audioOutDevice = getAudioOutDeviceState();
if(audioOutDevice.equals("SPEAKER")){
}else if(audioOutDevice.equals("USB SPEAKER")){
}
String audioInDevice = getAudioInDeviceState();
if(audioInDevice.equals("BuildIn Mic")){
}else if(audioInDevice.equals("USB Mic")){
}
}
}
private static String getAudioOutDeviceState(){
return SystemProperties.get("persist.current.audio.output.device","SPEAKER");
}
private static String getAudioInDeviceState(){
return SystemProperties.get("persist.current.audio.input.device","BuildIn Mic");
}
}
waysion@waysion:/home/sdb/workspace/rk3399_android11.0_sdk/packages/apps/Settings$ git diff
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 16b29dc…fc5985e 100644
— a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -107,6 +107,10 @@
-
<application android:label=“@string/settings_label”
android:icon=“@drawable/ic_launcher_settings”
android:theme=“@style/Theme.Settings”
@@ -3291,6 +3295,13 @@
android:permission=“android.permission.MANAGE_SLICE_PERMISSIONS”
android:exported=“true” /> -
<receiver
-
android:name=".notification.AudioManagerReceiver" >
-
<intent-filter android:priority="1000" >
-
<action android:name="android.intent.action.BOOT_COMPLETED"/>
-
</intent-filter>
-
</receiver>
-
<!-- Couldn't be triggered from outside of settings. Statsd can trigger it because we send PendingIntent to it--> <receiver android:name=".fuelgauge.batterytip.AnomalyDetectionReceiver"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 035feed…f06d42b 100644
— a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1602,4 +1602,26 @@
2
3
+
- SPEAKER
- USB SPEAKER
- SPEAKER
- USB SPEAKER
- BuildIn Mic
- USB Mic
- BuildIn Mic
- USB Mic
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 692ab2c…0de019d 100644
— a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7909,6 +7909,11 @@
<xliff:g id=“on_count” example=“10”>%d</xliff:g> schedules set
- Audio Device Manager
- Audio OutPut Device
- Audio Input Device
- Do Not Disturb
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index fc5c3e2…494174e 100644
— a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -210,6 +210,30 @@
android:summary=“%s”/>
- <PreferenceCategory
-
android:key="audio_device_manager"
-
android:title="@string/audio_device_manager_preference_title"
-
android:order="-50">
-
<ListPreference
-
android:key="audio_output_device_manager"
-
android:title="@string/audio_output_device_manager_title"
-
android:summary="audio_output_device_summary"
-
android:entries="@array/audio_device_output_entries"
-
android:entryValues="@array/audio_device_output_values"
-
android:defaultValue="SPEAKER"
-
/>
-
<ListPreference
-
android:key="audio_input_device_manager"
-
android:title="@string/audio_input_device_manager_title"
-
android:summary="audio_input_device_summary"
-
android:entries="@array/audio_device_input_entries"
-
android:entryValues="@array/audio_device_input_values"
-
android:defaultValue="BuildIn Mic"
-
/>
- <com.android.settings.widget.WorkOnlyCategory
android:key=“sound_work_settings_section”
android:title=“@string/sound_work_settings”
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index b088fe3…6dd3010 100644
— a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -19,18 +19,20 @@ package com.android.settings.notification;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
+import android.os.SystemProperties;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.preference.SeekBarVolumizer;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.core.OnActivityResultListener;
@@ -44,18 +46,25 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.widget.UpdatableListPreferenceDialogFragment;
+import android.media.AudioManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import android.util.Log;
@SearchIndexable
-public class SoundSettings extends DashboardFragment implements OnActivityResultListener {
+public class SoundSettings extends DashboardFragment implements OnActivityResultListener, Preference.OnPreferenceChangeListener {
private static final String TAG = “SoundSettings”;
private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
private static final int REQUEST_CODE = 200;
private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds
- private static final String KEY_AUDIO_OUTPUT_DEVICE = “audio_output_device_manager”;
- private static final String KEY_AUDIO_INPUT_DEVICE = “audio_input_device_manager”;
- private static Context mContext;
- private AudioManager am;
@VisibleForTesting
static final int STOP_SAMPLE = 1;
@@ -78,6 +87,9 @@ public class SoundSettings extends DashboardFragment implements OnActivityResult
private String mHfpOutputControllerKey;
private String mVibrationPreferencesKey = “vibration_preference_screen”;
-
private ListPreference mAudioOutputDevicePreference = null;
-
private ListPreference mAudioInputDevicePreference = null;
-
@Override
public int getMetricsCategory() {
return SettingsEnums.SOUND;
@@ -97,6 +109,26 @@ public class SoundSettings extends DashboardFragment implements OnActivityResult
.findFragmentByTag(TAG);
mDialogFragment = dialogFragment;
} -
mContext = getContext();
-
am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
-
if(mAudioOutputDevicePreference==null && mAudioInputDevicePreference==null){
-
mAudioOutputDevicePreference = (ListPreference) findPreference(KEY_AUDIO_OUTPUT_DEVICE);
-
mAudioInputDevicePreference = (ListPreference) findPreference(KEY_AUDIO_INPUT_DEVICE);
-
mAudioOutputDevicePreference.setOnPreferenceChangeListener(this);
-
mAudioInputDevicePreference.setOnPreferenceChangeListener(this);
-
String audioOutDevice = getAudioOutDeviceState();
-
Log.d("max.chen","------audioOutDevice:"+audioOutDevice);
-
mAudioOutputDevicePreference.setValue(audioOutDevice);
-
mAudioOutputDevicePreference.setSummary(audioOutDevice);
-
String audioInDevice = getAudioInDeviceState();
-
Log.d("max.chen","------audioOutDevice:"+audioInDevice);
-
mAudioInputDevicePreference.setValue(audioInDevice);
-
mAudioInputDevicePreference.setSummary(audioInDevice);
-
}
-
}
@Override
@@ -110,6 +142,51 @@ public class SoundSettings extends DashboardFragment implements OnActivityResult
mVolumeCallback.stopSample();
} -
@Override
-
public boolean onPreferenceChange(Preference preference, Object value) {
-
// TODO Auto-generated method stub
-
Log.d("max.chen", "max.chen preference = " + preference + " value = " + value);
-
//把preference这个Preference强制转化为ListPreference类型
-
ListPreference listPreference=(ListPreference)preference;
-
//获取ListPreference中的实体内容
-
CharSequence[] entries=listPreference.getEntries();
-
//获取ListPreference中的实体内容的下标值
-
int index=listPreference.findIndexOfValue((String)value);
-
//把listPreference中的摘要显示为当前ListPreference的实体内容中选择的那个项目
-
listPreference.setSummary(entries[index]);
-
if(listPreference == mAudioOutputDevicePreference){
-
SystemProperties.set("persist.vendor.audio.output.device",(String)value);
-
if(String.valueOf(value).contains("USB")){
-
am.setParameters("saintway_usb_headset_enable=true");
-
}else{
-
am.setParameters("saintway_usb_headset_enable=false");
-
}
-
}else if(listPreference == mAudioInputDevicePreference){
-
SystemProperties.set("persist.vendor.audio.input.device",(String)value);
-
if(String.valueOf(value).contains("USB")){
-
am.setParameters("saintway_usb_headset_enable=true");
-
}else{
-
am.setParameters("saintway_usb_headset_enable=false");
-
}
-
}
-
return true;
-
}
-
private String getAudioOutDeviceState(){
-
return SystemProperties.get("persist.vendor.audio.output.device","SPEAKER");
-
}
-
private String getAudioInDeviceState(){
-
return SystemProperties.get("persist.vendor.audio.input.device","BuildIn Mic");
-
}
-
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference instanceof RingtonePreference) {
2.frameworks/av/media/utils/ServiceUtilities.cpp中开放APP更改音频的权限
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index cc64f9f…ed2ecd2 100644
— a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -196,12 +196,13 @@ bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid)
bool settingsAllowed() {
// given this is a permission check, could this be isAudioServerOrRootUid()?
- if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
- static const String16 sAudioSettings(“android.permission.MODIFY_AUDIO_SETTINGS”);
- //if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
- //static const String16 sAudioSettings(“android.permission.MODIFY_AUDIO_SETTINGS”);
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
- bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
- if (!ok) ALOGE(“Request requires android.permission.MODIFY_AUDIO_SETTINGS”);
- return ok;
- //bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
- //if (!ok) ALOGE(“Request requires android.permission.MODIFY_AUDIO_SETTINGS”);
- //return ok;
- return true;
}
3.修改音频策略
frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
+#pragma clang diagnostic ignored “-Wunused-parameter”
+#include <cutils/properties.h>
DeviceVector Engine::getDevicesForStrategyInt函数中修改输出
DeviceVector devices2;
char value[PROPERTY_VALUE_MAX] = "";
char value_usb[PROPERTY_VALUE_MAX] = "";
property_get("persist.system.usb.headset_state",value, "unknow");
property_get("persist.vendor.audio.output.device",value_usb,"unknow");
if(devices2.isEmpty()){
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
}
if(/*!(strcmp(value,"on")&&*/!strcmp(value_usb,"USB SPEAKER")){
if(devices2.isEmpty()){
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
AUDIO_DEVICE_OUT_USB_HEADSET, AUDIO_DEVICE_OUT_USB_DEVICE});
}
}
if(devices2.isEmpty()){
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
}
if(devices2.isEmpty()){
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
}
if(devices2.isEmpty()){
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
devices.add(devices2);
Engine::getDeviceForInputSource 中修改输出
char value[PROPERTY_VALUE_MAX] = “”;
char value_usb[PROPERTY_VALUE_MAX] = “”;
char value_hdmiin[PROPERTY_VALUE_MAX] = “”;
property_get(“persist.system.usb.headset_state”,value, “unknow”);
property_get(“persist.vendor.audio.input.device”,value_usb,“unknow”);
property_get(“media.audio.hdmiin”,value_hdmiin,“0”);
if (isInCall()) {
if(/*!(strcmp(value,"on")&&*/!strcmp(value_usb,"USB Mic")){
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_IN_USB_HEADSET,
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_WIRED_HEADSET,AUDIO_DEVICE_IN_BUILTIN_MIC});
}else{
device = availableDevices.getFirstExistingDevice({
}
}else{
if(/*!(strcmp(value,"on")&&*/!strcmp(value_usb,"USB Mic")){
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_USB_HEADSET,AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_WIRED_HEADSET,AUDIO_DEVICE_IN_BUILTIN_MIC});
}else{
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_WIRED_HEADSET,AUDIO_DEVICE_IN_BUILTIN_MIC});
}
}
if(strcmp(value_hdmiin,"1")==0){
device = availableDevices.getFirstExistingDevice({AUDIO_DEVICE_IN_HDMI});
}
if (device == nullptr) {
ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
ALOGE_IF(device == nullptr,
"getDeviceForInputSource() no default device defined");
}
ALOGD("max.chen getDeviceForInputSource()input source %d, device %08x",
inputSource, device->type());
return device;
4.修改hardware/rockchip/audio/tinyalsa/audio_hw.c
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
/* usb_headset enable/disable */
ret = str_parms_get_str(parms, “saintway_usb_headset_enable”, value, sizeof(value));
if (0 <= ret) {
if (strcmp(value, "true") == 0) {
ALOGD("max.chen Enable usb headset ");
struct stream_out *out = adev->outputs[OUTPUT_DIRECT];
out->snd_reopen = true;
} else if (strcmp(value, "false") == 0) {
ALOGD("max.chen Disable usb headset");
struct stream_out *out = adev->outputs[OUTPUT_DIRECT];
out->snd_reopen = true;
}
}
————————————————
版权声明:本文为CSDN博主「Max.Chen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chgh1306/article/details/126065722