Merge "Handle the mute events"

This commit is contained in:
Vlad Popa
2022-07-29 14:07:40 +00:00
committed by Android (Google) Code Review
4 changed files with 167 additions and 10 deletions

View File

@@ -172,6 +172,11 @@ public final class AudioPlaybackConfiguration implements Parcelable {
* The state used to update port id, does not actually change the state of the player
*/
public static final int PLAYER_UPDATE_PORT_ID = 6;
/**
* @hide
* Used to update the mute state of a player through its port id
*/
public static final int PLAYER_UPDATE_MUTED = 7;
/** @hide */
@IntDef({
@@ -183,6 +188,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
PLAYER_STATE_STOPPED,
PLAYER_UPDATE_DEVICE_ID,
PLAYER_UPDATE_PORT_ID,
PLAYER_UPDATE_MUTED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PlayerState {}
@@ -198,11 +204,50 @@ public final class AudioPlaybackConfiguration implements Parcelable {
case PLAYER_STATE_STOPPED: return "PLAYER_STATE_STOPPED";
case PLAYER_UPDATE_DEVICE_ID: return "PLAYER_UPDATE_DEVICE_ID";
case PLAYER_UPDATE_PORT_ID: return "PLAYER_UPDATE_PORT_ID";
case PLAYER_UPDATE_MUTED: return "PLAYER_UPDATE_MUTED";
default:
return "invalid state " + state;
}
}
/**
* @hide
* Used to update the mute state of a player through its port ID. Must be kept in sync with
* frameworks/native/include/audiomanager/AudioManager.h
*/
public static final String EXTRA_PLAYER_EVENT_MUTE =
"android.media.extra.PLAYER_EVENT_MUTE";
/**
* @hide
* Flag used when muted by master volume.
*/
public static final int PLAYER_MUTE_MASTER = (1 << 0);
/**
* @hide
* Flag used when muted by stream volume.
*/
public static final int PLAYER_MUTE_STREAM_VOLUME = (1 << 1);
/**
* @hide
* Flag used when muted by stream mute.
*/
public static final int PLAYER_MUTE_STREAM_MUTED = (1 << 2);
/**
* @hide
* Flag used when playback is restricted by AppOps manager with OP_PLAY_AUDIO.
*/
public static final int PLAYER_MUTE_PLAYBACK_RESTRICTED = (1 << 3);
/** @hide */
@IntDef(
flag = true,
value = {PLAYER_MUTE_MASTER, PLAYER_MUTE_STREAM_VOLUME, PLAYER_MUTE_STREAM_MUTED,
PLAYER_MUTE_PLAYBACK_RESTRICTED})
@Retention(RetentionPolicy.SOURCE)
public @interface PlayerMuteEvent {
}
// immutable data
private final int mPlayerIId;
@@ -678,6 +723,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
case PLAYER_STATE_STOPPED: return "stopped";
case PLAYER_UPDATE_DEVICE_ID: return "device updated";
case PLAYER_UPDATE_PORT_ID: return "port updated";
case PLAYER_UPDATE_MUTED: return "muted updated";
default:
return "unknown player state - FIXME";
}

View File

@@ -54,6 +54,7 @@ import android.media.audiopolicy.AudioVolumeGroup;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.media.projection.IMediaProjection;
import android.net.Uri;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.view.KeyEvent;
@@ -86,6 +87,8 @@ interface IAudioService {
oneway void playerSessionId(in int piid, in int sessionId);
oneway void portEvent(in int portId, in int event, in @nullable PersistableBundle extras);
// Java-only methods below.
void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage);

View File

@@ -134,6 +134,7 @@ import android.os.HwBinder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -11141,6 +11142,16 @@ public class AudioService extends IAudioService.Stub
mPlaybackMonitor.playerEvent(piid, event, eventValue, Binder.getCallingUid());
}
/**
* Update event for port id
* @param portId Port id to update
* @param event The new event for the given port
* @param extras Bundle of extra values to describe the event
*/
public void portEvent(int portId, int event, @Nullable PersistableBundle extras) {
mPlaybackMonitor.portEvent(portId, event, extras, Binder.getCallingUid());
}
public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
}

View File

