Merge "AudioService: refactor audio mode stack" into sc-dev
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
/*
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 The Android Open Source Project
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -765,10 +765,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return mAudioService.getVssVolumeForDevice(streamType, device);
|
return mAudioService.getVssVolumeForDevice(streamType, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getModeOwnerPid() {
|
|
||||||
return mModeOwnerPid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ int getDeviceForStream(int streamType) {
|
/*package*/ int getDeviceForStream(int streamType) {
|
||||||
return mAudioService.getDeviceForStream(streamType);
|
return mAudioService.getDeviceForStream(streamType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ import android.media.IVolumeController;
|
|||||||
import android.media.MediaExtractor;
|
import android.media.MediaExtractor;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.media.MediaMetrics;
|
import android.media.MediaMetrics;
|
||||||
|
import android.media.MediaRecorder.AudioSource;
|
||||||
import android.media.PlayerBase;
|
import android.media.PlayerBase;
|
||||||
import android.media.VolumePolicy;
|
import android.media.VolumePolicy;
|
||||||
import android.media.audiofx.AudioEffect;
|
import android.media.audiofx.AudioEffect;
|
||||||
@@ -161,9 +162,11 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -301,6 +304,9 @@ public class AudioService extends IAudioService.Stub
|
|||||||
private static final int MSG_UPDATE_VOLUME_STATES_FOR_DEVICE = 33;
|
private static final int MSG_UPDATE_VOLUME_STATES_FOR_DEVICE = 33;
|
||||||
private static final int MSG_REINIT_VOLUMES = 34;
|
private static final int MSG_REINIT_VOLUMES = 34;
|
||||||
private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35;
|
private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35;
|
||||||
|
private static final int MSG_UPDATE_AUDIO_MODE = 36;
|
||||||
|
private static final int MSG_RECORDING_CONFIG_CHANGE = 37;
|
||||||
|
|
||||||
// start of messages handled under wakelock
|
// start of messages handled under wakelock
|
||||||
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
|
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
|
||||||
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
|
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
|
||||||
@@ -941,6 +947,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
mDeviceBroker = new AudioDeviceBroker(mContext, this);
|
mDeviceBroker = new AudioDeviceBroker(mContext, this);
|
||||||
|
|
||||||
mRecordMonitor = new RecordingActivityMonitor(mContext);
|
mRecordMonitor = new RecordingActivityMonitor(mContext);
|
||||||
|
mRecordMonitor.registerRecordingCallback(mVoiceRecordingActivityMonitor, true);
|
||||||
|
|
||||||
// must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
|
// must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
|
||||||
// array initialized by updateStreamVolumeAlias()
|
// array initialized by updateStreamVolumeAlias()
|
||||||
@@ -950,6 +957,8 @@ public class AudioService extends IAudioService.Stub
|
|||||||
|
|
||||||
mPlaybackMonitor =
|
mPlaybackMonitor =
|
||||||
new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
|
new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
|
||||||
|
mPlaybackMonitor.registerPlaybackCallback(mVoicePlaybackActivityMonitor, true);
|
||||||
|
|
||||||
mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
|
mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
|
||||||
|
|
||||||
readAndSetLowRamDevice();
|
readAndSetLowRamDevice();
|
||||||
@@ -1198,12 +1207,8 @@ public class AudioService extends IAudioService.Stub
|
|||||||
|
|
||||||
// Restore call state
|
// Restore call state
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
if (mAudioSystem.setPhoneState(mMode, getModeOwnerUid())
|
onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(),
|
||||||
== AudioSystem.AUDIO_STATUS_OK) {
|
mContext.getPackageName());
|
||||||
mModeLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode)
|
|
||||||
+ ", uid=" + getModeOwnerUid() + ")"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final int forSys;
|
final int forSys;
|
||||||
synchronized (mSettingsLock) {
|
synchronized (mSettingsLock) {
|
||||||
@@ -2991,7 +2996,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getHearingAidStreamType() {
|
/*package*/ int getHearingAidStreamType() {
|
||||||
return getHearingAidStreamType(mMode);
|
return getHearingAidStreamType(getMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getHearingAidStreamType(int mode) {
|
private int getHearingAidStreamType(int mode) {
|
||||||
@@ -3004,15 +3009,15 @@ public class AudioService extends IAudioService.Stub
|
|||||||
// other conditions will influence the stream type choice, read on...
|
// other conditions will influence the stream type choice, read on...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (mVoiceActive.get()) {
|
if (mVoicePlaybackActive.get()) {
|
||||||
return AudioSystem.STREAM_VOICE_CALL;
|
return AudioSystem.STREAM_VOICE_CALL;
|
||||||
}
|
}
|
||||||
return AudioSystem.STREAM_MUSIC;
|
return AudioSystem.STREAM_MUSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AtomicBoolean mVoiceActive = new AtomicBoolean(false);
|
private AtomicBoolean mVoicePlaybackActive = new AtomicBoolean(false);
|
||||||
|
|
||||||
private final IPlaybackConfigDispatcher mVoiceActivityMonitor =
|
private final IPlaybackConfigDispatcher mVoicePlaybackActivityMonitor =
|
||||||
new IPlaybackConfigDispatcher.Stub() {
|
new IPlaybackConfigDispatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
|
public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
|
||||||
@@ -3034,16 +3039,126 @@ public class AudioService extends IAudioService.Stub
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mVoiceActive.getAndSet(voiceActive) != voiceActive) {
|
if (mVoicePlaybackActive.getAndSet(voiceActive) != voiceActive) {
|
||||||
updateHearingAidVolumeOnVoiceActivityUpdate();
|
updateHearingAidVolumeOnVoiceActivityUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update playback active state for all apps in audio mode stack.
|
||||||
|
// 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 after a grace period.
|
||||||
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
|
boolean updateAudioMode = false;
|
||||||
|
int existingMsgPolicy = SENDMSG_QUEUE;
|
||||||
|
int delay = CHECK_MODE_FOR_UID_PERIOD_MS;
|
||||||
|
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
||||||
|
boolean wasActive = h.isActive();
|
||||||
|
h.setPlaybackActive(false);
|
||||||
|
for (AudioPlaybackConfiguration config : configs) {
|
||||||
|
final int usage = config.getAudioAttributes().getUsage();
|
||||||
|
if (config.getClientUid() == h.getUid()
|
||||||
|
&& (usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
|
||||||
|
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING)
|
||||||
|
&& config.getPlayerState()
|
||||||
|
== AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
|
||||||
|
h.setPlaybackActive(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 final IRecordingConfigDispatcher mVoiceRecordingActivityMonitor =
|
||||||
|
new IRecordingConfigDispatcher.Stub() {
|
||||||
|
@Override
|
||||||
|
public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) {
|
||||||
|
sendMsg(mAudioHandler, MSG_RECORDING_CONFIG_CHANGE, SENDMSG_REPLACE,
|
||||||
|
0 /*arg1 ignored*/, 0 /*arg2 ignored*/,
|
||||||
|
configs /*obj*/, 0 /*delay*/);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void onRecordingConfigChange(List<AudioRecordingConfiguration> configs) {
|
||||||
|
// Update recording active state for all apps in audio mode stack.
|
||||||
|
// 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 after a grace period.
|
||||||
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
|
boolean updateAudioMode = false;
|
||||||
|
int existingMsgPolicy = SENDMSG_QUEUE;
|
||||||
|
int delay = CHECK_MODE_FOR_UID_PERIOD_MS;
|
||||||
|
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) {
|
||||||
|
pw.println("\nAudio mode: ");
|
||||||
|
pw.println("- Current mode = " + AudioSystem.modeToString(getMode()));
|
||||||
|
pw.println("- Mode owner: ");
|
||||||
|
SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
|
||||||
|
if (hdlr != null) {
|
||||||
|
hdlr.dump(pw, -1);
|
||||||
|
} else {
|
||||||
|
pw.println(" None");
|
||||||
|
}
|
||||||
|
pw.println("- Mode owner stack: ");
|
||||||
|
if (mSetModeDeathHandlers.isEmpty()) {
|
||||||
|
pw.println(" Empty");
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < mSetModeDeathHandlers.size(); i++) {
|
||||||
|
mSetModeDeathHandlers.get(i).dump(pw, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateHearingAidVolumeOnVoiceActivityUpdate() {
|
private void updateHearingAidVolumeOnVoiceActivityUpdate() {
|
||||||
final int streamType = getHearingAidStreamType();
|
final int streamType = getHearingAidStreamType();
|
||||||
final int index = getStreamVolume(streamType);
|
final int index = getStreamVolume(streamType);
|
||||||
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_HEARING_AID,
|
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_HEARING_AID,
|
||||||
mVoiceActive.get(), streamType, index));
|
mVoicePlaybackActive.get(), streamType, index));
|
||||||
mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
|
mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4060,65 +4175,46 @@ public class AudioService extends IAudioService.Stub
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the pid of the current audio mode owner
|
|
||||||
* @return 0 if nobody owns the mode
|
|
||||||
*/
|
|
||||||
/*package*/ int getModeOwnerPid() {
|
|
||||||
int modeOwnerPid = 0;
|
|
||||||
try {
|
|
||||||
modeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// nothing to do, modeOwnerPid is not modified
|
|
||||||
}
|
|
||||||
return modeOwnerPid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the uid of the current audio mode owner
|
|
||||||
* @return 0 if nobody owns the mode
|
|
||||||
*/
|
|
||||||
/*package*/ int getModeOwnerUid() {
|
|
||||||
int modeOwnerUid = 0;
|
|
||||||
try {
|
|
||||||
modeOwnerUid = mSetModeDeathHandlers.get(0).getUid();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// nothing to do, modeOwnerUid is not modified
|
|
||||||
}
|
|
||||||
return modeOwnerUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SetModeDeathHandler implements IBinder.DeathRecipient {
|
private class SetModeDeathHandler implements IBinder.DeathRecipient {
|
||||||
private final IBinder mCb; // To be notified of client's death
|
private final IBinder mCb; // To be notified of client's death
|
||||||
private final int mPid;
|
private final int mPid;
|
||||||
private final int mUid;
|
private final int mUid;
|
||||||
private final boolean mIsPrivileged;
|
private final boolean mIsPrivileged;
|
||||||
private final String mPackage;
|
private final String mPackage;
|
||||||
private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
|
private int mMode;
|
||||||
|
private long mUpdateTime;
|
||||||
|
private boolean mPlaybackActive = false;
|
||||||
|
private boolean mRecordingActive = false;
|
||||||
|
|
||||||
SetModeDeathHandler(IBinder cb, int pid, int uid, boolean isPrivileged, String caller) {
|
SetModeDeathHandler(IBinder cb, int pid, int uid, boolean isPrivileged,
|
||||||
|
String caller, int mode) {
|
||||||
|
mMode = mode;
|
||||||
mCb = cb;
|
mCb = cb;
|
||||||
mPid = pid;
|
mPid = pid;
|
||||||
mUid = uid;
|
mUid = uid;
|
||||||
mIsPrivileged = isPrivileged;
|
|
||||||
mPackage = caller;
|
mPackage = caller;
|
||||||
|
mIsPrivileged = isPrivileged;
|
||||||
|
mUpdateTime = java.lang.System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
int newModeOwnerPid = 0;
|
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
Log.w(TAG, "setMode() client died");
|
Log.w(TAG, "SetModeDeathHandler client died");
|
||||||
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 SetModeDeathHandler client died");
|
||||||
} else {
|
} else {
|
||||||
newModeOwnerPid = setModeInt(
|
SetModeDeathHandler h = mSetModeDeathHandlers.get(index);
|
||||||
AudioSystem.MODE_NORMAL, mCb, mPid, mUid, mIsPrivileged, TAG);
|
mSetModeDeathHandlers.remove(index);
|
||||||
|
sendMsg(mAudioHandler,
|
||||||
|
MSG_UPDATE_AUDIO_MODE,
|
||||||
|
SENDMSG_QUEUE,
|
||||||
|
AudioSystem.MODE_CURRENT,
|
||||||
|
android.os.Process.myPid(),
|
||||||
|
mContext.getPackageName(),
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
|
||||||
// SCO connections not started by the application changing the mode when pid changes
|
|
||||||
mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid, AudioService.this.getMode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPid() {
|
public int getPid() {
|
||||||
@@ -4127,6 +4223,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
|
|
||||||
public void setMode(int mode) {
|
public void setMode(int mode) {
|
||||||
mMode = mode;
|
mMode = mode;
|
||||||
|
mUpdateTime = java.lang.System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMode() {
|
public int getMode() {
|
||||||
@@ -4148,25 +4245,131 @@ public class AudioService extends IAudioService.Stub
|
|||||||
public boolean isPrivileged() {
|
public boolean isPrivileged() {
|
||||||
return mIsPrivileged;
|
return mIsPrivileged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getUpdateTime() {
|
||||||
|
return mUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaybackActive(boolean active) {
|
||||||
|
mPlaybackActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordingActive(boolean active) {
|
||||||
|
mRecordingActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An app is considered active if:
|
||||||
|
* - It is privileged (has MODIFY_PHONE_STATE permission)
|
||||||
|
* or
|
||||||
|
* - It requests mode MODE_IN_COMMUNICATION, and it is either playing
|
||||||
|
* or recording for VOICE_COMMUNICATION.
|
||||||
|
* or
|
||||||
|
* - It requests a mode different from MODE_IN_COMMUNICATION or MODE_NORMAL
|
||||||
|
*/
|
||||||
|
public boolean isActive() {
|
||||||
|
return mIsPrivileged
|
||||||
|
|| ((mMode == AudioSystem.MODE_IN_COMMUNICATION)
|
||||||
|
&& (mRecordingActive || mPlaybackActive))
|
||||||
|
|| mMode == AudioSystem.MODE_IN_CALL
|
||||||
|
|| mMode == AudioSystem.MODE_RINGTONE
|
||||||
|
|| mMode == AudioSystem.MODE_CALL_SCREENING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump(PrintWriter pw, int index) {
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss:SSS");
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
pw.println(" Requester # " + (index + 1) + ":");
|
||||||
|
}
|
||||||
|
pw.println(" - Mode: " + AudioSystem.modeToString(mMode));
|
||||||
|
pw.println(" - Binder: " + mCb);
|
||||||
|
pw.println(" - Pid: " + mPid);
|
||||||
|
pw.println(" - Uid: " + mUid);
|
||||||
|
pw.println(" - Package: " + mPackage);
|
||||||
|
pw.println(" - Privileged: " + mIsPrivileged);
|
||||||
|
pw.println(" - Active: " + isActive());
|
||||||
|
pw.println(" Playback active: " + mPlaybackActive);
|
||||||
|
pw.println(" Recording active: " + mRecordingActive);
|
||||||
|
pw.println(" - update time: " + format.format(new Date(mUpdateTime)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mDeviceBroker.mSetModeLock")
|
||||||
|
private SetModeDeathHandler getAudioModeOwnerHandler() {
|
||||||
|
// The Audio mode owner is:
|
||||||
|
// 1) the most recent privileged app in the stack
|
||||||
|
// 2) the most recent active app in the tack
|
||||||
|
SetModeDeathHandler modeOwner = null;
|
||||||
|
SetModeDeathHandler privilegedModeOwner = null;
|
||||||
|
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
||||||
|
if (h.isActive()) {
|
||||||
|
// privileged apps are always active
|
||||||
|
if (h.isPrivileged()) {
|
||||||
|
if (privilegedModeOwner == null
|
||||||
|
|| h.getUpdateTime() > privilegedModeOwner.getUpdateTime()) {
|
||||||
|
privilegedModeOwner = h;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (modeOwner == null
|
||||||
|
|| h.getUpdateTime() > modeOwner.getUpdateTime()) {
|
||||||
|
modeOwner = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return privilegedModeOwner != null ? privilegedModeOwner : modeOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pid of the current audio mode owner
|
||||||
|
* @return 0 if nobody owns the mode
|
||||||
|
*/
|
||||||
|
@GuardedBy("mDeviceBroker.mSetModeLock")
|
||||||
|
/*package*/ int getModeOwnerPid() {
|
||||||
|
SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
|
||||||
|
if (hdlr != null) {
|
||||||
|
return hdlr.getPid();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the uid of the current audio mode owner
|
||||||
|
* @return 0 if nobody owns the mode
|
||||||
|
*/
|
||||||
|
@GuardedBy("mDeviceBroker.mSetModeLock")
|
||||||
|
/*package*/ int getModeOwnerUid() {
|
||||||
|
SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
|
||||||
|
if (hdlr != null) {
|
||||||
|
return hdlr.getUid();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see AudioManager#setMode(int) */
|
/** @see AudioManager#setMode(int) */
|
||||||
public void setMode(int mode, IBinder cb, String callingPackage) {
|
public void setMode(int mode, IBinder cb, String callingPackage) {
|
||||||
|
int pid = Binder.getCallingPid();
|
||||||
|
int uid = Binder.getCallingUid();
|
||||||
if (DEBUG_MODE) {
|
if (DEBUG_MODE) {
|
||||||
Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")");
|
Log.v(TAG, "setMode(mode=" + mode + ", pid=" + pid
|
||||||
|
+ ", uid=" + uid + ", caller=" + callingPackage + ")");
|
||||||
}
|
}
|
||||||
if (!checkAudioSettingsPermission("setMode()")) {
|
if (!checkAudioSettingsPermission("setMode()")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean hasModifyPhoneStatePermission = mContext.checkCallingOrSelfPermission(
|
if (cb == null) {
|
||||||
android.Manifest.permission.MODIFY_PHONE_STATE)
|
Log.e(TAG, "setMode() called with null binder");
|
||||||
== PackageManager.PERMISSION_GRANTED;
|
|
||||||
final int callingPid = Binder.getCallingPid();
|
|
||||||
if ((mode == AudioSystem.MODE_IN_CALL) && !hasModifyPhoneStatePermission) {
|
|
||||||
Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
|
|
||||||
+ callingPid + ", uid=" + Binder.getCallingUid());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
|
||||||
|
Log.w(TAG, "setMode() invalid mode: " + mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == AudioSystem.MODE_CURRENT) {
|
||||||
|
mode = getMode();
|
||||||
|
}
|
||||||
|
|
||||||
if (mode == AudioSystem.MODE_CALL_SCREENING && !mIsCallScreeningModeSupported) {
|
if (mode == AudioSystem.MODE_CALL_SCREENING && !mIsCallScreeningModeSupported) {
|
||||||
Log.w(TAG, "setMode(MODE_CALL_SCREENING) not permitted "
|
Log.w(TAG, "setMode(MODE_CALL_SCREENING) not permitted "
|
||||||
@@ -4174,171 +4377,152 @@ public class AudioService extends IAudioService.Stub
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
|
final boolean hasModifyPhoneStatePermission = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.MODIFY_PHONE_STATE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
|
if ((mode == AudioSystem.MODE_IN_CALL) && !hasModifyPhoneStatePermission) {
|
||||||
|
Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
|
||||||
|
+ pid + ", uid=" + Binder.getCallingUid());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newModeOwnerPid;
|
SetModeDeathHandler currentModeHandler = null;
|
||||||
synchronized (mDeviceBroker.mSetModeLock) {
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
if (mode == AudioSystem.MODE_CURRENT) {
|
for (SetModeDeathHandler h : mSetModeDeathHandlers) {
|
||||||
mode = mMode;
|
if (h.getPid() == pid) {
|
||||||
|
currentModeHandler = h;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int oldModeOwnerPid = getModeOwnerPid();
|
|
||||||
// Do not allow changing mode if a call is active and the requester
|
if (mode == AudioSystem.MODE_NORMAL) {
|
||||||
// does not have permission to modify phone state or is not the mode owner,
|
if (currentModeHandler != null) {
|
||||||
// unless returning to NORMAL mode (will not change current mode owner) or
|
if (!currentModeHandler.isPrivileged()
|
||||||
// not changing mode in which case the mode owner will reflect the last
|
&& currentModeHandler.getMode() == AudioSystem.MODE_IN_COMMUNICATION) {
|
||||||
// requester of current mode
|
mAudioHandler.removeEqualMessages(
|
||||||
if (!((mode == mMode) || (mode == AudioSystem.MODE_NORMAL))
|
MSG_CHECK_MODE_FOR_UID, currentModeHandler);
|
||||||
&& ((mMode == AudioSystem.MODE_IN_CALL)
|
}
|
||||||
|| (mMode == AudioSystem.MODE_IN_COMMUNICATION))
|
mSetModeDeathHandlers.remove(currentModeHandler);
|
||||||
&& !(hasModifyPhoneStatePermission || (oldModeOwnerPid == callingPid))) {
|
if (DEBUG_MODE) {
|
||||||
Log.w(TAG, "setMode(" + mode + ") from pid=" + callingPid
|
Log.v(TAG, "setMode(" + mode + ") removing hldr for pid: " + pid);
|
||||||
+ ", uid=" + Binder.getCallingUid()
|
}
|
||||||
+ ", cannot change mode from " + mMode
|
try {
|
||||||
+ " without permission or being mode owner");
|
currentModeHandler.getBinder().unlinkToDeath(currentModeHandler, 0);
|
||||||
return;
|
} catch (NoSuchElementException e) {
|
||||||
|
Log.w(TAG, "setMode link does not exist ...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentModeHandler != null) {
|
||||||
|
currentModeHandler.setMode(mode);
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
Log.v(TAG, "setMode(" + mode + ") updating hldr for pid: " + pid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentModeHandler = new SetModeDeathHandler(cb, pid, uid,
|
||||||
|
hasModifyPhoneStatePermission, callingPackage, mode);
|
||||||
|
// Register for client death notification
|
||||||
|
try {
|
||||||
|
cb.linkToDeath(currentModeHandler, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Client has died!
|
||||||
|
Log.w(TAG, "setMode() could not link to " + cb + " binder death");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mSetModeDeathHandlers.add(currentModeHandler);
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
Log.v(TAG, "setMode(" + mode + ") adding handler for pid=" + pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mode == AudioSystem.MODE_IN_COMMUNICATION) {
|
||||||
|
// Force active state when entering/updating the stack to avoid glitches when
|
||||||
|
// an app starts playing/recording after settng the audio mode,
|
||||||
|
// and send a reminder to check activity after a grace period.
|
||||||
|
if (!currentModeHandler.isPrivileged()) {
|
||||||
|
currentModeHandler.setPlaybackActive(true);
|
||||||
|
currentModeHandler.setRecordingActive(true);
|
||||||
|
sendMsg(mAudioHandler,
|
||||||
|
MSG_CHECK_MODE_FOR_UID,
|
||||||
|
SENDMSG_QUEUE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
currentModeHandler,
|
||||||
|
CHECK_MODE_FOR_UID_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newModeOwnerPid = setModeInt(mode, cb, callingPid, Binder.getCallingUid(),
|
|
||||||
hasModifyPhoneStatePermission, callingPackage);
|
sendMsg(mAudioHandler,
|
||||||
|
MSG_UPDATE_AUDIO_MODE,
|
||||||
|
SENDMSG_REPLACE,
|
||||||
|
mode,
|
||||||
|
pid,
|
||||||
|
callingPackage,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
|
|
||||||
// SCO connections not started by the application changing the mode when pid changes
|
|
||||||
mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid, getMode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setModeInt() returns a valid PID if the audio mode was successfully set to
|
|
||||||
// any mode other than NORMAL.
|
|
||||||
@GuardedBy("mDeviceBroker.mSetModeLock")
|
@GuardedBy("mDeviceBroker.mSetModeLock")
|
||||||
private int setModeInt(
|
void onUpdateAudioMode(int requestedMode, int requesterPid, String requesterPackage) {
|
||||||
int mode, IBinder cb, int pid, int uid, boolean isPrivileged, String caller) {
|
if (requestedMode == AudioSystem.MODE_CURRENT) {
|
||||||
|
requestedMode = getMode();
|
||||||
|
}
|
||||||
|
int mode = AudioSystem.MODE_NORMAL;
|
||||||
|
int uid = 0;
|
||||||
|
int pid = 0;
|
||||||
|
SetModeDeathHandler currentModeHandler = getAudioModeOwnerHandler();
|
||||||
|
if (currentModeHandler != null) {
|
||||||
|
mode = currentModeHandler.getMode();
|
||||||
|
uid = currentModeHandler.getUid();
|
||||||
|
pid = currentModeHandler.getPid();
|
||||||
|
}
|
||||||
if (DEBUG_MODE) {
|
if (DEBUG_MODE) {
|
||||||
Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid
|
Log.v(TAG, "onUpdateAudioMode() mode: " + mode + ", mMode: " + mMode
|
||||||
+ ", uid=" + uid + ", caller=" + caller + ")");
|
+ " requestedMode: " + requestedMode);
|
||||||
}
|
|
||||||
int newModeOwnerPid = 0;
|
|
||||||
if (cb == null) {
|
|
||||||
Log.e(TAG, "setModeInt() called with null binder");
|
|
||||||
return newModeOwnerPid;
|
|
||||||
}
|
}
|
||||||
|
if (mode != mMode) {
|
||||||
|
final long identity = Binder.clearCallingIdentity();
|
||||||
|
int status = mAudioSystem.setPhoneState(mode, uid);
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
if (status == AudioSystem.AUDIO_STATUS_OK) {
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
Log.v(TAG, "onUpdateAudioMode: mode successfully set to " + mode);
|
||||||
|
}
|
||||||
|
int previousMode = mMode;
|
||||||
|
mMode = mode;
|
||||||
|
// Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
|
||||||
|
mModeLogger.log(new PhoneStateEvent(requesterPackage, requesterPid,
|
||||||
|
requestedMode, pid, mode));
|
||||||
|
|
||||||
SetModeDeathHandler hdlr = null;
|
int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||||||
Iterator iter = mSetModeDeathHandlers.iterator();
|
int device = getDeviceForStream(streamType);
|
||||||
while (iter.hasNext()) {
|
int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
|
||||||
SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
|
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true,
|
||||||
if (h.getPid() == pid) {
|
requesterPackage, true /*hasModifyAudioSettings*/);
|
||||||
hdlr = h;
|
|
||||||
// Remove from client list so that it is re-inserted at top of list
|
updateStreamVolumeAlias(true /*updateVolumes*/, requesterPackage);
|
||||||
iter.remove();
|
|
||||||
if (hdlr.getMode() == AudioSystem.MODE_IN_COMMUNICATION) {
|
// change of mode may require volume to be re-applied on some devices
|
||||||
mAudioHandler.removeEqualMessages(MSG_CHECK_MODE_FOR_UID, hdlr);
|
updateAbsVolumeMultiModeDevices(previousMode, mode);
|
||||||
}
|
|
||||||
try {
|
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
|
||||||
hdlr.getBinder().unlinkToDeath(hdlr, 0);
|
// connections not started by the application changing the mode when pid changes
|
||||||
if (cb != hdlr.getBinder()){
|
mDeviceBroker.postSetModeOwnerPid(pid, mode);
|
||||||
hdlr = null;
|
|
||||||
}
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
hdlr = null;
|
|
||||||
Log.w(TAG, "link does not exist ...");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final int oldMode = mMode;
|
|
||||||
int status = AudioSystem.AUDIO_STATUS_OK;
|
|
||||||
int actualMode;
|
|
||||||
do {
|
|
||||||
actualMode = mode;
|
|
||||||
if (mode == AudioSystem.MODE_NORMAL) {
|
|
||||||
// get new mode from client at top the list if any
|
|
||||||
if (!mSetModeDeathHandlers.isEmpty()) {
|
|
||||||
hdlr = mSetModeDeathHandlers.get(0);
|
|
||||||
cb = hdlr.getBinder();
|
|
||||||
actualMode = hdlr.getMode();
|
|
||||||
if (DEBUG_MODE) {
|
|
||||||
Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
|
|
||||||
+ hdlr.mPid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (hdlr == null) {
|
Log.w(TAG, "onUpdateAudioMode: failed to set audio mode to: " + mode);
|
||||||
hdlr = new SetModeDeathHandler(cb, pid, uid, isPrivileged, caller);
|
|
||||||
}
|
|
||||||
// Register for client death notification
|
|
||||||
try {
|
|
||||||
cb.linkToDeath(hdlr, 0);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
// Client has died!
|
|
||||||
Log.w(TAG, "setMode() could not link to "+cb+" binder death");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last client to call setMode() is always at top of client list
|
|
||||||
// as required by SetModeDeathHandler.binderDied()
|
|
||||||
mSetModeDeathHandlers.add(0, hdlr);
|
|
||||||
hdlr.setMode(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actualMode != mMode) {
|
|
||||||
final long identity = Binder.clearCallingIdentity();
|
|
||||||
status = mAudioSystem.setPhoneState(actualMode, getModeOwnerUid());
|
|
||||||
Binder.restoreCallingIdentity(identity);
|
|
||||||
if (status == AudioSystem.AUDIO_STATUS_OK) {
|
|
||||||
if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
|
|
||||||
mMode = actualMode;
|
|
||||||
} else {
|
|
||||||
if (hdlr != null) {
|
|
||||||
mSetModeDeathHandlers.remove(hdlr);
|
|
||||||
cb.unlinkToDeath(hdlr, 0);
|
|
||||||
}
|
|
||||||
// force reading new top of mSetModeDeathHandlers stack
|
|
||||||
if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
|
|
||||||
mode = AudioSystem.MODE_NORMAL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = AudioSystem.AUDIO_STATUS_OK;
|
|
||||||
}
|
|
||||||
} while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
|
|
||||||
|
|
||||||
if (status == AudioSystem.AUDIO_STATUS_OK) {
|
|
||||||
if (actualMode != AudioSystem.MODE_NORMAL) {
|
|
||||||
newModeOwnerPid = getModeOwnerPid();
|
|
||||||
if (newModeOwnerPid == 0) {
|
|
||||||
Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
|
|
||||||
mModeLogger.log(
|
|
||||||
new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
|
|
||||||
|
|
||||||
int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
|
|
||||||
int device = getDeviceForStream(streamType);
|
|
||||||
int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
|
|
||||||
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller,
|
|
||||||
true /*hasModifyAudioSettings*/);
|
|
||||||
|
|
||||||
updateStreamVolumeAlias(true /*updateVolumes*/, caller);
|
|
||||||
|
|
||||||
// change of mode may require volume to be re-applied on some devices
|
|
||||||
updateAbsVolumeMultiModeDevices(oldMode, actualMode);
|
|
||||||
|
|
||||||
if (actualMode == AudioSystem.MODE_IN_COMMUNICATION
|
|
||||||
&& !hdlr.isPrivileged()) {
|
|
||||||
sendMsg(mAudioHandler,
|
|
||||||
MSG_CHECK_MODE_FOR_UID,
|
|
||||||
SENDMSG_QUEUE,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
hdlr,
|
|
||||||
CHECK_MODE_FOR_UID_PERIOD_MS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newModeOwnerPid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see AudioManager#getMode() */
|
/** @see AudioManager#getMode() */
|
||||||
public int getMode() {
|
public int getMode() {
|
||||||
return mMode;
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
|
SetModeDeathHandler currentModeHandler = getAudioModeOwnerHandler();
|
||||||
|
if (currentModeHandler != null) {
|
||||||
|
return currentModeHandler.getMode();
|
||||||
|
}
|
||||||
|
return AudioSystem.MODE_NORMAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** cached value read from audiopolicy manager after initialization. */
|
/** cached value read from audiopolicy manager after initialization. */
|
||||||
@@ -5685,11 +5869,6 @@ public class AudioService extends IAudioService.Stub
|
|||||||
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
|
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
|
||||||
+ " (dis)connection, got " + state);
|
+ " (dis)connection, got " + state);
|
||||||
}
|
}
|
||||||
if (state == BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
|
|
||||||
} else {
|
|
||||||
mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
|
|
||||||
}
|
|
||||||
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
|
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
|
||||||
device, state, suppressNoisyIntent, musicDevice, "AudioService");
|
device, state, suppressNoisyIntent, musicDevice, "AudioService");
|
||||||
}
|
}
|
||||||
@@ -7034,6 +7213,9 @@ public class AudioService extends IAudioService.Stub
|
|||||||
case MSG_PLAYBACK_CONFIG_CHANGE:
|
case MSG_PLAYBACK_CONFIG_CHANGE:
|
||||||
onPlaybackConfigChange((List<AudioPlaybackConfiguration>) msg.obj);
|
onPlaybackConfigChange((List<AudioPlaybackConfiguration>) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
case MSG_RECORDING_CONFIG_CHANGE:
|
||||||
|
onRecordingConfigChange((List<AudioRecordingConfiguration>) msg.obj);
|
||||||
|
break;
|
||||||
|
|
||||||
case MSG_BROADCAST_MICROPHONE_MUTE:
|
case MSG_BROADCAST_MICROPHONE_MUTE:
|
||||||
mSystemServer.sendMicrophoneMuteChangedIntent();
|
mSystemServer.sendMicrophoneMuteChangedIntent();
|
||||||
@@ -7044,30 +7226,19 @@ public class AudioService extends IAudioService.Stub
|
|||||||
if (msg.obj == null) {
|
if (msg.obj == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If no other app is currently owning the audio mode and
|
// Update active playback/recording for apps requesting IN_COMMUNICATION
|
||||||
// the app corresponding to this mode death handler object is still in the
|
// mode after a grace period following the mode change
|
||||||
// mode owner stack but not capturing or playing audio after 3 seconds,
|
|
||||||
// remove it from the stack.
|
|
||||||
// Otherwise, check again in 3 seconds.
|
|
||||||
SetModeDeathHandler h = (SetModeDeathHandler) msg.obj;
|
SetModeDeathHandler h = (SetModeDeathHandler) msg.obj;
|
||||||
if (mSetModeDeathHandlers.indexOf(h) < 0) {
|
if (mSetModeDeathHandlers.indexOf(h) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (getModeOwnerUid() != h.getUid()
|
boolean wasActive = h.isActive();
|
||||||
|| mRecordMonitor.isRecordingActiveForUid(h.getUid())
|
h.setPlaybackActive(mPlaybackMonitor.isPlaybackActiveForUid(h.getUid()));
|
||||||
|| mPlaybackMonitor.isPlaybackActiveForUid(h.getUid())) {
|
h.setRecordingActive(mRecordMonitor.isRecordingActiveForUid(h.getUid()));
|
||||||
sendMsg(mAudioHandler,
|
if (wasActive != h.isActive()) {
|
||||||
MSG_CHECK_MODE_FOR_UID,
|
onUpdateAudioMode(AudioSystem.MODE_CURRENT,
|
||||||
SENDMSG_QUEUE,
|
android.os.Process.myPid(), mContext.getPackageName());
|
||||||
0,
|
|
||||||
0,
|
|
||||||
h,
|
|
||||||
CHECK_MODE_FOR_UID_PERIOD_MS);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
setModeInt(AudioSystem.MODE_NORMAL, h.getBinder(), h.getPid(), h.getUid(),
|
|
||||||
h.isPrivileged(), "MSG_CHECK_MODE_FOR_UID");
|
|
||||||
mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid()));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -7084,10 +7255,16 @@ public class AudioService extends IAudioService.Stub
|
|||||||
case MSG_REINIT_VOLUMES:
|
case MSG_REINIT_VOLUMES:
|
||||||
onReinitVolumes((String) msg.obj);
|
onReinitVolumes((String) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_UPDATE_A11Y_SERVICE_UIDS:
|
case MSG_UPDATE_A11Y_SERVICE_UIDS:
|
||||||
onUpdateAccessibilityServiceUids();
|
onUpdateAccessibilityServiceUids();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSG_UPDATE_AUDIO_MODE:
|
||||||
|
synchronized (mDeviceBroker.mSetModeLock) {
|
||||||
|
onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8118,6 +8295,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
dumpStreamStates(pw);
|
dumpStreamStates(pw);
|
||||||
dumpVolumeGroups(pw);
|
dumpVolumeGroups(pw);
|
||||||
dumpRingerMode(pw);
|
dumpRingerMode(pw);
|
||||||
|
dumpAudioMode(pw);
|
||||||
pw.println("\nAudio routes:");
|
pw.println("\nAudio routes:");
|
||||||
pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
|
pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
|
||||||
mDeviceBroker.getCurAudioRoutes().mainType));
|
mDeviceBroker.getCurAudioRoutes().mainType));
|
||||||
|
|||||||
Reference in New Issue
Block a user