AudioDeviceBroker: ignore communication route requests by idle apps am: 43e951b21d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23783543 Change-Id: Id6fb47c64d84495bdf14c9e44049000215e7a0a8 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -30,6 +30,8 @@ import android.media.AudioAttributes;
|
|||||||
import android.media.AudioDeviceAttributes;
|
import android.media.AudioDeviceAttributes;
|
||||||
import android.media.AudioDeviceInfo;
|
import android.media.AudioDeviceInfo;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioPlaybackConfiguration;
|
||||||
|
import android.media.AudioRecordingConfiguration;
|
||||||
import android.media.AudioRoutesInfo;
|
import android.media.AudioRoutesInfo;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
import android.media.BluetoothProfileConnectionInfo;
|
import android.media.BluetoothProfileConnectionInfo;
|
||||||
@@ -289,37 +291,38 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* @param on
|
* @param on
|
||||||
* @param eventSource for logging purposes
|
* @param eventSource for logging purposes
|
||||||
*/
|
*/
|
||||||
/*package*/ void setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) {
|
/*package*/ void setSpeakerphoneOn(
|
||||||
|
IBinder cb, int uid, boolean on, boolean isPrivileged, String eventSource) {
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "setSpeakerphoneOn, on: " + on + " pid: " + pid);
|
Log.v(TAG, "setSpeakerphoneOn, on: " + on + " uid: " + uid);
|
||||||
}
|
}
|
||||||
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
||||||
cb, pid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""),
|
cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""),
|
||||||
on, BtHelper.SCO_MODE_UNDEFINED, eventSource, false));
|
on, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select device for use for communication use cases.
|
* Select device for use for communication use cases.
|
||||||
* @param cb Client binder for death detection
|
* @param cb Client binder for death detection
|
||||||
* @param pid Client pid
|
* @param uid Client uid
|
||||||
* @param device Device selected or null to unselect.
|
* @param device Device selected or null to unselect.
|
||||||
* @param eventSource for logging purposes
|
* @param eventSource for logging purposes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000;
|
private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000;
|
||||||
|
|
||||||
/*package*/ boolean setCommunicationDevice(
|
/*package*/ boolean setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device,
|
||||||
IBinder cb, int pid, AudioDeviceInfo device, String eventSource) {
|
boolean isPrivileged, String eventSource) {
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "setCommunicationDevice, device: " + device + ", pid: " + pid);
|
Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDeviceAttributes deviceAttr =
|
AudioDeviceAttributes deviceAttr =
|
||||||
(device != null) ? new AudioDeviceAttributes(device) : null;
|
(device != null) ? new AudioDeviceAttributes(device) : null;
|
||||||
CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, pid, deviceAttr,
|
CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, uid, deviceAttr,
|
||||||
device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, true);
|
device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, true, isPrivileged);
|
||||||
postSetCommunicationDeviceForClient(deviceInfo);
|
postSetCommunicationDeviceForClient(deviceInfo);
|
||||||
boolean status;
|
boolean status;
|
||||||
synchronized (deviceInfo) {
|
synchronized (deviceInfo) {
|
||||||
@@ -353,7 +356,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo);
|
Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo);
|
||||||
}
|
}
|
||||||
if (!deviceInfo.mOn) {
|
if (!deviceInfo.mOn) {
|
||||||
CommunicationRouteClient client = getCommunicationRouteClientForPid(deviceInfo.mPid);
|
CommunicationRouteClient client = getCommunicationRouteClientForUid(deviceInfo.mUid);
|
||||||
if (client == null || (deviceInfo.mDevice != null
|
if (client == null || (deviceInfo.mDevice != null
|
||||||
&& !deviceInfo.mDevice.equals(client.getDevice()))) {
|
&& !deviceInfo.mDevice.equals(client.getDevice()))) {
|
||||||
return false;
|
return false;
|
||||||
@@ -361,22 +364,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null;
|
AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null;
|
||||||
setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mPid, device,
|
setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mUid, device,
|
||||||
deviceInfo.mScoAudioMode, deviceInfo.mEventSource);
|
deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
/*package*/ void setCommunicationRouteForClient(
|
/*package*/ void setCommunicationRouteForClient(
|
||||||
IBinder cb, int pid, AudioDeviceAttributes device,
|
IBinder cb, int uid, AudioDeviceAttributes device,
|
||||||
int scoAudioMode, String eventSource) {
|
int scoAudioMode, boolean isPrivileged, String eventSource) {
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
|
Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
|
||||||
}
|
}
|
||||||
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
|
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
|
||||||
"setCommunicationRouteForClient for pid: " + pid
|
"setCommunicationRouteForClient for uid: " + uid
|
||||||
+ " device: " + device
|
+ " device: " + device + " isPrivileged: " + isPrivileged
|
||||||
+ " from API: " + eventSource)).printLog(TAG));
|
+ " from API: " + eventSource)).printLog(TAG));
|
||||||
|
|
||||||
final boolean wasBtScoRequested = isBluetoothScoRequested();
|
final boolean wasBtScoRequested = isBluetoothScoRequested();
|
||||||
@@ -385,16 +388,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
// Save previous client route in case of failure to start BT SCO audio
|
// Save previous client route in case of failure to start BT SCO audio
|
||||||
AudioDeviceAttributes prevClientDevice = null;
|
AudioDeviceAttributes prevClientDevice = null;
|
||||||
client = getCommunicationRouteClientForPid(pid);
|
boolean prevPrivileged = false;
|
||||||
|
client = getCommunicationRouteClientForUid(uid);
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
prevClientDevice = client.getDevice();
|
prevClientDevice = client.getDevice();
|
||||||
|
prevPrivileged = client.isPrivileged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
client = addCommunicationRouteClient(cb, pid, device);
|
client = addCommunicationRouteClient(cb, uid, device, isPrivileged);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
Log.w(TAG, "setCommunicationRouteForClient: could not add client for pid: "
|
Log.w(TAG, "setCommunicationRouteForClient: could not add client for uid: "
|
||||||
+ pid + " and device: " + device);
|
+ uid + " and device: " + device);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client = removeCommunicationRouteClient(cb, true);
|
client = removeCommunicationRouteClient(cb, true);
|
||||||
@@ -406,11 +411,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
boolean isBtScoRequested = isBluetoothScoRequested();
|
boolean isBtScoRequested = isBluetoothScoRequested();
|
||||||
if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) {
|
if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) {
|
||||||
if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
|
if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
|
||||||
Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for pid: "
|
Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for uid: "
|
||||||
+ pid);
|
+ uid);
|
||||||
// clean up or restore previous client selection
|
// clean up or restore previous client selection
|
||||||
if (prevClientDevice != null) {
|
if (prevClientDevice != null) {
|
||||||
addCommunicationRouteClient(cb, pid, prevClientDevice);
|
addCommunicationRouteClient(cb, uid, prevClientDevice, prevPrivileged);
|
||||||
} else {
|
} else {
|
||||||
removeCommunicationRouteClient(cb, true);
|
removeCommunicationRouteClient(cb, true);
|
||||||
}
|
}
|
||||||
@@ -447,11 +452,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
private CommunicationRouteClient topCommunicationRouteClient() {
|
private CommunicationRouteClient topCommunicationRouteClient() {
|
||||||
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
|
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
|
||||||
if (crc.getPid() == mAudioModeOwner.mPid) {
|
if (crc.getUid() == mAudioModeOwner.mUid) {
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0) {
|
if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0
|
||||||
|
&& mCommunicationRouteClients.get(0).isActive()) {
|
||||||
return mCommunicationRouteClients.get(0);
|
return mCommunicationRouteClients.get(0);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1107,26 +1113,26 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info);
|
sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode,
|
/*package*/ void startBluetoothScoForClient(IBinder cb, int uid, int scoAudioMode,
|
||||||
@NonNull String eventSource) {
|
boolean isPrivileged, @NonNull String eventSource) {
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "startBluetoothScoForClient, pid: " + pid);
|
Log.v(TAG, "startBluetoothScoForClient, uid: " + uid);
|
||||||
}
|
}
|
||||||
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
||||||
cb, pid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
|
cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
|
||||||
true, scoAudioMode, eventSource, false));
|
true, scoAudioMode, eventSource, false, isPrivileged));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void stopBluetoothScoForClient(
|
/*package*/ void stopBluetoothScoForClient(
|
||||||
IBinder cb, int pid, @NonNull String eventSource) {
|
IBinder cb, int uid, boolean isPrivileged, @NonNull String eventSource) {
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "stopBluetoothScoForClient, pid: " + pid);
|
Log.v(TAG, "stopBluetoothScoForClient, uid: " + uid);
|
||||||
}
|
}
|
||||||
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
|
||||||
cb, pid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
|
cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
|
||||||
false, BtHelper.SCO_MODE_UNDEFINED, eventSource, false));
|
false, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
|
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
|
||||||
@@ -1367,22 +1373,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
/*package*/ static final class CommunicationDeviceInfo {
|
/*package*/ static final class CommunicationDeviceInfo {
|
||||||
final @NonNull IBinder mCb; // Identifies the requesting client for death handler
|
final @NonNull IBinder mCb; // Identifies the requesting client for death handler
|
||||||
final int mPid; // Requester process ID
|
final int mUid; // Requester UID
|
||||||
final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset.
|
final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset.
|
||||||
final boolean mOn; // true if setting, false if resetting
|
final boolean mOn; // true if setting, false if resetting
|
||||||
final int mScoAudioMode; // only used for SCO: requested audio mode
|
final int mScoAudioMode; // only used for SCO: requested audio mode
|
||||||
|
final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission
|
||||||
final @NonNull String mEventSource; // caller identifier for logging
|
final @NonNull String mEventSource; // caller identifier for logging
|
||||||
boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent)
|
boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent)
|
||||||
boolean mStatus = false; // completion status only used if mWaitForStatus is true
|
boolean mStatus = false; // completion status only used if mWaitForStatus is true
|
||||||
|
|
||||||
CommunicationDeviceInfo(@NonNull IBinder cb, int pid,
|
CommunicationDeviceInfo(@NonNull IBinder cb, int uid,
|
||||||
@Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode,
|
@Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode,
|
||||||
@NonNull String eventSource, boolean waitForStatus) {
|
@NonNull String eventSource, boolean waitForStatus, boolean isPrivileged) {
|
||||||
mCb = cb;
|
mCb = cb;
|
||||||
mPid = pid;
|
mUid = uid;
|
||||||
mDevice = device;
|
mDevice = device;
|
||||||
mOn = on;
|
mOn = on;
|
||||||
mScoAudioMode = scoAudioMode;
|
mScoAudioMode = scoAudioMode;
|
||||||
|
mIsPrivileged = isPrivileged;
|
||||||
mEventSource = eventSource;
|
mEventSource = eventSource;
|
||||||
mWaitForStatus = waitForStatus;
|
mWaitForStatus = waitForStatus;
|
||||||
}
|
}
|
||||||
@@ -1401,16 +1409,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mCb.equals(((CommunicationDeviceInfo) o).mCb)
|
return mCb.equals(((CommunicationDeviceInfo) o).mCb)
|
||||||
&& mPid == ((CommunicationDeviceInfo) o).mPid;
|
&& mUid == ((CommunicationDeviceInfo) o).mUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CommunicationDeviceInfo mCb=" + mCb.toString()
|
return "CommunicationDeviceInfo mCb=" + mCb.toString()
|
||||||
+ " mPid=" + mPid
|
+ " mUid=" + mUid
|
||||||
+ " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]"
|
+ " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]"
|
||||||
+ " mOn=" + mOn
|
+ " mOn=" + mOn
|
||||||
+ " mScoAudioMode=" + mScoAudioMode
|
+ " mScoAudioMode=" + mScoAudioMode
|
||||||
|
+ " mIsPrivileged=" + mIsPrivileged
|
||||||
+ " mEventSource=" + mEventSource
|
+ " mEventSource=" + mEventSource
|
||||||
+ " mWaitForStatus=" + mWaitForStatus
|
+ " mWaitForStatus=" + mWaitForStatus
|
||||||
+ " mStatus=" + mStatus;
|
+ " mStatus=" + mStatus;
|
||||||
@@ -1507,8 +1516,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
pw.println("\n" + prefix + "Communication route clients:");
|
pw.println("\n" + prefix + "Communication route clients:");
|
||||||
mCommunicationRouteClients.forEach((cl) -> {
|
mCommunicationRouteClients.forEach((cl) -> {
|
||||||
pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
|
pw.println(" " + prefix + cl.toString()); });
|
||||||
+ cl.getDevice() + " cb: " + cl.getBinder()); });
|
|
||||||
|
|
||||||
pw.println("\n" + prefix + "Computed Preferred communication device: "
|
pw.println("\n" + prefix + "Computed Preferred communication device: "
|
||||||
+ preferredCommunicationDevice());
|
+ preferredCommunicationDevice());
|
||||||
@@ -2101,13 +2109,20 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
private class CommunicationRouteClient implements IBinder.DeathRecipient {
|
private class CommunicationRouteClient implements IBinder.DeathRecipient {
|
||||||
private final IBinder mCb;
|
private final IBinder mCb;
|
||||||
private final int mPid;
|
private final int mUid;
|
||||||
|
private final boolean mIsPrivileged;
|
||||||
private AudioDeviceAttributes mDevice;
|
private AudioDeviceAttributes mDevice;
|
||||||
|
private boolean mPlaybackActive;
|
||||||
|
private boolean mRecordingActive;
|
||||||
|
|
||||||
CommunicationRouteClient(IBinder cb, int pid, AudioDeviceAttributes device) {
|
CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device,
|
||||||
|
boolean isPrivileged) {
|
||||||
mCb = cb;
|
mCb = cb;
|
||||||
mPid = pid;
|
mUid = uid;
|
||||||
mDevice = device;
|
mDevice = device;
|
||||||
|
mIsPrivileged = isPrivileged;
|
||||||
|
mPlaybackActive = mAudioService.isPlaybackActiveForUid(uid);
|
||||||
|
mRecordingActive = mAudioService.isRecordingActiveForUid(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean registerDeathRecipient() {
|
public boolean registerDeathRecipient() {
|
||||||
@@ -2138,13 +2153,38 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return mCb;
|
return mCb;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getPid() {
|
int getUid() {
|
||||||
return mPid;
|
return mUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPrivileged() {
|
||||||
|
return mIsPrivileged;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDeviceAttributes getDevice() {
|
AudioDeviceAttributes getDevice() {
|
||||||
return mDevice;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPlaybackActive(boolean active) {
|
||||||
|
mPlaybackActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordingActive(boolean active) {
|
||||||
|
mRecordingActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return mIsPrivileged || mRecordingActive || mPlaybackActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[CommunicationRouteClient: mUid: " + mUid
|
||||||
|
+ " mDevice: " + mDevice.toString()
|
||||||
|
+ " mIsPrivileged: " + mIsPrivileged
|
||||||
|
+ " mPlaybackActive: " + mPlaybackActive
|
||||||
|
+ " mRecordingActive: " + mRecordingActive + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @GuardedBy("mSetModeLock")
|
// @GuardedBy("mSetModeLock")
|
||||||
@@ -2154,8 +2194,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Communication client died");
|
Log.w(TAG, "Communication client died");
|
||||||
setCommunicationRouteForClient(client.getBinder(), client.getPid(), null,
|
setCommunicationRouteForClient(client.getBinder(), client.getUid(), null,
|
||||||
BtHelper.SCO_MODE_UNDEFINED, "onCommunicationRouteClientDied");
|
BtHelper.SCO_MODE_UNDEFINED, client.isPrivileged(),
|
||||||
|
"onCommunicationRouteClientDied");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2242,8 +2283,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
+ crc + " eventSource: " + eventSource);
|
+ crc + " eventSource: " + eventSource);
|
||||||
}
|
}
|
||||||
if (crc != null) {
|
if (crc != null) {
|
||||||
setCommunicationRouteForClient(crc.getBinder(), crc.getPid(), crc.getDevice(),
|
setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
|
||||||
BtHelper.SCO_MODE_UNDEFINED, eventSource);
|
BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2282,11 +2323,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
private CommunicationRouteClient addCommunicationRouteClient(
|
private CommunicationRouteClient addCommunicationRouteClient(IBinder cb, int uid,
|
||||||
IBinder cb, int pid, AudioDeviceAttributes device) {
|
AudioDeviceAttributes device, boolean isPrivileged) {
|
||||||
// always insert new request at first position
|
// always insert new request at first position
|
||||||
removeCommunicationRouteClient(cb, true);
|
removeCommunicationRouteClient(cb, true);
|
||||||
CommunicationRouteClient client = new CommunicationRouteClient(cb, pid, device);
|
CommunicationRouteClient client =
|
||||||
|
new CommunicationRouteClient(cb, uid, device, isPrivileged);
|
||||||
if (client.registerDeathRecipient()) {
|
if (client.registerDeathRecipient()) {
|
||||||
mCommunicationRouteClients.add(0, client);
|
mCommunicationRouteClients.add(0, client);
|
||||||
return client;
|
return client;
|
||||||
@@ -2295,9 +2337,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
private CommunicationRouteClient getCommunicationRouteClientForPid(int pid) {
|
private CommunicationRouteClient getCommunicationRouteClientForUid(int uid) {
|
||||||
for (CommunicationRouteClient cl : mCommunicationRouteClients) {
|
for (CommunicationRouteClient cl : mCommunicationRouteClients) {
|
||||||
if (cl.getPid() == pid) {
|
if (cl.getUid() == uid) {
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2330,6 +2372,45 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateCommunicationRouteClientsActivity(
|
||||||
|
List<AudioPlaybackConfiguration> playbackConfigs,
|
||||||
|
List<AudioRecordingConfiguration> recordConfigs) {
|
||||||
|
synchronized (mSetModeLock) {
|
||||||
|
synchronized (mDeviceStateLock) {
|
||||||
|
boolean updateCommunicationRoute = false;
|
||||||
|
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
|
||||||
|
boolean wasActive = crc.isActive();
|
||||||
|
if (playbackConfigs != null) {
|
||||||
|
crc.setPlaybackActive(false);
|
||||||
|
for (AudioPlaybackConfiguration config : playbackConfigs) {
|
||||||
|
if (config.getClientUid() == crc.getUid()
|
||||||
|
&& config.isActive()) {
|
||||||
|
crc.setPlaybackActive(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (recordConfigs != null) {
|
||||||
|
crc.setRecordingActive(false);
|
||||||
|
for (AudioRecordingConfiguration config : recordConfigs) {
|
||||||
|
if (config.getClientUid() == crc.getUid()
|
||||||
|
&& !config.isClientSilenced()) {
|
||||||
|
crc.setRecordingActive(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wasActive != crc.isActive()) {
|
||||||
|
updateCommunicationRoute = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (updateCommunicationRoute) {
|
||||||
|
postUpdateCommunicationRouteClient("updateCommunicationRouteClientsActivity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
|
@Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
return mDeviceInventory.getDeviceSensorUuid(device);
|
return mDeviceInventory.getDeviceSensorUuid(device);
|
||||||
|
|||||||
@@ -4261,24 +4261,43 @@ public class AudioService extends IAudioService.Stub
|
|||||||
// When the audio mode owner becomes active, replace any delayed MSG_UPDATE_AUDIO_MODE
|
// When the audio mode owner becomes active, replace any delayed MSG_UPDATE_AUDIO_MODE
|
||||||
// and request an audio mode update immediately. Upon any other change, queue the message
|
// and request an audio mode update immediately. Upon any other change, queue the message
|
||||||
// and request an audio mode update after a grace period.
|
// and request an audio mode update after a grace period.
|
||||||
|
updateAudioModeHandlers(
|
||||||
|
configs /* playbackConfigs */, null /* recordConfigs */);
|
||||||
|
mDeviceBroker.updateCommunicationRouteClientsActivity(
|
||||||
|
configs /* playbackConfigs */, null /* recordConfigs */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateAudioModeHandlers(List<AudioPlaybackConfiguration> playbackConfigs,
|
||||||
|
List<AudioRecordingConfiguration> recordConfigs) {
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
boolean updateAudioMode = false;
|
boolean updateAudioMode = false;
|
||||||
int existingMsgPolicy = SENDMSG_QUEUE;
|
int existingMsgPolicy = SENDMSG_QUEUE;
|
||||||
int delay = CHECK_MODE_FOR_UID_PERIOD_MS;
|
int delay = CHECK_MODE_FOR_UID_PERIOD_MS;
|
||||||
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
||||||
boolean wasActive = h.isActive();
|
boolean wasActive = h.isActive();
|
||||||
|
if (playbackConfigs != null) {
|
||||||
h.setPlaybackActive(false);
|
h.setPlaybackActive(false);
|
||||||
for (AudioPlaybackConfiguration config : configs) {
|
for (AudioPlaybackConfiguration config : playbackConfigs) {
|
||||||
final int usage = config.getAudioAttributes().getUsage();
|
final int usage = config.getAudioAttributes().getUsage();
|
||||||
if (config.getClientUid() == h.getUid()
|
if (config.getClientUid() == h.getUid()
|
||||||
&& (usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
|
&& (usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
|
||||||
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING)
|
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING)
|
||||||
&& config.getPlayerState()
|
&& config.isActive()) {
|
||||||
== AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
|
|
||||||
h.setPlaybackActive(true);
|
h.setPlaybackActive(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (recordConfigs != null) {
|
||||||
|
h.setRecordingActive(false);
|
||||||
|
for (AudioRecordingConfiguration config : recordConfigs) {
|
||||||
|
if (config.getClientUid() == h.getUid() && !config.isClientSilenced()
|
||||||
|
&& config.getAudioSource() == AudioSource.VOICE_COMMUNICATION) {
|
||||||
|
h.setRecordingActive(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (wasActive != h.isActive()) {
|
if (wasActive != h.isActive()) {
|
||||||
updateAudioMode = true;
|
updateAudioMode = true;
|
||||||
if (h.isActive() && h == getAudioModeOwnerHandler()) {
|
if (h.isActive() && h == getAudioModeOwnerHandler()) {
|
||||||
@@ -4314,38 +4333,10 @@ public class AudioService extends IAudioService.Stub
|
|||||||
// When the audio mode owner becomes active, replace any delayed MSG_UPDATE_AUDIO_MODE
|
// When the audio mode owner becomes active, replace any delayed MSG_UPDATE_AUDIO_MODE
|
||||||
// and request an audio mode update immediately. Upon any other change, queue the message
|
// and request an audio mode update immediately. Upon any other change, queue the message
|
||||||
// and request an audio mode update after a grace period.
|
// and request an audio mode update after a grace period.
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
updateAudioModeHandlers(
|
||||||
boolean updateAudioMode = false;
|
null /* playbackConfigs */, configs /* recordConfigs */);
|
||||||
int existingMsgPolicy = SENDMSG_QUEUE;
|
mDeviceBroker.updateCommunicationRouteClientsActivity(
|
||||||
int delay = CHECK_MODE_FOR_UID_PERIOD_MS;
|
null /* playbackConfigs */, configs /* recordConfigs */);
|
||||||
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
|
||||||
boolean wasActive = h.isActive();
|
|
||||||
h.setRecordingActive(false);
|
|
||||||
for (AudioRecordingConfiguration config : configs) {
|
|
||||||
if (config.getClientUid() == h.getUid()
|
|
||||||
&& config.getAudioSource() == AudioSource.VOICE_COMMUNICATION) {
|
|
||||||
h.setRecordingActive(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wasActive != h.isActive()) {
|
|
||||||
updateAudioMode = true;
|
|
||||||
if (h.isActive() && h == getAudioModeOwnerHandler()) {
|
|
||||||
existingMsgPolicy = SENDMSG_REPLACE;
|
|
||||||
delay = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (updateAudioMode) {
|
|
||||||
sendMsg(mAudioHandler,
|
|
||||||
MSG_UPDATE_AUDIO_MODE,
|
|
||||||
existingMsgPolicy,
|
|
||||||
AudioSystem.MODE_CURRENT,
|
|
||||||
android.os.Process.myPid(),
|
|
||||||
mContext.getPackageName(),
|
|
||||||
delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpAudioMode(PrintWriter pw) {
|
private void dumpAudioMode(PrintWriter pw) {
|
||||||
@@ -6298,10 +6289,12 @@ public class AudioService extends IAudioService.Stub
|
|||||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||||
.record();
|
.record();
|
||||||
}
|
}
|
||||||
|
final boolean isPrivileged = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.MODIFY_PHONE_STATE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
return mDeviceBroker.setCommunicationDevice(cb, pid, device, eventSource);
|
return mDeviceBroker.setCommunicationDevice(cb, uid, device, isPrivileged, eventSource);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -6347,6 +6340,9 @@ public class AudioService extends IAudioService.Stub
|
|||||||
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
|
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final boolean isPrivileged = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.MODIFY_PHONE_STATE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
// for logging only
|
// for logging only
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
@@ -6362,9 +6358,10 @@ public class AudioService extends IAudioService.Stub
|
|||||||
.set(MediaMetrics.Property.STATE, on
|
.set(MediaMetrics.Property.STATE, on
|
||||||
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
||||||
.record();
|
.record();
|
||||||
|
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
|
mDeviceBroker.setSpeakerphoneOn(cb, uid, on, isPrivileged, eventSource);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -6489,7 +6486,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||||
BtHelper.scoAudioModeToString(scoAudioMode))
|
BtHelper.scoAudioModeToString(scoAudioMode))
|
||||||
.record();
|
.record();
|
||||||
startBluetoothScoInt(cb, pid, scoAudioMode, eventSource);
|
startBluetoothScoInt(cb, uid, scoAudioMode, eventSource);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6512,10 +6509,10 @@ public class AudioService extends IAudioService.Stub
|
|||||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||||
BtHelper.scoAudioModeToString(BtHelper.SCO_MODE_VIRTUAL_CALL))
|
BtHelper.scoAudioModeToString(BtHelper.SCO_MODE_VIRTUAL_CALL))
|
||||||
.record();
|
.record();
|
||||||
startBluetoothScoInt(cb, pid, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
|
startBluetoothScoInt(cb, uid, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startBluetoothScoInt(IBinder cb, int pid, int scoAudioMode, @NonNull String eventSource) {
|
void startBluetoothScoInt(IBinder cb, int uid, int scoAudioMode, @NonNull String eventSource) {
|
||||||
MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
||||||
.set(MediaMetrics.Property.EVENT, "startBluetoothScoInt")
|
.set(MediaMetrics.Property.EVENT, "startBluetoothScoInt")
|
||||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||||
@@ -6526,9 +6523,13 @@ public class AudioService extends IAudioService.Stub
|
|||||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "permission or systemReady").record();
|
mmi.set(MediaMetrics.Property.EARLY_RETURN, "permission or systemReady").record();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final boolean isPrivileged = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.MODIFY_PHONE_STATE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mDeviceBroker.startBluetoothScoForClient(cb, pid, scoAudioMode, eventSource);
|
mDeviceBroker.startBluetoothScoForClient(
|
||||||
|
cb, uid, scoAudioMode, isPrivileged, eventSource);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -6546,9 +6547,12 @@ public class AudioService extends IAudioService.Stub
|
|||||||
final String eventSource = new StringBuilder("stopBluetoothSco()")
|
final String eventSource = new StringBuilder("stopBluetoothSco()")
|
||||||
.append(") from u/pid:").append(uid).append("/")
|
.append(") from u/pid:").append(uid).append("/")
|
||||||
.append(pid).toString();
|
.append(pid).toString();
|
||||||
|
final boolean isPrivileged = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.MODIFY_PHONE_STATE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mDeviceBroker.stopBluetoothScoForClient(cb, pid, eventSource);
|
mDeviceBroker.stopBluetoothScoForClient(cb, uid, isPrivileged, eventSource);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -9283,8 +9287,8 @@ public class AudioService extends IAudioService.Stub
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
boolean wasActive = h.isActive();
|
boolean wasActive = h.isActive();
|
||||||
h.setPlaybackActive(mPlaybackMonitor.isPlaybackActiveForUid(h.getUid()));
|
h.setPlaybackActive(isPlaybackActiveForUid(h.getUid()));
|
||||||
h.setRecordingActive(mRecordMonitor.isRecordingActiveForUid(h.getUid()));
|
h.setRecordingActive(isRecordingActiveForUid(h.getUid()));
|
||||||
if (wasActive != h.isActive()) {
|
if (wasActive != h.isActive()) {
|
||||||
onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(),
|
onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(),
|
||||||
mContext.getPackageName(), false /*force*/);
|
mContext.getPackageName(), false /*force*/);
|
||||||
@@ -12377,6 +12381,16 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */
|
||||||
|
boolean isPlaybackActiveForUid(int uid) {
|
||||||
|
return mPlaybackMonitor.isPlaybackActiveForUid(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */
|
||||||
|
boolean isRecordingActiveForUid(int uid) {
|
||||||
|
return mRecordMonitor.isRecordingActiveForUid(uid);
|
||||||
|
}
|
||||||
|
|
||||||
//======================
|
//======================
|
||||||
// Audio device management
|
// Audio device management
|
||||||
//======================
|
//======================
|
||||||
|
|||||||
@@ -227,8 +227,8 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
|
|||||||
synchronized (mRecordStates) {
|
synchronized (mRecordStates) {
|
||||||
for (RecordingState state : mRecordStates) {
|
for (RecordingState state : mRecordStates) {
|
||||||
// Note: isActiveConfiguration() == true => state.getConfig() != null
|
// Note: isActiveConfiguration() == true => state.getConfig() != null
|
||||||
if (state.isActiveConfiguration()
|
if (state.isActiveConfiguration() && state.getConfig().getClientUid() == uid
|
||||||
&& state.getConfig().getClientUid() == uid) {
|
&& !state.getConfig().isClientSilenced()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user