@@ -16,6 +16,14 @@
package com.android.server.audio;
import static android.media.AudioPlaybackConfiguration.EXTRA_PLAYER_EVENT_MUTE;
import static android.media.AudioPlaybackConfiguration.PLAYER_MUTE_MASTER;
import static android.media.AudioPlaybackConfiguration.PLAYER_MUTE_PLAYBACK_RESTRICTED;
import static android.media.AudioPlaybackConfiguration.PLAYER_MUTE_STREAM_MUTED;
import static android.media.AudioPlaybackConfiguration.PLAYER_MUTE_STREAM_VOLUME;
import static android.media.AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
import static android.media.AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -24,6 +32,7 @@ import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioPlaybackConfiguration.PlayerMuteEvent;
import android.media.AudioSystem;
import android.media.IPlaybackConfigDispatcher;
import android.media.PlayerBase;
@@ -33,7 +42,9 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;
@@ -349,6 +360,56 @@ public final class PlaybackActivityMonitor
}
}
/**
* Update event for port
* @param portId Port id to update
* @param event The new port event
* @param extras The values associated with this event
* @param binderUid Calling binder uid
*/
public void portEvent(int portId, int event, @Nullable PersistableBundle extras,
int binderUid) {
if (!UserHandle.isCore(binderUid)) {
Log.e(TAG, "Forbidden operation from uid " + binderUid);
return;
}
if (DEBUG) {
Log.v(TAG, TextUtils.formatSimple("portEvent(portId=%d, event=%s, extras=%s)",
portId, AudioPlaybackConfiguration.playerStateToString(event), extras));
}
synchronized (mPlayerLock) {
int piid = mPortIdToPiid.get(portId, PLAYER_PIID_INVALID);
if (piid == PLAYER_PIID_INVALID) {
if (DEBUG) {
Log.v(TAG, "No piid assigned for invalid/internal port id " + portId);
}
return;
}
final AudioPlaybackConfiguration apc = mPlayers.get(piid);
if (apc == null) {
if (DEBUG) {
Log.v(TAG, "No AudioPlaybackConfiguration assigned for piid " + piid);
}
return;
}
if (apc.getPlayerType()
== AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
// FIXME SoundPool not ready for state reporting
return;
}
if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED) {
mEventHandler.sendMessage(
mEventHandler.obtainMessage(MSG_L_UPDATE_PLAYER_MUTED_EVENT, piid,
portId,
extras));
}
}
}
public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio, int binderUid) {
// no check on UID yet because this is only for logging at the moment
sEventLogger.log(new PlayerOpPlayAudioEvent(piid, hasOpPlayAudio, binderUid));
@@ -1062,18 +1123,32 @@ public final class PlaybackActivityMonitor
@Override
public String eventToString() {
if (mEvent == AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID) {
return AudioPlaybackConfiguration.toLogFriendlyPlayerState(mEvent) + " portId:"
+ mEventValue + " mapped to player piid:" + mPlayerIId;
}
StringBuilder builder = new StringBuilder("player piid:").append(mPlayerIId).append(
" state:")
" event:")
.append(AudioPlaybackConfiguration.toLogFriendlyPlayerState(mEvent));
if (mEventValue != 0) {
builder.append(" DeviceId:").append(mEventValue);
switch (mEvent) {
case AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID:
return AudioPlaybackConfiguration.toLogFriendlyPlayerState(mEvent) + " portId:"
+ mEventValue + " mapped to player piid:" + mPlayerIId;
case AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID:
if (mEventValue != 0) {
builder.append(" deviceId:").append(mEventValue);
}
return builder.toString();
case AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED:
builder.append(" muteFromMasterMute:").append(
(mEventValue & PLAYER_MUTE_MASTER) != 0);
builder.append(" muteFromStreamVolume:").append(
(mEventValue & PLAYER_MUTE_STREAM_VOLUME) != 0);
builder.append(" muteFromStreamMute:").append(
(mEventValue & PLAYER_MUTE_STREAM_MUTED) != 0);
builder.append(" muteFromPlaybackRestricted:").append(
(mEventValue & PLAYER_MUTE_PLAYBACK_RESTRICTED) != 0);
return builder.toString();
default:
return builder.toString();
}
return builder.toString();
}
}
@@ -1322,12 +1397,22 @@ public final class PlaybackActivityMonitor
*/
private static final int MSG_L_UPDATE_PORT_EVENT = 2;
/**
* event for player getting muted
* args:
* msg.arg1: piid
* msg.arg2: port id
* msg.obj: extras describing the mute reason
* type: PersistableBundle
*/
private static final int MSG_L_UPDATE_PLAYER_MUTED_EVENT = 3;
/**
* clear all ports assigned to a given piid
* args:
* msg.arg1: the piid
*/
private static final int MSG_L_CLEAR_PORTS_FOR_PIID = 3;
private static final int MSG_L_CLEAR_PORTS_FOR_PIID = 4;
private void initEventHandler() {
mEventThread = new HandlerThread(TAG);
@@ -1349,6 +1434,18 @@ public final class PlaybackActivityMonitor
mPortIdToPiid.put(/*portId*/msg.arg1, /*piid*/msg.arg2);
}
break;
case MSG_L_UPDATE_PLAYER_MUTED_EVENT:
// TODO: replace PersistableBundle with own struct
PersistableBundle extras = (PersistableBundle) msg.obj;
if (extras == null) {
Log.w(TAG, "Received mute event with no extras");
break;
}
@PlayerMuteEvent int eventValue = extras.getInt(EXTRA_PLAYER_EVENT_MUTE);
sEventLogger.log(new PlayerEvent(/*piid=*/msg.arg1, PLAYER_UPDATE_MUTED,
eventValue));
break;
case MSG_L_CLEAR_PORTS_FOR_PIID:
int piid = msg.arg1;
if (piid == AudioPlaybackConfiguration.PLAYER_PIID_INVALID) {