1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.incallui.audiomode; 18 19 import android.content.Context; 20 import android.media.AudioDeviceInfo; 21 import android.media.AudioManager; 22 import android.telecom.CallAudioState; 23 import com.android.dialer.common.LogUtil; 24 import java.util.ArrayList; 25 import java.util.List; 26 27 /** Proxy class for getting and setting the audio mode. */ 28 public class AudioModeProvider { 29 private static final int SUPPORTED_AUDIO_ROUTE_ALL = 30 CallAudioState.ROUTE_EARPIECE 31 | CallAudioState.ROUTE_BLUETOOTH 32 | CallAudioState.ROUTE_WIRED_HEADSET 33 | CallAudioState.ROUTE_SPEAKER; 34 35 private static final AudioModeProvider instance = new AudioModeProvider(); 36 private final List<AudioModeListener> listeners = new ArrayList<>(); 37 private CallAudioState audioState = 38 new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, SUPPORTED_AUDIO_ROUTE_ALL); 39 getInstance()40 public static AudioModeProvider getInstance() { 41 return instance; 42 } 43 onAudioStateChanged(CallAudioState audioState)44 public void onAudioStateChanged(CallAudioState audioState) { 45 if (!this.audioState.equals(audioState)) { 46 this.audioState = audioState; 47 for (AudioModeListener listener : listeners) { 48 listener.onAudioStateChanged(audioState); 49 } 50 } 51 } 52 addListener(AudioModeListener listener)53 public void addListener(AudioModeListener listener) { 54 if (!listeners.contains(listener)) { 55 listeners.add(listener); 56 listener.onAudioStateChanged(audioState); 57 } 58 } 59 removeListener(AudioModeListener listener)60 public void removeListener(AudioModeListener listener) { 61 listeners.remove(listener); 62 } 63 getAudioState()64 public CallAudioState getAudioState() { 65 return audioState; 66 } 67 68 /** 69 * Sets a approximated audio state before {@link #onAudioStateChanged} is called. Classes such as 70 * {@link com.android.incallui.ProximitySensor} fetches the audio state before it is updated by 71 * telecom. This method attempts to guess the correct routing based on connected audio devices. 72 * The audio state may still be wrong on a second call due to a bug, telecom setting the 73 * route back to earpiece when a call ends. 74 */ initializeAudioState(Context context)75 public void initializeAudioState(Context context) { 76 onAudioStateChanged( 77 new CallAudioState(false, getApproximatedAudioRoute(context), SUPPORTED_AUDIO_ROUTE_ALL)); 78 } 79 getApproximatedAudioRoute(Context context)80 private static int getApproximatedAudioRoute(Context context) { 81 AudioManager audioManager = context.getSystemService(AudioManager.class); 82 boolean hasBluetooth = false; 83 boolean hasHeadset = false; 84 for (AudioDeviceInfo info : audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) { 85 switch (info.getType()) { 86 case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: 87 case AudioDeviceInfo.TYPE_BLUETOOTH_SCO: 88 hasBluetooth = true; 89 continue; 90 case AudioDeviceInfo.TYPE_WIRED_HEADSET: 91 hasHeadset = true; 92 continue; 93 default: 94 continue; 95 } 96 } 97 if (hasBluetooth) { 98 LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to bluetooth"); 99 return CallAudioState.ROUTE_BLUETOOTH; 100 } 101 if (hasHeadset) { 102 LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to headset"); 103 return CallAudioState.ROUTE_WIRED_HEADSET; 104 } 105 LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to earpiece"); 106 return CallAudioState.ROUTE_EARPIECE; 107 } 108 109 /** Notified on changes to audio mode. */ 110 public interface AudioModeListener { 111 onAudioStateChanged(CallAudioState audioState)112 void onAudioStateChanged(CallAudioState audioState); 113 } 114 } 115