rk3399 android 11 音频设备优先级管理

本文介绍了如何在Android系统的Settings应用中增加设备管理选项,允许用户选择音频输出设备(如扬声器或USB音箱)和输入设备(内置麦克风或USB麦克风),并通过系统属性文件进行设备状态的动态管理。还展示了如何通过AudioManager服务调整USB耳机功能和修改音频策略,涉及权限管理及硬件级别的音频控制。
摘要由CSDN通过智能技术生成

功能:根据需求选择音频音频设备的输入输出

1.在Settings中增加设备管理选项

packages/apps/Settings/src/com/android/settings/notification/AudioManagerReceiver.java

​
/*
* Copyright (C) 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 @@
     <uses-permission android:name="android.permission.READ_DREAM_STATE" />
     <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION" />
 
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
+
     <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 @@
         <item>2</item>
         <item>3</item>
     </string-array>
+
+    <!-- AUDIO -->
+    <string-array name="audio_device_output_entries">
+    <item>SPEAKER</item>
+    <item>USB SPEAKER</item>
+    </string-array>
+
+    <string-array name="audio_device_output_values">
+    <item>SPEAKER</item>
+    <item>USB SPEAKER</item>
+    </string-array>
+
+    <string-array name="audio_device_input_entries">
+    <item>BuildIn Mic</item>
+    <item>USB Mic</item>
+    </string-array>
+
+    <string-array name="audio_device_input_values">
+    <item>BuildIn Mic</item>
+    <item>USB Mic</item>
+    </string-array>
+
 </resources>

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 @@
         <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> schedules set</item>
     </plurals>
 
+    <!-- Audio Manager -->
+    <string name="audio_device_manager_preference_title">Audio Device Manager</string>
+    <string name="audio_output_device_manager_title">Audio OutPut Device</string>
+    <string name="audio_input_device_manager_title">Audio Input Device</string>
+
     <!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
     <string name="zen_mode_settings_title">Do Not Disturb</string>
 
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>
 
+    <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"
+       />
+
+    </PreferenceCategory>
+
     <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;

        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Max.Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值