5353import android .os .Looper ;
5454import android .os .Message ;
5555import android .os .PowerManager ;
56+ import android .os .RemoteCallbackList ;
5657import android .os .RemoteException ;
5758import android .os .ServiceManager ;
5859import android .os .SystemProperties ;
6263import android .speech .RecognizerIntent ;
6364import android .telephony .PhoneStateListener ;
6465import android .telephony .TelephonyManager ;
66+ import android .text .TextUtils ;
6567import android .util .Log ;
6668import android .view .KeyEvent ;
6769import android .view .VolumePanel ;
@@ -135,10 +137,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
135137 private static final int MSG_RCDISPLAY_UPDATE = 13 ;
136138 private static final int MSG_SET_ALL_VOLUMES = 14 ;
137139 private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 15 ;
140+ private static final int MSG_REPORT_NEW_ROUTES = 16 ;
138141 // messages handled under wakelock, can only be queued, i.e. sent with queueMsgUnderWakeLock(),
139142 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
140- private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 16 ;
141- private static final int MSG_SET_A2DP_CONNECTION_STATE = 17 ;
143+ private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 17 ;
144+ private static final int MSG_SET_A2DP_CONNECTION_STATE = 18 ;
142145
143146
144147 // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -397,6 +400,11 @@ public void onError(int error) {
397400 private boolean mBluetoothA2dpEnabled ;
398401 private final Object mBluetoothA2dpEnabledLock = new Object ();
399402
403+ // Monitoring of audio routes. Protected by mCurAudioRoutes.
404+ final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo ();
405+ final RemoteCallbackList <IAudioRoutesObserver > mRoutesObservers
406+ = new RemoteCallbackList <IAudioRoutesObserver >();
407+
400408 ///////////////////////////////////////////////////////////////////////////
401409 // Construction
402410 ///////////////////////////////////////////////////////////////////////////
@@ -3011,6 +3019,26 @@ public void handleMessage(Message msg) {
30113019 onSetA2dpConnectionState ((BluetoothDevice )msg .obj , msg .arg1 );
30123020 mMediaEventWakeLock .release ();
30133021 break ;
3022+
3023+ case MSG_REPORT_NEW_ROUTES : {
3024+ int N = mRoutesObservers .beginBroadcast ();
3025+ if (N > 0 ) {
3026+ AudioRoutesInfo routes ;
3027+ synchronized (mCurAudioRoutes ) {
3028+ routes = new AudioRoutesInfo (mCurAudioRoutes );
3029+ }
3030+ while (N > 0 ) {
3031+ N --;
3032+ IAudioRoutesObserver obs = mRoutesObservers .getBroadcastItem (N );
3033+ try {
3034+ obs .dispatchAudioRoutesChanged (routes );
3035+ } catch (RemoteException e ) {
3036+ }
3037+ }
3038+ }
3039+ mRoutesObservers .finishBroadcast ();
3040+ break ;
3041+ }
30143042 }
30153043 }
30163044 }
@@ -3127,6 +3155,13 @@ private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
31273155 } else {
31283156 makeA2dpDeviceUnavailableNow (address );
31293157 }
3158+ synchronized (mCurAudioRoutes ) {
3159+ if (mCurAudioRoutes .mBluetoothName != null ) {
3160+ mCurAudioRoutes .mBluetoothName = null ;
3161+ sendMsg (mAudioHandler , MSG_REPORT_NEW_ROUTES ,
3162+ SENDMSG_NOOP , 0 , 0 , null , 0 );
3163+ }
3164+ }
31303165 } else if (!isConnected && state == BluetoothProfile .STATE_CONNECTED ) {
31313166 if (btDevice .isBluetoothDock ()) {
31323167 // this could be a reconnection after a transient disconnection
@@ -3141,6 +3176,14 @@ private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
31413176 }
31423177 }
31433178 makeA2dpDeviceAvailable (address );
3179+ synchronized (mCurAudioRoutes ) {
3180+ String name = btDevice .getAliasName ();
3181+ if (!TextUtils .equals (mCurAudioRoutes .mBluetoothName , name )) {
3182+ mCurAudioRoutes .mBluetoothName = name ;
3183+ sendMsg (mAudioHandler , MSG_REPORT_NEW_ROUTES ,
3184+ SENDMSG_NOOP , 0 , 0 , null , 0 );
3185+ }
3186+ }
31443187 }
31453188 }
31463189 }
@@ -3204,20 +3247,43 @@ private void sendDeviceConnectionIntent(int device, int state, String name)
32043247 intent .putExtra ("name" , name );
32053248 intent .addFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY );
32063249
3250+ int connType = 0 ;
3251+
32073252 if (device == AudioSystem .DEVICE_OUT_WIRED_HEADSET ) {
3253+ connType = AudioRoutesInfo .MAIN_HEADSET ;
32083254 intent .setAction (Intent .ACTION_HEADSET_PLUG );
32093255 intent .putExtra ("microphone" , 1 );
32103256 } else if (device == AudioSystem .DEVICE_OUT_WIRED_HEADPHONE ) {
3257+ connType = AudioRoutesInfo .MAIN_HEADPHONES ;
32113258 intent .setAction (Intent .ACTION_HEADSET_PLUG );
32123259 intent .putExtra ("microphone" , 0 );
32133260 } else if (device == AudioSystem .DEVICE_OUT_ANLG_DOCK_HEADSET ) {
3261+ connType = AudioRoutesInfo .MAIN_DOCK_SPEAKERS ;
32143262 intent .setAction (Intent .ACTION_ANALOG_AUDIO_DOCK_PLUG );
32153263 } else if (device == AudioSystem .DEVICE_OUT_DGTL_DOCK_HEADSET ) {
3264+ connType = AudioRoutesInfo .MAIN_DOCK_SPEAKERS ;
32163265 intent .setAction (Intent .ACTION_DIGITAL_AUDIO_DOCK_PLUG );
32173266 } else if (device == AudioSystem .DEVICE_OUT_AUX_DIGITAL ) {
3267+ connType = AudioRoutesInfo .MAIN_HDMI ;
32183268 intent .setAction (Intent .ACTION_HDMI_AUDIO_PLUG );
32193269 }
32203270
3271+ synchronized (mCurAudioRoutes ) {
3272+ if (connType != 0 ) {
3273+ int newConn = mCurAudioRoutes .mMainType ;
3274+ if (state != 0 ) {
3275+ newConn |= connType ;
3276+ } else {
3277+ newConn &= ~connType ;
3278+ }
3279+ if (newConn != mCurAudioRoutes .mMainType ) {
3280+ mCurAudioRoutes .mMainType = newConn ;
3281+ sendMsg (mAudioHandler , MSG_REPORT_NEW_ROUTES ,
3282+ SENDMSG_NOOP , 0 , 0 , null , 0 );
3283+ }
3284+ }
3285+ }
3286+
32213287 ActivityManagerNative .broadcastStickyIntent (intent , null );
32223288 }
32233289
@@ -4795,6 +4861,15 @@ public IRingtonePlayer getRingtonePlayer() {
47954861 return mRingtonePlayer ;
47964862 }
47974863
4864+ @ Override
4865+ public AudioRoutesInfo startWatchingRoutes (IAudioRoutesObserver observer ) {
4866+ synchronized (mCurAudioRoutes ) {
4867+ AudioRoutesInfo routes = new AudioRoutesInfo (mCurAudioRoutes );
4868+ mRoutesObservers .register (observer );
4869+ return routes ;
4870+ }
4871+ }
4872+
47984873 @ Override
47994874 protected void dump (FileDescriptor fd , PrintWriter pw , String [] args ) {
48004875 mContext .enforceCallingOrSelfPermission (android .Manifest .permission .DUMP , TAG );
@@ -4803,5 +4878,8 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
48034878 dumpFocusStack (pw );
48044879 dumpRCStack (pw );
48054880 dumpStreamStates (pw );
4881+ pw .println ("\n Audio routes:" );
4882+ pw .print (" mMainType=0x" ); pw .println (Integer .toHexString (mCurAudioRoutes .mMainType ));
4883+ pw .print (" mBluetoothName=" ); pw .println (mCurAudioRoutes .mBluetoothName );
48064884 }
48074885}
0 commit comments