What does Callaudiomanager do? Words to write the call Audio Manager, a class that manages the audio status in a conversation. Initialize
A picture to see how Callaudiomanager.
Initialize the telecomglobals when the Teleservice is created, then new out a callsmanager, and a Callaudiomanager () in the Callsmanager.java constructor, With three parameters Callaudiomanager (context, Statusbarnotifier, Mwiredheadsetmanager). File Structure
Then take a look at the inheritance and implementation relationships of Callaudiomanager
Callaudiomanager extends Callsmanagerlistenerbase
Implements Wiredheadsetmanager.listener {
Callaudiomanager.java inherits Callsmanagerlistenerbase.java (actually Callsmanager Callsmanagerlistener interface), implements Wiredheadsetmanager.liste NER (),
so it overrides a series of methods in Callsmanagerlistenerbase, implements the Wiredheadsetmanager interface Onwiredheadsetpluggedinchanged (), as shown in the following figure:
From this image we can get an overview of some of the things that Callaudiomanager cares about, and when call changes, when the
Wired headset is plugged in/unplugged, this class does some work setting up, saving or updating some of the audio information. See Onwiredheadsetpluggedinchanged () This method, perhaps some people think, since there is a way to care about the plug/Unplug status of the wired headset changes, there is no way to handle the bluetooth headset connection/ The state of the disconnection. Actually there is, but it is not like wired headphones by the implementation of the interface implementation, but in the internal write a few methods to listen to the status of Bluetooth processing, one of the wired headphone insertion/extraction corresponding to the method is Onbluetoothstatechange (). The
can be seen by the constructor of the callaudiomanager below, when the Callaudiomanager initial session is new with a bluetoothmanager (),
Callaudiomanager (context context, Statusbarnotifier Statusbarnotifier,
wiredheadsetmanager Wiredheadsetmanager ) {
mstatusbarnotifier = statusbarnotifier;
Maudiomanager = (Audiomanager) context.getsystemservice (context.audio_service);
Mbluetoothmanager = new Bluetoothmanager (context, this);
Mwiredheadsetmanager = Wiredheadsetmanager;
Mwiredheadsetmanager.addlistener (this);
Saveaudiostate (Getinitialaudiostate (null));
Maudiofocusstreamtype = Stream_none;
Mcontext = context;
}
1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12
and Wiredheadsetmanager () is in Callsmanager initialization time with Callaudiomanager was new out, feeling wiredheadset and Bluetooth the same uneven level, I don't know what to think for the moment.
/**
* Initializes the required Telecom components.
*
/Callsmanager (context context, Missedcallnotifier Missedcallnotifier,
blacklistcallnotifier Blacklistcallnotifier,
Phoneaccountregistrar phoneaccountregistrar) {
...
Mwiredheadsetmanager = new Wiredheadsetmanager (context);
Mcallaudiomanager = new Callaudiomanager (context, statusbarnotifier, Mwiredheadsetmanager);
...
}
1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11
This is a class that manages audio status in a call, so it is necessary to set a new state and notify the state of the change. Thus this class may be the most important method of setsystemaudiostate (),
private void Setsystemaudiostate (Boolean force, Boolean ismuted, int route, int supportedroutemask) {
if (!hasfocus ()) {return;
} audiostate oldaudiostate = Maudiostate;
Saveaudiostate (New Audiostate (ismuted, Route, Supportedroutemask));
if (!force && objects.equals (oldaudiostate, maudiostate)) {return;
} log.i (this, "Changing audio state from%s to%s", Oldaudiostate, maudiostate);
Mute. if (maudiostate.ismuted () = Maudiomanager.ismicrophonemute ()) {log.i (this, "changing microphone mute State t
O:%b ", maudiostate.ismuted ());
Maudiomanager.setmicrophonemute (maudiostate.ismuted ());
}//Audio route.
if (maudiostate.getroute () = = Audiostate.route_bluetooth) {//set to Bluetooth Turnonspeaker (false);
Turnonbluetooth (TRUE);
} else if (maudiostate.getroute () = = Audiostate.route_speaker) {//Speaker Turnonbluetooth (FALSE);
Turnonspeaker (TRUE);
} else if (maudiostate.getroute () = = Audiostate.route_earpiece | |
Maudiostate.getroute () = = Audiostate.route_wired_headset) {//handset or wired headset turnonbluetooth (false);
Turnonspeaker (FALSE); } if (!oldaudiostate.equals (maudiostate)) {callsmanager.getinstance (). onaudiostatechanged (oldAudioSt
Ate, maudiostate);//Notification status change Updateaudioforforegroundcall (); }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
All of the previous steps to the end are almost all done in order to execute into this method, go to open/close speaker, "Turn on/Off" Bluetooth, and then notify the status changes. There is no separate way to inform the state of the change, just call the Callsmanager.getinstance () within this method. onaudiostatechanged (Oldaudiostate, maudiostate);.
It is noteworthy that Turnonspeaker (true) is passed Maudiomanager.setspeakerphoneon (on), while Turnonbluetooth (true); It is through Mbluetoothmanager.connectbluetoothaudio (), the way that Bluetooth does not return to the Audiomanager tube. Think about it too, there could be a Bluetooth keyboard connected.
Alternatively, switch to the handset and the wired headset and then turn off the speakers and Bluetooth. Callaudio Update
At first I wanted to write "audio update", but why change to "Callaudio update"? Because this audio is too close to call, it can be said that there is no audio there, and that many of the audio-related classes on Android M associated with call are renamed by Audio to Callaudio (such as Audiostate.java , Callaudiostate.java).
The most important approach to this class is setsystemaudiostate (), so look at the call hierarchy:
Then draw the schematic form:
Interpret the above figure in conjunction with the code. (Round setsystemaudiostate () and right rounded rectangle method with the same name, carrying parameters)
The rounded rectangle on the left indicates "set as default audio state" When calling this method, without having to carry audio-related parameters, the method generates an initialized audiostate itself. The two ellipses represent a scenario where all calls are removed, the default is restored, and an initialized audiostate is set to meet ' from Voicecall to Voicecall '.
The right rounded rectangle means "set audio state", calling this method with 4 parameters, namely: Force setting, whether Mute,audiostate, all currently supported audiostate.
Only the bottom setaudioroute () in the rightmost 6 ellipse is manually set, and our operation on the Incallui interface is passed from this entry. The rest can be thought of as automatic setup. audiostate
Let's talk about one of the key variables Maudiostate.
Maudiostate This variable almost carries all the audio related information, the key two:
/**
* @return The current audio route being used. How the current audio transfer is used
*
/public int getroute () {
return route;
}
/**
* @return Bit Mask of all routes supported by this call.//Current All supported modes of transmission
*/public
int Getsupportedroutema SK () {
return supportedroutemask;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13
As we have said above, audiostate changes by Callsmanager.getinstance (). onaudiostatechanged (Oldaudiostate, maudiostate); This line of code is updated, It can be understood to broadcast the value of the maudiostate. Maudiostate can be understood as the source of the data, once the maudiostate in addition to the problem, then the upper layer will certainly have problems.
(The ringtone exists longer than the call life cycle)
But in the existing code, when there is no call and no ringtone, this value is not updated (note ①), so this will cause a problem, what is the problem. Readers may wish to take a look at them.
The problem is that when the call and the ringtone are not present, the headset is plugged in, the audio changes caused by connecting/disconnecting the Bluetooth headset are not updated to Maudiostate, and the upper level will not be aware of changes in the Audiostate state, resulting in Audiobutton display errors. This phenomenon only in the caller status can be seen, the call is answered after the Audiobutton display normal, because in onincomingcallanswered () will Setsystemaudiostate () and then update audiostate.
Think about the solution. (Do not Disturb mode, multi-channel call)
04.14 Supplement
We found that on the Android M version, first set up a call, open the speaker, and then add a new call, the open speaker will be closed.
Find commit discovery, commit message writes to
Route audio to earpiece in dialing state if call was a Voice call and
Bluetooth or wired headset is not connected. This fixes an issue where
If we make a first video call and second outgoing call is voice, audio
are routed to speaker which are not expected.
In previous audio-related blogs, I introduced some of the usage strategies for speaker in video telephony, which was mentioned in the "first pass is a video call, the second is a voice call" scenario, but we found that when actually used, Two of all voice calls will also be turned off.
There is no right or wrong here, but you may need to reconsider the audio switching strategy. There is also a need to see if the above submission is accurate enough to achieve the desired effect.