Merge "AudioService AudioDeviceBroker: fix speakerphone control" into rvc-dev am: bf01a79a83
Change-Id: I922d2be182c9937e82790e8b4ab9b49213d1e2c4
This commit is contained in:
@@ -1505,7 +1505,7 @@ public class AudioManager {
|
|||||||
public void setSpeakerphoneOn(boolean on){
|
public void setSpeakerphoneOn(boolean on){
|
||||||
final IAudioService service = getService();
|
final IAudioService service = getService();
|
||||||
try {
|
try {
|
||||||
service.setSpeakerphoneOn(on);
|
service.setSpeakerphoneOn(mICallBack, on);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ interface IAudioService {
|
|||||||
|
|
||||||
oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
|
oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
|
||||||
|
|
||||||
void setSpeakerphoneOn(boolean on);
|
void setSpeakerphoneOn(IBinder cb, boolean on);
|
||||||
|
|
||||||
boolean isSpeakerphoneOn();
|
boolean isSpeakerphoneOn();
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.os.IBinder;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
@@ -43,6 +44,9 @@ import android.util.PrintWriterPrinter;
|
|||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
/*package*/ final class AudioDeviceBroker {
|
/*package*/ final class AudioDeviceBroker {
|
||||||
@@ -91,6 +95,9 @@ import java.io.PrintWriter;
|
|||||||
// TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
|
// TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
|
||||||
/*package*/ final Object mSetModeLock = new Object();
|
/*package*/ final Object mSetModeLock = new Object();
|
||||||
|
|
||||||
|
/** PID of current audio mode owner communicated by AudioService */
|
||||||
|
private int mModeOwnerPid = 0;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
|
/*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -136,6 +143,7 @@ import java.io.PrintWriter;
|
|||||||
/*package*/ void onSystemReady() {
|
/*package*/ void onSystemReady() {
|
||||||
synchronized (mSetModeLock) {
|
synchronized (mSetModeLock) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
|
mModeOwnerPid = mAudioService.getModeOwnerPid();
|
||||||
mBtHelper.onSystemReady();
|
mBtHelper.onSystemReady();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,30 +210,57 @@ import java.io.PrintWriter;
|
|||||||
* @param eventSource for logging purposes
|
* @param eventSource for logging purposes
|
||||||
* @return true if speakerphone state changed
|
* @return true if speakerphone state changed
|
||||||
*/
|
*/
|
||||||
/*package*/ boolean setSpeakerphoneOn(boolean on, String eventSource) {
|
/*package*/ boolean setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
final boolean wasOn = isSpeakerphoneOn();
|
if (!addSpeakerphoneClient(cb, pid, on)) {
|
||||||
if (on) {
|
return false;
|
||||||
if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
|
|
||||||
setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
|
|
||||||
}
|
|
||||||
mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
|
|
||||||
} else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
|
|
||||||
if (mBtHelper.isBluetoothScoOn()) {
|
|
||||||
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
|
|
||||||
setForceUse_Async(
|
|
||||||
AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
|
|
||||||
} else {
|
|
||||||
mForcedUseForComm = AudioSystem.FORCE_NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
final boolean wasOn = isSpeakerphoneOn();
|
||||||
mForcedUseForCommExt = mForcedUseForComm;
|
updateSpeakerphoneOn(eventSource);
|
||||||
setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
|
|
||||||
return (wasOn != isSpeakerphoneOn());
|
return (wasOn != isSpeakerphoneOn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mDeviceStateLock")
|
||||||
|
private void updateSpeakerphoneOn(String eventSource) {
|
||||||
|
if (isSpeakerphoneOnRequested()) {
|
||||||
|
if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
|
||||||
|
setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
|
||||||
|
}
|
||||||
|
mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
|
||||||
|
} else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
|
||||||
|
if (mBtHelper.isBluetoothScoOn()) {
|
||||||
|
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
|
||||||
|
setForceUse_Async(
|
||||||
|
AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
|
||||||
|
} else {
|
||||||
|
mForcedUseForComm = AudioSystem.FORCE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mForcedUseForCommExt = mForcedUseForComm;
|
||||||
|
setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if speakerphone is requested ON or OFF.
|
||||||
|
* If the current audio mode owner is in the speakerphone client list, use this preference.
|
||||||
|
* Otherwise use first client's preference (first client corresponds to latest request).
|
||||||
|
* Speakerphone is requested OFF if no client is in the list.
|
||||||
|
* @return true if speakerphone is requested ON, false otherwise
|
||||||
|
*/
|
||||||
|
@GuardedBy("mDeviceStateLock")
|
||||||
|
private boolean isSpeakerphoneOnRequested() {
|
||||||
|
if (mSpeakerphoneClients.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (SpeakerphoneClient cl : mSpeakerphoneClients) {
|
||||||
|
if (cl.getPid() == mModeOwnerPid) {
|
||||||
|
return cl.isOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mSpeakerphoneClients.get(0).isOn();
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ boolean isSpeakerphoneOn() {
|
/*package*/ boolean isSpeakerphoneOn() {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
|
return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
|
||||||
@@ -384,7 +419,8 @@ import java.io.PrintWriter;
|
|||||||
}
|
}
|
||||||
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
|
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
|
||||||
} else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
|
} else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
|
||||||
mForcedUseForComm = AudioSystem.FORCE_NONE;
|
mForcedUseForComm = isSpeakerphoneOnRequested()
|
||||||
|
? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE;
|
||||||
}
|
}
|
||||||
mForcedUseForCommExt = mForcedUseForComm;
|
mForcedUseForCommExt = mForcedUseForComm;
|
||||||
AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off"));
|
AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off"));
|
||||||
@@ -429,8 +465,8 @@ import java.io.PrintWriter;
|
|||||||
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
|
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postDisconnectBluetoothSco(int exceptPid) {
|
/*package*/ void postSetModeOwnerPid(int pid) {
|
||||||
sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid);
|
sendIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
|
/*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
|
||||||
@@ -483,7 +519,7 @@ import java.io.PrintWriter;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getModeOwnerPid() {
|
/*package*/ int getModeOwnerPid() {
|
||||||
return mAudioService.getModeOwnerPid();
|
return mModeOwnerPid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getDeviceForStream(int streamType) {
|
/*package*/ int getDeviceForStream(int streamType) {
|
||||||
@@ -605,6 +641,10 @@ import java.io.PrintWriter;
|
|||||||
sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
|
sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ void postSpeakerphoneClientDied(Object obj) {
|
||||||
|
sendLMsgNoDelay(MSG_L_SPEAKERPHONE_CLIENT_DIED, SENDMSG_QUEUE, obj);
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy,
|
/*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy,
|
||||||
AudioDeviceAttributes device)
|
AudioDeviceAttributes device)
|
||||||
{
|
{
|
||||||
@@ -674,7 +714,7 @@ import java.io.PrintWriter;
|
|||||||
new BtHelper.BluetoothA2dpDeviceInfo(btDevice);
|
new BtHelper.BluetoothA2dpDeviceInfo(btDevice);
|
||||||
return (mBrokerHandler.hasEqualMessages(
|
return (mBrokerHandler.hasEqualMessages(
|
||||||
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck)
|
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck)
|
||||||
|| mBrokerHandler.hasEqualMessages(
|
|| mBrokerHandler.hasEqualMessages(
|
||||||
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck));
|
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,7 +747,20 @@ import java.io.PrintWriter;
|
|||||||
} else {
|
} else {
|
||||||
pw.println("Message handler is null");
|
pw.println("Message handler is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeviceInventory.dump(pw, prefix);
|
mDeviceInventory.dump(pw, prefix);
|
||||||
|
|
||||||
|
pw.println("\n" + prefix + "mForcedUseForComm: "
|
||||||
|
+ AudioSystem.forceUseConfigToString(mForcedUseForComm));
|
||||||
|
pw.println(prefix + "mForcedUseForCommExt: "
|
||||||
|
+ AudioSystem.forceUseConfigToString(mForcedUseForCommExt));
|
||||||
|
pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
|
||||||
|
pw.println(prefix + "Speakerphone clients:");
|
||||||
|
mSpeakerphoneClients.forEach((cl) -> {
|
||||||
|
pw.println(" " + prefix + "pid: " + cl.getPid() + " on: "
|
||||||
|
+ cl.isOn() + " cb: " + cl.getBinder()); });
|
||||||
|
|
||||||
|
mBtHelper.dump(pw, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
@@ -877,10 +930,16 @@ import java.io.PrintWriter;
|
|||||||
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
|
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_I_DISCONNECT_BT_SCO:
|
case MSG_I_SET_MODE_OWNER_PID:
|
||||||
synchronized (mSetModeLock) {
|
synchronized (mSetModeLock) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mBtHelper.disconnectBluetoothSco(msg.arg1);
|
if (mModeOwnerPid != msg.arg1) {
|
||||||
|
mModeOwnerPid = msg.arg1;
|
||||||
|
updateSpeakerphoneOn("setNewModeOwner");
|
||||||
|
if (mModeOwnerPid != 0) {
|
||||||
|
mBtHelper.disconnectBluetoothSco(mModeOwnerPid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -891,6 +950,11 @@ import java.io.PrintWriter;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MSG_L_SPEAKERPHONE_CLIENT_DIED:
|
||||||
|
synchronized (mDeviceStateLock) {
|
||||||
|
speakerphoneClientDied(msg.obj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case MSG_TOGGLE_HDMI:
|
case MSG_TOGGLE_HDMI:
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mDeviceInventory.onToggleHdmi();
|
mDeviceInventory.onToggleHdmi();
|
||||||
@@ -1021,7 +1085,7 @@ import java.io.PrintWriter;
|
|||||||
private static final int MSG_REPORT_NEW_ROUTES = 13;
|
private static final int MSG_REPORT_NEW_ROUTES = 13;
|
||||||
private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
|
private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
|
||||||
private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
|
private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
|
||||||
private static final int MSG_I_DISCONNECT_BT_SCO = 16;
|
private static final int MSG_I_SET_MODE_OWNER_PID = 16;
|
||||||
|
|
||||||
// process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo
|
// process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo
|
||||||
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
|
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
|
||||||
@@ -1051,6 +1115,8 @@ import java.io.PrintWriter;
|
|||||||
private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33;
|
private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33;
|
||||||
private static final int MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY = 34;
|
private static final int MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY = 34;
|
||||||
|
|
||||||
|
private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35;
|
||||||
|
|
||||||
|
|
||||||
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
||||||
switch(msgId) {
|
switch(msgId) {
|
||||||
@@ -1166,4 +1232,93 @@ import java.io.PrintWriter;
|
|||||||
time);
|
time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SpeakerphoneClient implements IBinder.DeathRecipient {
|
||||||
|
private final IBinder mCb;
|
||||||
|
private final int mPid;
|
||||||
|
private final boolean mOn;
|
||||||
|
SpeakerphoneClient(IBinder cb, int pid, boolean on) {
|
||||||
|
mCb = cb;
|
||||||
|
mPid = pid;
|
||||||
|
mOn = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean registerDeathRecipient() {
|
||||||
|
boolean status = false;
|
||||||
|
try {
|
||||||
|
mCb.linkToDeath(this, 0);
|
||||||
|
status = true;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "SpeakerphoneClient could not link to " + mCb + " binder death");
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterDeathRecipient() {
|
||||||
|
try {
|
||||||
|
mCb.unlinkToDeath(this, 0);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
Log.w(TAG, "SpeakerphoneClient could not not unregistered to binder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
postSpeakerphoneClientDied(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IBinder getBinder() {
|
||||||
|
return mCb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getPid() {
|
||||||
|
return mPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isOn() {
|
||||||
|
return mOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mDeviceStateLock")
|
||||||
|
private void speakerphoneClientDied(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Speaker client died");
|
||||||
|
if (removeSpeakerphoneClient(((SpeakerphoneClient) obj).getBinder(), false) != null) {
|
||||||
|
updateSpeakerphoneOn("speakerphoneClientDied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpeakerphoneClient removeSpeakerphoneClient(IBinder cb, boolean unregister) {
|
||||||
|
for (SpeakerphoneClient cl : mSpeakerphoneClients) {
|
||||||
|
if (cl.getBinder() == cb) {
|
||||||
|
if (unregister) {
|
||||||
|
cl.unregisterDeathRecipient();
|
||||||
|
}
|
||||||
|
mSpeakerphoneClients.remove(cl);
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mDeviceStateLock")
|
||||||
|
private boolean addSpeakerphoneClient(IBinder cb, int pid, boolean on) {
|
||||||
|
// always insert new request at first position
|
||||||
|
removeSpeakerphoneClient(cb, true);
|
||||||
|
SpeakerphoneClient client = new SpeakerphoneClient(cb, pid, on);
|
||||||
|
if (client.registerDeathRecipient()) {
|
||||||
|
mSpeakerphoneClients.add(0, client);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of clients requesting speakerPhone ON
|
||||||
|
@GuardedBy("mDeviceStateLock")
|
||||||
|
private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients =
|
||||||
|
new ArrayList<SpeakerphoneClient>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3567,11 +3567,9 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
int oldModeOwnerPid;
|
|
||||||
int newModeOwnerPid = 0;
|
int newModeOwnerPid = 0;
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
Log.w(TAG, "setMode() client died");
|
Log.w(TAG, "setMode() client died");
|
||||||
oldModeOwnerPid = getModeOwnerPid();
|
|
||||||
int index = mSetModeDeathHandlers.indexOf(this);
|
int index = mSetModeDeathHandlers.indexOf(this);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
Log.w(TAG, "unregistered setMode() client died");
|
Log.w(TAG, "unregistered setMode() client died");
|
||||||
@@ -3581,9 +3579,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
||||||
// SCO connections not started by the application changing the mode when pid changes
|
// SCO connections not started by the application changing the mode when pid changes
|
||||||
if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
|
mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
|
||||||
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPid() {
|
public int getPid() {
|
||||||
@@ -3635,17 +3631,20 @@ public class AudioService extends IAudioService.Stub
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oldModeOwnerPid;
|
|
||||||
int newModeOwnerPid;
|
int newModeOwnerPid;
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
if (mode == AudioSystem.MODE_CURRENT) {
|
if (mode == AudioSystem.MODE_CURRENT) {
|
||||||
mode = mMode;
|
mode = mMode;
|
||||||
}
|
}
|
||||||
oldModeOwnerPid = getModeOwnerPid();
|
int oldModeOwnerPid = getModeOwnerPid();
|
||||||
// Do not allow changing mode if a call is active and the requester
|
// Do not allow changing mode if a call is active and the requester
|
||||||
// does not have permission to modify phone state or is not the mode owner.
|
// does not have permission to modify phone state or is not the mode owner,
|
||||||
if (((mMode == AudioSystem.MODE_IN_CALL)
|
// unless returning to NORMAL mode (will not change current mode owner) or
|
||||||
|| (mMode == AudioSystem.MODE_IN_COMMUNICATION))
|
// not changing mode in which case the mode owner will reflect the last
|
||||||
|
// requester of current mode
|
||||||
|
if (!((mode == mMode) || (mode == AudioSystem.MODE_NORMAL))
|
||||||
|
&& ((mMode == AudioSystem.MODE_IN_CALL)
|
||||||
|
|| (mMode == AudioSystem.MODE_IN_COMMUNICATION))
|
||||||
&& !(hasModifyPhoneStatePermission || (oldModeOwnerPid == callingPid))) {
|
&& !(hasModifyPhoneStatePermission || (oldModeOwnerPid == callingPid))) {
|
||||||
Log.w(TAG, "setMode(" + mode + ") from pid=" + callingPid
|
Log.w(TAG, "setMode(" + mode + ") from pid=" + callingPid
|
||||||
+ ", uid=" + Binder.getCallingUid()
|
+ ", uid=" + Binder.getCallingUid()
|
||||||
@@ -3658,9 +3657,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
||||||
// SCO connections not started by the application changing the mode when pid changes
|
// SCO connections not started by the application changing the mode when pid changes
|
||||||
if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
|
mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
|
||||||
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setModeInt() returns a valid PID if the audio mode was successfully set to
|
// setModeInt() returns a valid PID if the audio mode was successfully set to
|
||||||
@@ -3937,32 +3934,18 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @see AudioManager#setSpeakerphoneOn(boolean) */
|
/** @see AudioManager#setSpeakerphoneOn(boolean) */
|
||||||
public void setSpeakerphoneOn(boolean on){
|
public void setSpeakerphoneOn(IBinder cb, boolean on) {
|
||||||
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
|
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mContext.checkCallingOrSelfPermission(
|
|
||||||
android.Manifest.permission.MODIFY_PHONE_STATE)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
synchronized (mSetModeDeathHandlers) {
|
|
||||||
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
|
||||||
if (h.getMode() == AudioSystem.MODE_IN_CALL) {
|
|
||||||
Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
|
|
||||||
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for logging only
|
// for logging only
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
|
final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
|
||||||
.append(") from u/pid:").append(uid).append("/")
|
.append(") from u/pid:").append(uid).append("/")
|
||||||
.append(pid).toString();
|
.append(pid).toString();
|
||||||
final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(on, eventSource);
|
final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
|
||||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
||||||
+ MediaMetrics.SEPARATOR + "setSpeakerphoneOn")
|
+ MediaMetrics.SEPARATOR + "setSpeakerphoneOn")
|
||||||
.setUid(uid)
|
.setUid(uid)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
@@ -131,6 +132,26 @@ public class BtHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the scoAudioState.
|
||||||
|
*/
|
||||||
|
public static String scoAudioStateToString(int scoAudioState) {
|
||||||
|
switch (scoAudioState) {
|
||||||
|
case SCO_STATE_INACTIVE:
|
||||||
|
return "SCO_STATE_INACTIVE";
|
||||||
|
case SCO_STATE_ACTIVATE_REQ:
|
||||||
|
return "SCO_STATE_ACTIVATE_REQ";
|
||||||
|
case SCO_STATE_ACTIVE_EXTERNAL:
|
||||||
|
return "SCO_STATE_ACTIVE_EXTERNAL";
|
||||||
|
case SCO_STATE_ACTIVE_INTERNAL:
|
||||||
|
return "SCO_STATE_ACTIVE_INTERNAL";
|
||||||
|
case SCO_STATE_DEACTIVATING:
|
||||||
|
return "SCO_STATE_DEACTIVATING";
|
||||||
|
default:
|
||||||
|
return "SCO_STATE_(" + scoAudioState + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
/*package*/ static class BluetoothA2dpDeviceInfo {
|
/*package*/ static class BluetoothA2dpDeviceInfo {
|
||||||
private final @NonNull BluetoothDevice mBtDevice;
|
private final @NonNull BluetoothDevice mBtDevice;
|
||||||
@@ -1007,4 +1028,20 @@ public class BtHelper {
|
|||||||
return "ENCODING_BT_CODEC_TYPE(" + btCodecType + ")";
|
return "ENCODING_BT_CODEC_TYPE(" + btCodecType + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
/*package*/ void dump(PrintWriter pw, String prefix) {
|
||||||
|
pw.println("\n" + prefix + "mBluetoothHeadset: " + mBluetoothHeadset);
|
||||||
|
pw.println(prefix + "mBluetoothHeadsetDevice: " + mBluetoothHeadsetDevice);
|
||||||
|
pw.println(prefix + "mScoAudioState: " + scoAudioStateToString(mScoAudioState));
|
||||||
|
pw.println(prefix + "mScoAudioMode: " + scoAudioModeToString(mScoAudioMode));
|
||||||
|
pw.println(prefix + "Sco clients:");
|
||||||
|
mScoClients.forEach((cl) -> {
|
||||||
|
pw.println(" " + prefix + "pid: " + cl.getPid() + " cb: " + cl.getBinder()); });
|
||||||
|
|
||||||
|
pw.println("\n" + prefix + "mHearingAid: " + mHearingAid);
|
||||||
|
pw.println(prefix + "mA2dp: " + mA2dp);
|
||||||
|
pw.println(prefix + "mAvrcpAbsVolSupported: " + mAvrcpAbsVolSupported);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user