車関連
調べてみると、mFocusListener が設定されているのはここだけなので、Car を使って調べてみましょう。
パッケージ/サービス/車/サービス/src/com/android/car/CarAudioService.java
public void init () { AudioPolicy . ビルダービルダー=新しいAudioPolicy . ビルダー( mContext ); ...ビルダー。setAudioPolicyFocusListener ( mSystemFocusListener ); ... }
mSystemFocusListener
//SystemFocusListenerはCarAudioServiceの内部类 private class SystemFocusListener extends AudioPolicyFocusListener { public void onAudioFocusGrant ( AudioFocusInfo afi , int requestResult ) { ... if ( requestResult == AudioManager . AUDIOFOCUS_REQUEST_GRANTED ) { synchronized ( mLock ) { mPendingFocusChanges . addFirst ( afi ); mFocusHandler _ .handleAndroidFocusChange (); } ... } public void onAudioFocusLoss ( AudioFocusInfo afi , boolean wasNotified ) { // 理由がわかりません。要するに、この場所ではトラッキング ゲインとしてロスを無視しても安全です。少なくとも一番下のリスナーは// 常にそこにあり、フォーカス許可を取得します. したがって、ここではこれを無視しても安全です. } }
mFocusHandler の定義:
mFocusHandlerThread = 新しい HandlerThread ( CarLog . TAG_AUDIO ); mFocusHandler = new CarAudioFocusChangeHandler ( mFocusHandlerThread . getLooper ());
mFocusHandler.handleAndroidFocusChange
private void handleAndroidFocusChange () { cancelFocusReleaseRequest (); メッセージmsg = getsMessage ( MSG_ANDROID_FOCUS_CHANGE ); sendMessage (メッセージ); }
case MSG_ANDROID_FOCUS_CHANGE : doHandleAndroidFocusChange ( false /* triggerByStreamChange * / ); 休憩;
より複雑な関数 doHandleAndroidFocusChange@CarAudioService に遭遇しました
private void doHandleAndroidFocusChange ( boolean triggerByStreamChange ) { ... //mPendingFocusChanges.addFirst(afi ); newTopInfo = mPendingFocusChanges .getFirst (); //これは LinkedList です。getFirst . clear (); ... if ( newTopInfo != null ) { if ( newTopInfo . getGainRequest () == AudioManager . AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ) { //新しいリクエストは、一時的なアヒルを取得することです//前のボスを代理人に降格させますmSecondaryFocusInfo = mPrimaryFocusInfo ; } else { //それ以外の場合、代理人を設定しないでくださいmSecondaryFocusInfo = null ; } //新しいものボスになるmPrimaryFocusInfo = newTopInfo ; } //後で解析を参照してくださいfocusRequested = handleCarFocusRequestAndResponseLocked (); ... //応答がある場合、またはタイムアウトが必須if ( focusRequested ) { doHandleCarFocusChange (); } }
newTopInfo は MediaFocusControl の mFocusStack.peek().toAudioFocusInfo() までさかのぼります。これは、実際には mFocusStack スタックの一番上にある現在のオーディオ フォーカス所有者情報です!
ここでは、最初に handleCarFocusRequestAndResponseLocked の分析を行います
private boolean handleCarFocusRequestAndResponseLocked () { boolean focusRequested = reevaluateCarAudioFocusAndSendFocusLocked (); if ( focusRequested ) { ... // フォーカス応答を取得した後、コンテキスト変更を送信します。关键的新概念,CarAudioContext if ( mCarAudioContextChangeHandler != null ) { mCarAudioContextChangeHandler . requestContextChangeNotification ( mAudioContextChangeListener、mCurrentPrimaryAudioContext、mCurrentPrimaryPhysicalStream ); } // キャンバスの稼働状況をチェック?checkCanStatus (); } return focusRequested ; }
この関数は最後に、reevaluateCarAudioFocusAndSendFocusLocked から返された focusRequested を返します。
この巨大な関数を見てみましょう。
reevaluateCarAudioFocusAndSendFocusLocked@CarAudioService
if ( mPrimaryFocusInfo == null ) { if ( mSystemSoundPhysicalStreamActive ) { // 最後に mVehicleHal.set(AUDIO_FOCUS).to(payload) を呼び出し; //payload = { リクエスト、ストリーム、extFocus、audioContexts }; return requestFocusForSystemSoundOnlyCaseLocked (); } . .. } ... // 計算と割り当てを判断するセクションの後、割り当て//focusToRequest、streamsToRequest、extFocus、//audioContexts、routingHintChanged これらのパラメータ... return sendFocusRequestToCarIfNecessaryLocked ( focusToRequest , streamsToRequest , extFocus , audioContexts、routingHintChanged ); }
そして sendFocusRequestToCarIfNecessaryLocked も呼び出します
mAudioHal . requestAudioFocusChange ( focusToRequest、streamToRequest、extFocus、audioContexts );
それから
int []ペイロード = {リクエスト、ストリーム、extFocus、audioContexts }; mVehicleHal . 設定( AUDIO_FOCUS )。に(ペイロード);
同様の呼び出しが以前に分析されているため、ベンダーはそれをさらに下に実装する必要があります。
ハードウェア/インターフェース/自動車/車両/2.0/types.hal
最初はその注釈です(原文は掲載されていません、多すぎます)
AUDIO_FOCUS = ( 0x0900 | VehiclePropertyGroup :システム| VehiclePropertyType : INT32_VEC | VehicleArea : GLOBAL ),
Android 側のオーディオ フォーカス ステータスを表します。車のオーディオ モジュールにはオーディオ フォーカスが必要であり、Android 側にオーディオ フォーカスを付与 (許可、解放?) する必要があることに注意してください (Android 側から要求された場合)。フォーカスには、ストリーム特性と両方の特性があります。グローバルな特徴。
聞く:
フォーカス リクエスト (このプロパティの取得) は、次の形式 (VehicleAudioFocusIndex で定義されたインデックス) である必要があります (上記の呼び出しと同様)。
int32Values[0]: VehicleAudioFocusRequest タイプ
int32Values[1]: このフォーカス要求によって要求されたストリームのビット フラグ。
最大 32 のストリームが存在できます。
int32Values[2]: 外部フォーカス状態フラグ....
int32Values[3]:アクティブになりたいオーディオ コンテキスト....
応答:
フォーカス レスポンス (このプロパティの設定およびサブスクリプション コールバック)
int32Values[0]: VehicleAudioFocusState タイプ
int32Values[1]: 許可されるストリームのビット フラグ。
int32Values[2]: 外部フォーカス状態...(GAIN,GAIN_TRANSIENT,LOSS,LOSS_TRANSIENT)
int32Values[3]:アクティブにできるオーディオ コンテキスト。
Android からのフォーカス リクエストの場合、リクエストの元のコンテキストは
ここで繰り返されます。フォーカスを外したり、リクエストを拒否したりすると、
拒否または停止されたコンテキストでは、対応するビットがクリアされます。
オーディオ コンテキスト: 承認された場合は、要求を繰り返します。拒否または停止された場合、コンテキストは対応するビットをクリアする必要があります。
フォーカス状態が変更されていない場合でも、各フォーカス リクエストにはフォーカス レスポンスが必要です。これは、フォーカス リクエストのような場合に発生する可能性があります。
オーディオモジュールが必要な変更を行ったことを確認するために、Android側で一致するフォーカス応答が必要なコンテキストの変更のみを伴います(context有变化的時候)。
車が AUDIO_FOCUS をサポートしていない場合、フォーカスは常に許可されていると見なされます。
//外部コンポーネントがオーディオフォーカスを制御できるようにするためのプロパティ //どうしたらいいのかわからない//データ 形式はAUDIO_FOCUSプロパティと同じ (データ形式はAUDIO_FOCUSと同じ) AUDIO_FOCUS_EXT_SYNC = ( 0x0910 | VehiclePropertyGroup : SYSTEM | VehiclePropertyType : INT32_VEC | VehicleArea : GLOBAL )、
コメントに記載されている VehicleAudioFocusIndex
/** * VehicleProperty#AUDIO_FOCUS プロパティの int32Values のインデックス。*/ enum VehicleAudioFocusIndex : int32_t { FOCUS = 0 , STREAMS = 1 , EXTERNAL_FOCUS_STATE = 2 , AUDIO_CONTEXTS = 3 , };
VehicleAudioFocusIndex の例 (VehicleAudioFocusIndex の定義は自動的に生成されます):
サービス/車/サービス/src/com/android/車/hal/AudioHalService.java
... int focusState = vec . get ( VehicleAudioFocusIndex . FOCUS ); intストリーム= vec . get ( VehicleAudioFocusIndex . STREAMS ); int externalFocus = vec . get ( VehicleAudioFocusIndex . EXTERNAL_FOCUS_STATE ); ...
AudioContext の使用例:
/packages/services/Car/service/src/com/android/car/VolumeUtils.java
public static final int [] CAR_AUDIO_CONTEXT = { VehicleAudioContextFlag . MUSIC_FLAG、VehicleAudioContextFlag。NAVIGATION_FLAG、VehicleAudioContextFlag。VOICE_COMMAND_FLAG、VehicleAudioContextFlag。CALL_FLAG、VehicleAudioContextFlag。ALARM_FLAG VehicleAudioContextFlag。NOTIFICATION_FLAG、VehicleAudioContextFlag。UNKNOWN_FLAG、VehicleAudioContextFlag。SAFETY_ALERT_FLAG 、 VehicleAudioContextFlag。CD_ROM_FLAG、VehicleAudioContextFlag。AUX_AUDIO_FLAG、VehicleAudioContextFlag。SYSTEM_SOUND_FLAG、VehicleAudioContextFlag。RADIO_FLAG }; //android传统的ストリームがCarContextに到達する转换public static int androidStreamToCarContext ( int logicalAndroidStream ) { switch ( logicalAndroidStream ) { case AudioManager . STREAM_VOICE_CALL : VehicleAudioContextFlagを返します。 CALL_FLAG ; ケースAudioManager。STREAM_SYSTEM : VehicleAudioContextFlagを返します。SYSTEM_SOUND_FLAG ; ケースAudioManager。STREAM_RING : VehicleAudioContextFlagを返します。RINGTONE_FLAG ; ケースAudioManager。STREAM_MUSIC : VehicleAudioContextFlagを返します。MUSIC_FLAG ; ケースAudioManager。STREAM_ALARM : VehicleAudioContextFlagを返します。ALARM_FLAG ; ケース AudioManager。STREAM_NOTIFICATION : VehicleAudioContextFlagを返します。NOTIFICATION_FLAG ; ケースAudioManager。STREAM_DTMF : VehicleAudioContextFlagを返します。SYSTEM_SOUND_FLAG ; デフォルト: VehicleAudioContextFlagを返します。UNKNOWN_FLAG ; } }
先ほどmVehicleHal.set(AUDIO_FOCUS).to(payload)の例を見ましたが、改めて車両側の応答の流れを見てみましょう。
onPropertyEvent@VehicleHal
public void onPropertyEvent ( ArrayList < VehiclePropValue > propValues ) { for ( VehiclePropValue v : propValues ) { //mPropertyHandlers已经存有対応关系HalServiceBase service = mPropertyHandlers . get ( v . prop ); サービス。getDispatchList ()。追加( v ); mServicesToDispatch。追加(サービス); } ... for ( HalServiceBase s : mServicesToDispatch ) { s . handleHalEvents ( s . getDispatchList ()); ... } }
VehicleHal は init を呼び出すときに各サービスが気にするプロパティを既にバインドしているため、この場所に popValues イベントがあると、対応するサービスを見つけることができます。
//init@VehicleHal コレクション< VehiclePropConfig > 取得 = サービス. takeSupportedProperties (プロパティ); for ( VehiclePropConfig p :取得) { mPropertyHandlers . append ( p . prop , service ); }
takeSupportedProperties@AudioHalService
public synchronized Collection < VehiclePropConfig > takeSupportedProperties ( Collection < VehiclePropConfig > allProperties ) { for ( VehiclePropConfig p : allProperties ) { switch ( p . prop ) { //AudioHalService が気にするすべての props. case Vehicle AUDProperty_ . : case VehicleProperty . AUDIO_VOLUME : case VehicleProperty . AUDIO_VOLUME_LIMIT : 車両プロパティの場合。AUDIO_HW_VARIANT :ケースVehicleProperty。AUDIO_EXT_ROUTING_HINT :ケースVehicleProperty。AUDIO_PARAMETERS : case VehicleProperty . AUDIO_STREAM_STATE : mProperties . put ( p . prop , p ); 休憩; } }新しいArrayList <>を返します( mProperties . values ()); }
上記の s.handleHalEvents は
handleHalEvents@AudioHalService
public void handleHalEvents ( List < VehiclePropValue >値) { AudioHalFocusListener focusListener ; AudioHalVolumeListenerボリュームリスナー; OnParameterChangeListener parameterListener ; 同期(これ) { focusListener = mFocusListener ; volumeListener = mVolumeListener ; parameterListener = mOnParameterChangeListener ; } dispatchEventToListener ( focusListener、volumeListener、parameterListener、値); }
上記の VehicleAudioFocusIndex はまもなく登場します
dispatchEventToListener@AudioHalService
… の場合_ AUDIO_FOCUS : { ArrayList <整数> vec = v . 値。int32Values ; //即是types.halで定義されたAUDIO_FOCUSの応答方法(Audio Contextはどこ?) int focusState = vec . get ( VehicleAudioFocusIndex . FOCUS ); intストリーム= vec . get ( VehicleAudioFocusIndex . STREAMS ); int externalFocus = vec . get ( VehicleAudioFocusIndex . EXTERNAL_FOCUS_STATE ); if ( focusListener != null ) { focusListener . onFocusChange ( focusState、ストリーム、externalFocus ); } } ...
このListrnerは誰ですか、考えないでください、それだけです
onFocusChange@CarAudioService
public void onFocusChange ( int focusState , int stream , int externalFocus ) { synchronized ( mLock ) { mFocusReceived = FocusState . 作成( focusState、ストリーム、externalFocus ); // フォーカス応答を待っているスレッドを起動します。mロック。通知すべて(); mFocusHandler . _ handleFocusChange (); }
いくつかの手順を省略した後、ここにあります
doHandleCarFocusChange@CarAudioService
private void doHandleCarFocusChange () { ... newFocusState = ??? ... switch ( newFocusState ) { case AudioHalService . VEHICLE_AUDIO_FOCUS_STATE_GAIN : doHandleFocusGainFromCar ( mCurrentFocusState , topInfo , systemSoundActive ); 休憩; ケースAudioHalService。VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT : doHandleFocusGainTransientFromCar ( mCurrentFocusState , topInfo , システムサウンドアクティブ); 休憩; ケースAudioHalService。VEHICLE_AUDIO_FOCUS_STATE_LOSS : doHandleFocusLossFromCar ( mCurrentFocusState , topInfo ); 休憩; ケースAudioHalService。VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT : doHandleFocusLossTransientFromCar ( mCurrentFocusState ); 休憩; ケースAudioHalService。VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK : doHandleFocusLossTransientCanDuckFromCar ( mCurrentFocusState ); 休憩; ケースAudioHalService。VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE : doHandleFocusLossTransientExclusiveFromCar ( mCurrentFocusState ); 休憩; } }
LossTransientExclusive)FromCar この一連の関数は、基本的に mAudioManager.abandonAudioFocus およびその他の従来の関数を呼び出します。