Merge changes Ibca1d27b,I8cc6f5ce into rvc-dev
* changes: MediaMetrics: Update Audio Java logging MediaMetrics instrumentation
This commit is contained in:
@@ -2712,6 +2712,32 @@ public class AudioManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static String audioFocusToString(int focus) {
|
||||
switch (focus) {
|
||||
case AUDIOFOCUS_NONE:
|
||||
return "AUDIOFOCUS_NONE";
|
||||
case AUDIOFOCUS_GAIN:
|
||||
return "AUDIOFOCUS_GAIN";
|
||||
case AUDIOFOCUS_GAIN_TRANSIENT:
|
||||
return "AUDIOFOCUS_GAIN_TRANSIENT";
|
||||
case AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
|
||||
return "AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK";
|
||||
case AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
|
||||
return "AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE";
|
||||
case AUDIOFOCUS_LOSS:
|
||||
return "AUDIOFOCUS_LOSS";
|
||||
case AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
return "AUDIOFOCUS_LOSS_TRANSIENT";
|
||||
case AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // Note CAN_DUCK not MAY_DUCK.
|
||||
return "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK";
|
||||
default:
|
||||
return "AUDIO_FOCUS_UNKNOWN(" + focus + ")";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to indicate no audio focus has been gained or lost, or requested.
|
||||
*/
|
||||
|
||||
@@ -214,6 +214,175 @@ public class AudioSystem
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Convert a native audio format integer constant to a string.
|
||||
*/
|
||||
public static String audioFormatToString(int audioFormat) {
|
||||
switch (audioFormat) {
|
||||
case /* AUDIO_FORMAT_INVALID */ 0xFFFFFFFF:
|
||||
return "AUDIO_FORMAT_INVALID";
|
||||
case /* AUDIO_FORMAT_DEFAULT */ 0:
|
||||
return "AUDIO_FORMAT_DEFAULT";
|
||||
case /* AUDIO_FORMAT_MP3 */ 0x01000000:
|
||||
return "AUDIO_FORMAT_MP3";
|
||||
case /* AUDIO_FORMAT_AMR_NB */ 0x02000000:
|
||||
return "AUDIO_FORMAT_AMR_NB";
|
||||
case /* AUDIO_FORMAT_AMR_WB */ 0x03000000:
|
||||
return "AUDIO_FORMAT_AMR_WB";
|
||||
case /* AUDIO_FORMAT_AAC */ 0x04000000:
|
||||
return "AUDIO_FORMAT_AAC";
|
||||
case /* AUDIO_FORMAT_HE_AAC_V1 */ 0x05000000:
|
||||
return "AUDIO_FORMAT_HE_AAC_V1";
|
||||
case /* AUDIO_FORMAT_HE_AAC_V2 */ 0x06000000:
|
||||
return "AUDIO_FORMAT_HE_AAC_V2";
|
||||
case /* AUDIO_FORMAT_VORBIS */ 0x07000000:
|
||||
return "AUDIO_FORMAT_VORBIS";
|
||||
case /* AUDIO_FORMAT_OPUS */ 0x08000000:
|
||||
return "AUDIO_FORMAT_OPUS";
|
||||
case /* AUDIO_FORMAT_AC3 */ 0x09000000:
|
||||
return "AUDIO_FORMAT_AC3";
|
||||
case /* AUDIO_FORMAT_E_AC3 */ 0x0A000000:
|
||||
return "AUDIO_FORMAT_E_AC3";
|
||||
case /* AUDIO_FORMAT_DTS */ 0x0B000000:
|
||||
return "AUDIO_FORMAT_DTS";
|
||||
case /* AUDIO_FORMAT_DTS_HD */ 0x0C000000:
|
||||
return "AUDIO_FORMAT_DTS_HD";
|
||||
case /* AUDIO_FORMAT_IEC61937 */ 0x0D000000:
|
||||
return "AUDIO_FORMAT_IEC61937";
|
||||
case /* AUDIO_FORMAT_DOLBY_TRUEHD */ 0x0E000000:
|
||||
return "AUDIO_FORMAT_DOLBY_TRUEHD";
|
||||
case /* AUDIO_FORMAT_EVRC */ 0x10000000:
|
||||
return "AUDIO_FORMAT_EVRC";
|
||||
case /* AUDIO_FORMAT_EVRCB */ 0x11000000:
|
||||
return "AUDIO_FORMAT_EVRCB";
|
||||
case /* AUDIO_FORMAT_EVRCWB */ 0x12000000:
|
||||
return "AUDIO_FORMAT_EVRCWB";
|
||||
case /* AUDIO_FORMAT_EVRCNW */ 0x13000000:
|
||||
return "AUDIO_FORMAT_EVRCNW";
|
||||
case /* AUDIO_FORMAT_AAC_ADIF */ 0x14000000:
|
||||
return "AUDIO_FORMAT_AAC_ADIF";
|
||||
case /* AUDIO_FORMAT_WMA */ 0x15000000:
|
||||
return "AUDIO_FORMAT_WMA";
|
||||
case /* AUDIO_FORMAT_WMA_PRO */ 0x16000000:
|
||||
return "AUDIO_FORMAT_WMA_PRO";
|
||||
case /* AUDIO_FORMAT_AMR_WB_PLUS */ 0x17000000:
|
||||
return "AUDIO_FORMAT_AMR_WB_PLUS";
|
||||
case /* AUDIO_FORMAT_MP2 */ 0x18000000:
|
||||
return "AUDIO_FORMAT_MP2";
|
||||
case /* AUDIO_FORMAT_QCELP */ 0x19000000:
|
||||
return "AUDIO_FORMAT_QCELP";
|
||||
case /* AUDIO_FORMAT_DSD */ 0x1A000000:
|
||||
return "AUDIO_FORMAT_DSD";
|
||||
case /* AUDIO_FORMAT_FLAC */ 0x1B000000:
|
||||
return "AUDIO_FORMAT_FLAC";
|
||||
case /* AUDIO_FORMAT_ALAC */ 0x1C000000:
|
||||
return "AUDIO_FORMAT_ALAC";
|
||||
case /* AUDIO_FORMAT_APE */ 0x1D000000:
|
||||
return "AUDIO_FORMAT_APE";
|
||||
case /* AUDIO_FORMAT_AAC_ADTS */ 0x1E000000:
|
||||
return "AUDIO_FORMAT_AAC_ADTS";
|
||||
case /* AUDIO_FORMAT_SBC */ 0x1F000000:
|
||||
return "AUDIO_FORMAT_SBC";
|
||||
case /* AUDIO_FORMAT_APTX */ 0x20000000:
|
||||
return "AUDIO_FORMAT_APTX";
|
||||
case /* AUDIO_FORMAT_APTX_HD */ 0x21000000:
|
||||
return "AUDIO_FORMAT_APTX_HD";
|
||||
case /* AUDIO_FORMAT_AC4 */ 0x22000000:
|
||||
return "AUDIO_FORMAT_AC4";
|
||||
case /* AUDIO_FORMAT_LDAC */ 0x23000000:
|
||||
return "AUDIO_FORMAT_LDAC";
|
||||
case /* AUDIO_FORMAT_MAT */ 0x24000000:
|
||||
return "AUDIO_FORMAT_MAT";
|
||||
case /* AUDIO_FORMAT_AAC_LATM */ 0x25000000:
|
||||
return "AUDIO_FORMAT_AAC_LATM";
|
||||
case /* AUDIO_FORMAT_CELT */ 0x26000000:
|
||||
return "AUDIO_FORMAT_CELT";
|
||||
case /* AUDIO_FORMAT_APTX_ADAPTIVE */ 0x27000000:
|
||||
return "AUDIO_FORMAT_APTX_ADAPTIVE";
|
||||
case /* AUDIO_FORMAT_LHDC */ 0x28000000:
|
||||
return "AUDIO_FORMAT_LHDC";
|
||||
case /* AUDIO_FORMAT_LHDC_LL */ 0x29000000:
|
||||
return "AUDIO_FORMAT_LHDC_LL";
|
||||
case /* AUDIO_FORMAT_APTX_TWSP */ 0x2A000000:
|
||||
return "AUDIO_FORMAT_APTX_TWSP";
|
||||
|
||||
/* Aliases */
|
||||
case /* AUDIO_FORMAT_PCM_16_BIT */ 0x1:
|
||||
return "AUDIO_FORMAT_PCM_16_BIT"; // (PCM | PCM_SUB_16_BIT)
|
||||
case /* AUDIO_FORMAT_PCM_8_BIT */ 0x2:
|
||||
return "AUDIO_FORMAT_PCM_8_BIT"; // (PCM | PCM_SUB_8_BIT)
|
||||
case /* AUDIO_FORMAT_PCM_32_BIT */ 0x3:
|
||||
return "AUDIO_FORMAT_PCM_32_BIT"; // (PCM | PCM_SUB_32_BIT)
|
||||
case /* AUDIO_FORMAT_PCM_8_24_BIT */ 0x4:
|
||||
return "AUDIO_FORMAT_PCM_8_24_BIT"; // (PCM | PCM_SUB_8_24_BIT)
|
||||
case /* AUDIO_FORMAT_PCM_FLOAT */ 0x5:
|
||||
return "AUDIO_FORMAT_PCM_FLOAT"; // (PCM | PCM_SUB_FLOAT)
|
||||
case /* AUDIO_FORMAT_PCM_24_BIT_PACKED */ 0x6:
|
||||
return "AUDIO_FORMAT_PCM_24_BIT_PACKED"; // (PCM | PCM_SUB_24_BIT_PACKED)
|
||||
case /* AUDIO_FORMAT_AAC_MAIN */ 0x4000001:
|
||||
return "AUDIO_FORMAT_AAC_MAIN"; // (AAC | AAC_SUB_MAIN)
|
||||
case /* AUDIO_FORMAT_AAC_LC */ 0x4000002:
|
||||
return "AUDIO_FORMAT_AAC_LC"; // (AAC | AAC_SUB_LC)
|
||||
case /* AUDIO_FORMAT_AAC_SSR */ 0x4000004:
|
||||
return "AUDIO_FORMAT_AAC_SSR"; // (AAC | AAC_SUB_SSR)
|
||||
case /* AUDIO_FORMAT_AAC_LTP */ 0x4000008:
|
||||
return "AUDIO_FORMAT_AAC_LTP"; // (AAC | AAC_SUB_LTP)
|
||||
case /* AUDIO_FORMAT_AAC_HE_V1 */ 0x4000010:
|
||||
return "AUDIO_FORMAT_AAC_HE_V1"; // (AAC | AAC_SUB_HE_V1)
|
||||
case /* AUDIO_FORMAT_AAC_SCALABLE */ 0x4000020:
|
||||
return "AUDIO_FORMAT_AAC_SCALABLE"; // (AAC | AAC_SUB_SCALABLE)
|
||||
case /* AUDIO_FORMAT_AAC_ERLC */ 0x4000040:
|
||||
return "AUDIO_FORMAT_AAC_ERLC"; // (AAC | AAC_SUB_ERLC)
|
||||
case /* AUDIO_FORMAT_AAC_LD */ 0x4000080:
|
||||
return "AUDIO_FORMAT_AAC_LD"; // (AAC | AAC_SUB_LD)
|
||||
case /* AUDIO_FORMAT_AAC_HE_V2 */ 0x4000100:
|
||||
return "AUDIO_FORMAT_AAC_HE_V2"; // (AAC | AAC_SUB_HE_V2)
|
||||
case /* AUDIO_FORMAT_AAC_ELD */ 0x4000200:
|
||||
return "AUDIO_FORMAT_AAC_ELD"; // (AAC | AAC_SUB_ELD)
|
||||
case /* AUDIO_FORMAT_AAC_XHE */ 0x4000300:
|
||||
return "AUDIO_FORMAT_AAC_XHE"; // (AAC | AAC_SUB_XHE)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_MAIN */ 0x1e000001:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_MAIN"; // (AAC_ADTS | AAC_SUB_MAIN)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_LC */ 0x1e000002:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_LC"; // (AAC_ADTS | AAC_SUB_LC)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_SSR */ 0x1e000004:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_SSR"; // (AAC_ADTS | AAC_SUB_SSR)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_LTP */ 0x1e000008:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_LTP"; // (AAC_ADTS | AAC_SUB_LTP)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_HE_V1 */ 0x1e000010:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_HE_V1"; // (AAC_ADTS | AAC_SUB_HE_V1)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_SCALABLE */ 0x1e000020:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_SCALABLE"; // (AAC_ADTS | AAC_SUB_SCALABLE)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_ERLC */ 0x1e000040:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_ERLC"; // (AAC_ADTS | AAC_SUB_ERLC)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_LD */ 0x1e000080:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_LD"; // (AAC_ADTS | AAC_SUB_LD)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_HE_V2 */ 0x1e000100:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_HE_V2"; // (AAC_ADTS | AAC_SUB_HE_V2)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_ELD */ 0x1e000200:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_ELD"; // (AAC_ADTS | AAC_SUB_ELD)
|
||||
case /* AUDIO_FORMAT_AAC_ADTS_XHE */ 0x1e000300:
|
||||
return "AUDIO_FORMAT_AAC_ADTS_XHE"; // (AAC_ADTS | AAC_SUB_XHE)
|
||||
case /* AUDIO_FORMAT_AAC_LATM_LC */ 0x25000002:
|
||||
return "AUDIO_FORMAT_AAC_LATM_LC"; // (AAC_LATM | AAC_SUB_LC)
|
||||
case /* AUDIO_FORMAT_AAC_LATM_HE_V1 */ 0x25000010:
|
||||
return "AUDIO_FORMAT_AAC_LATM_HE_V1"; // (AAC_LATM | AAC_SUB_HE_V1)
|
||||
case /* AUDIO_FORMAT_AAC_LATM_HE_V2 */ 0x25000100:
|
||||
return "AUDIO_FORMAT_AAC_LATM_HE_V2"; // (AAC_LATM | AAC_SUB_HE_V2)
|
||||
case /* AUDIO_FORMAT_E_AC3_JOC */ 0xA000001:
|
||||
return "AUDIO_FORMAT_E_AC3_JOC"; // (E_AC3 | E_AC3_SUB_JOC)
|
||||
case /* AUDIO_FORMAT_MAT_1_0 */ 0x24000001:
|
||||
return "AUDIO_FORMAT_MAT_1_0"; // (MAT | MAT_SUB_1_0)
|
||||
case /* AUDIO_FORMAT_MAT_2_0 */ 0x24000002:
|
||||
return "AUDIO_FORMAT_MAT_2_0"; // (MAT | MAT_SUB_2_0)
|
||||
case /* AUDIO_FORMAT_MAT_2_1 */ 0x24000003:
|
||||
return "AUDIO_FORMAT_MAT_2_1"; // (MAT | MAT_SUB_2_1)
|
||||
default:
|
||||
return "AUDIO_FORMAT_(" + audioFormat + ")";
|
||||
}
|
||||
}
|
||||
|
||||
/* Routing bits for the former setRouting/getRouting API */
|
||||
/** @hide @deprecated */
|
||||
@Deprecated public static final int ROUTE_EARPIECE = (1 << 0);
|
||||
|
||||
@@ -38,6 +38,117 @@ import java.util.Objects;
|
||||
public class MediaMetrics {
|
||||
public static final String TAG = "MediaMetrics";
|
||||
|
||||
public static final String SEPARATOR = ".";
|
||||
|
||||
/**
|
||||
* A list of established MediaMetrics names that can be used for Items.
|
||||
*/
|
||||
public static class Name {
|
||||
public static final String AUDIO = "audio";
|
||||
public static final String AUDIO_BLUETOOTH = AUDIO + SEPARATOR + "bluetooth";
|
||||
public static final String AUDIO_DEVICE = AUDIO + SEPARATOR + "device";
|
||||
public static final String AUDIO_FOCUS = AUDIO + SEPARATOR + "focus";
|
||||
public static final String AUDIO_FORCE_USE = AUDIO + SEPARATOR + "forceUse";
|
||||
public static final String AUDIO_MIC = AUDIO + SEPARATOR + "mic";
|
||||
public static final String AUDIO_SERVICE = AUDIO + SEPARATOR + "service";
|
||||
public static final String AUDIO_VOLUME = AUDIO + SEPARATOR + "volume";
|
||||
public static final String AUDIO_VOLUME_EVENT = AUDIO_VOLUME + SEPARATOR + "event";
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of established string values.
|
||||
*/
|
||||
public static class Value {
|
||||
public static final String CONNECT = "connect";
|
||||
public static final String CONNECTED = "connected";
|
||||
public static final String DISCONNECT = "disconnect";
|
||||
public static final String DISCONNECTED = "disconnected";
|
||||
public static final String DOWN = "down";
|
||||
public static final String MUTE = "mute";
|
||||
public static final String NO = "no";
|
||||
public static final String OFF = "off";
|
||||
public static final String ON = "on";
|
||||
public static final String UNMUTE = "unmute";
|
||||
public static final String UP = "up";
|
||||
public static final String YES = "yes";
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of standard property keys for consistent use and type.
|
||||
*/
|
||||
public static class Property {
|
||||
// A use for Bluetooth or USB device addresses
|
||||
public static final Key<String> ADDRESS = createKey("address", String.class);
|
||||
// A string representing the Audio Attributes
|
||||
public static final Key<String> ATTRIBUTES = createKey("attributes", String.class);
|
||||
|
||||
// The calling package responsible for the state change
|
||||
public static final Key<String> CALLING_PACKAGE =
|
||||
createKey("callingPackage", String.class);
|
||||
|
||||
// The client name
|
||||
public static final Key<String> CLIENT_NAME = createKey("clientName", String.class);
|
||||
|
||||
// The device type
|
||||
public static final Key<Integer> DELAY_MS = createKey("delayMs", Integer.class);
|
||||
|
||||
// The device type
|
||||
public static final Key<String> DEVICE = createKey("device", String.class);
|
||||
|
||||
// For volume changes, up or down
|
||||
public static final Key<String> DIRECTION = createKey("direction", String.class);
|
||||
|
||||
// A reason for early return or error
|
||||
public static final Key<String> EARLY_RETURN =
|
||||
createKey("earlyReturn", String.class);
|
||||
// ENCODING_ ... string to match AudioFormat encoding
|
||||
public static final Key<String> ENCODING = createKey("encoding", String.class);
|
||||
|
||||
public static final Key<String> EVENT = createKey("event#", String.class);
|
||||
|
||||
// event generated is external (yes, no)
|
||||
public static final Key<String> EXTERNAL = createKey("external", String.class);
|
||||
|
||||
public static final Key<Integer> FLAGS = createKey("flags", Integer.class);
|
||||
public static final Key<String> FOCUS_CHANGE_HINT =
|
||||
createKey("focusChangeHint", String.class);
|
||||
public static final Key<String> FORCE_USE_DUE_TO =
|
||||
createKey("forceUseDueTo", String.class);
|
||||
public static final Key<String> FORCE_USE_MODE =
|
||||
createKey("forceUseMode", String.class);
|
||||
public static final Key<Double> GAIN_DB =
|
||||
createKey("gainDb", Double.class);
|
||||
public static final Key<String> GROUP =
|
||||
createKey("group", String.class);
|
||||
// For volume
|
||||
public static final Key<Integer> INDEX = createKey("index", Integer.class);
|
||||
public static final Key<Integer> MAX_INDEX = createKey("maxIndex", Integer.class);
|
||||
public static final Key<Integer> MIN_INDEX = createKey("minIndex", Integer.class);
|
||||
public static final Key<String> MODE =
|
||||
createKey("mode", String.class); // audio_mode
|
||||
public static final Key<String> MUTE =
|
||||
createKey("mute", String.class); // microphone, on or off.
|
||||
|
||||
// Bluetooth or Usb device name
|
||||
public static final Key<String> NAME =
|
||||
createKey("name", String.class);
|
||||
|
||||
// Number of observers
|
||||
public static final Key<Integer> OBSERVERS =
|
||||
createKey("observers", Integer.class);
|
||||
|
||||
public static final Key<String> REQUEST =
|
||||
createKey("request", String.class);
|
||||
|
||||
// For Bluetooth
|
||||
public static final Key<String> SCO_AUDIO_MODE =
|
||||
createKey("scoAudioMode", String.class);
|
||||
public static final Key<Integer> SDK = createKey("sdk", Integer.class);
|
||||
public static final Key<String> STATE = createKey("state", String.class);
|
||||
public static final Key<Integer> STATUS = createKey("status", Integer.class);
|
||||
public static final Key<String> STREAM_TYPE = createKey("streamType", String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The TYPE constants below should match those in native MediaMetricsItem.h
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.media.AudioRoutesInfo;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IAudioRoutesObserver;
|
||||
import android.media.IStrategyPreferredDeviceDispatcher;
|
||||
import android.media.MediaMetrics;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -668,6 +669,13 @@ import java.io.PrintWriter;
|
||||
}
|
||||
AudioService.sForceUseLogger.log(
|
||||
new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR
|
||||
+ AudioSystem.forceUseUsageToString(useCase))
|
||||
.set(MediaMetrics.Property.EVENT, "onSetForceUse")
|
||||
.set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource)
|
||||
.set(MediaMetrics.Property.FORCE_USE_MODE,
|
||||
AudioSystem.forceUseConfigToString(config))
|
||||
.record();
|
||||
AudioSystem.setForceUse(useCase, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.media.AudioRoutesInfo;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IAudioRoutesObserver;
|
||||
import android.media.IStrategyPreferredDeviceDispatcher;
|
||||
import android.media.MediaMetrics;
|
||||
import android.os.Binder;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
@@ -64,10 +65,69 @@ public class AudioDeviceInventory {
|
||||
// lock to synchronize all access to mConnectedDevices and mApmConnectedDevices
|
||||
private final Object mDevicesLock = new Object();
|
||||
|
||||
//Audio Analytics ids.
|
||||
private static final String mMetricsId = "audio.device.";
|
||||
|
||||
// List of connected devices
|
||||
// Key for map created from DeviceInfo.makeDeviceListKey()
|
||||
@GuardedBy("mDevicesLock")
|
||||
private final LinkedHashMap<String, DeviceInfo> mConnectedDevices = new LinkedHashMap<>();
|
||||
private final LinkedHashMap<String, DeviceInfo> mConnectedDevices = new LinkedHashMap<>() {
|
||||
@Override
|
||||
public DeviceInfo put(String key, DeviceInfo value) {
|
||||
final DeviceInfo result = super.put(key, value);
|
||||
record("put", true /* connected */, key, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceInfo putIfAbsent(String key, DeviceInfo value) {
|
||||
final DeviceInfo result = super.putIfAbsent(key, value);
|
||||
if (result == null) {
|
||||
record("putIfAbsent", true /* connected */, key, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceInfo remove(Object key) {
|
||||
final DeviceInfo result = super.remove(key);
|
||||
if (result != null) {
|
||||
record("remove", false /* connected */, (String) key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
final boolean result = super.remove(key, value);
|
||||
if (result) {
|
||||
record("remove", false /* connected */, (String) key, (DeviceInfo) value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Not overridden
|
||||
// clear
|
||||
// compute
|
||||
// computeIfAbsent
|
||||
// computeIfPresent
|
||||
// merge
|
||||
// putAll
|
||||
// replace
|
||||
// replaceAll
|
||||
private void record(String event, boolean connected, String key, DeviceInfo value) {
|
||||
// DeviceInfo - int mDeviceType;
|
||||
// DeviceInfo - int mDeviceCodecFormat;
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
||||
+ MediaMetrics.SEPARATOR + AudioSystem.getDeviceName(value.mDeviceType))
|
||||
.set(MediaMetrics.Property.ADDRESS, value.mDeviceAddress)
|
||||
.set(MediaMetrics.Property.EVENT, event)
|
||||
.set(MediaMetrics.Property.NAME, value.mDeviceName)
|
||||
.set(MediaMetrics.Property.STATE, connected
|
||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||
.record();
|
||||
}
|
||||
};
|
||||
|
||||
// List of devices actually connected to AudioPolicy (through AudioSystem), only one
|
||||
// by device type, which is used as the key, value is the DeviceInfo generated key.
|
||||
@@ -236,6 +296,16 @@ public class AudioDeviceInventory {
|
||||
+ " codec=" + a2dpCodec
|
||||
+ " vol=" + a2dpVolume));
|
||||
|
||||
new MediaMetrics.Item(mMetricsId + "a2dp")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.ENCODING, AudioSystem.audioFormatToString(a2dpCodec))
|
||||
.set(MediaMetrics.Property.EVENT, "onSetA2dpSinkConnectionState")
|
||||
.set(MediaMetrics.Property.INDEX, a2dpVolume)
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == BluetoothProfile.STATE_CONNECTED
|
||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||
.record();
|
||||
|
||||
synchronized (mDevicesLock) {
|
||||
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
btDevice.getAddress());
|
||||
@@ -284,6 +354,15 @@ public class AudioDeviceInventory {
|
||||
final DeviceInfo di = mConnectedDevices.get(key);
|
||||
boolean isConnected = di != null;
|
||||
|
||||
new MediaMetrics.Item(mMetricsId + "onSetA2dpSourceConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP))
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == BluetoothProfile.STATE_CONNECTED
|
||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||
.record();
|
||||
|
||||
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
|
||||
makeA2dpSrcUnavailable(address);
|
||||
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
|
||||
@@ -301,6 +380,17 @@ public class AudioDeviceInventory {
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"onSetHearingAidConnectionState addr=" + address));
|
||||
|
||||
new MediaMetrics.Item(mMetricsId + "onSetHearingAidConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP))
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == BluetoothProfile.STATE_CONNECTED
|
||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(streamType))
|
||||
.record();
|
||||
|
||||
synchronized (mDevicesLock) {
|
||||
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
|
||||
btDevice.getAddress());
|
||||
@@ -317,10 +407,15 @@ public class AudioDeviceInventory {
|
||||
}
|
||||
|
||||
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
||||
/*package*/ void onBluetoothA2dpActiveDeviceChange(
|
||||
/*package*/ void onBluetoothA2dpActiveDeviceChange(
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
||||
+ "onBluetoothA2dpActiveDeviceChange")
|
||||
.set(MediaMetrics.Property.EVENT, BtHelper.a2dpDeviceEventToString(event));
|
||||
|
||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
||||
if (btDevice == null) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "btDevice null").record();
|
||||
return;
|
||||
}
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
@@ -341,6 +436,8 @@ public class AudioDeviceInventory {
|
||||
if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"A2dp config change ignored (scheduled connection change)"));
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "A2dp config change ignored")
|
||||
.record();
|
||||
return;
|
||||
}
|
||||
final String key = DeviceInfo.makeDeviceListKey(
|
||||
@@ -348,9 +445,16 @@ public class AudioDeviceInventory {
|
||||
final DeviceInfo di = mConnectedDevices.get(key);
|
||||
if (di == null) {
|
||||
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "null DeviceInfo").record();
|
||||
return;
|
||||
}
|
||||
|
||||
mmi.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.ENCODING,
|
||||
AudioSystem.audioFormatToString(a2dpCodec))
|
||||
.set(MediaMetrics.Property.INDEX, a2dpVolume)
|
||||
.set(MediaMetrics.Property.NAME, di.mDeviceName);
|
||||
|
||||
if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
|
||||
// Device is connected
|
||||
if (a2dpVolume != -1) {
|
||||
@@ -388,6 +492,7 @@ public class AudioDeviceInventory {
|
||||
+ address + " codec=" + a2dpCodec).printLog(TAG));
|
||||
}
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
|
||||
/*package*/ void onMakeA2dpDeviceUnavailableNow(String address, int a2dpCodec) {
|
||||
@@ -399,6 +504,9 @@ public class AudioDeviceInventory {
|
||||
/*package*/ void onReportNewRoutes() {
|
||||
int n = mRoutesObservers.beginBroadcast();
|
||||
if (n > 0) {
|
||||
new MediaMetrics.Item(mMetricsId + "onReportNewRoutes")
|
||||
.set(MediaMetrics.Property.OBSERVERS, n)
|
||||
.record();
|
||||
AudioRoutesInfo routes;
|
||||
synchronized (mCurAudioRoutes) {
|
||||
routes = new AudioRoutesInfo(mCurAudioRoutes);
|
||||
@@ -428,6 +536,13 @@ public class AudioDeviceInventory {
|
||||
AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
|
||||
AudioService.sDeviceLogger.log(new AudioServiceEvents.WiredDevConnectEvent(wdcs));
|
||||
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
||||
+ "onSetWiredDeviceConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, wdcs.mAddress)
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(wdcs.mType))
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED
|
||||
? MediaMetrics.Value.DISCONNECTED : MediaMetrics.Value.CONNECTED);
|
||||
synchronized (mDevicesLock) {
|
||||
if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
|
||||
&& DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
|
||||
@@ -438,6 +553,8 @@ public class AudioDeviceInventory {
|
||||
if (!handleDeviceConnection(wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED,
|
||||
wdcs.mType, wdcs.mAddress, wdcs.mName)) {
|
||||
// change of connection state failed, bailout
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "change of connection state failed")
|
||||
.record();
|
||||
return;
|
||||
}
|
||||
if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
|
||||
@@ -453,15 +570,20 @@ public class AudioDeviceInventory {
|
||||
sendDeviceConnectionIntent(wdcs.mType, wdcs.mState, wdcs.mAddress, wdcs.mName);
|
||||
updateAudioRoutes(wdcs.mType, wdcs.mState);
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
|
||||
/*package*/ void onToggleHdmi() {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "onToggleHdmi")
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_OUT_HDMI));
|
||||
synchronized (mDevicesLock) {
|
||||
// Is HDMI connected?
|
||||
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
|
||||
final DeviceInfo di = mConnectedDevices.get(key);
|
||||
if (di == null) {
|
||||
Log.e(TAG, "invalid null DeviceInfo in onToggleHdmi");
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "invalid null DeviceInfo").record();
|
||||
return;
|
||||
}
|
||||
// Toggle HDMI to retrigger broadcast with proper formats.
|
||||
@@ -472,6 +594,7 @@ public class AudioDeviceInventory {
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
|
||||
"android"); // reconnect
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
|
||||
/*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDeviceAttributes device) {
|
||||
@@ -535,6 +658,12 @@ public class AudioDeviceInventory {
|
||||
+ Integer.toHexString(device) + " address:" + address
|
||||
+ " name:" + deviceName + ")");
|
||||
}
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "handleDeviceConnection")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(device))
|
||||
.set(MediaMetrics.Property.MODE, connect
|
||||
? MediaMetrics.Value.CONNECT : MediaMetrics.Value.DISCONNECT)
|
||||
.set(MediaMetrics.Property.NAME, deviceName);
|
||||
synchronized (mDevicesLock) {
|
||||
final String deviceKey = DeviceInfo.makeDeviceListKey(device, address);
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
@@ -550,13 +679,18 @@ public class AudioDeviceInventory {
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
if (res != AudioSystem.AUDIO_STATUS_OK) {
|
||||
Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device)
|
||||
+ " due to command error " + res);
|
||||
final String reason = "not connecting device 0x" + Integer.toHexString(device)
|
||||
+ " due to command error " + res;
|
||||
Slog.e(TAG, reason);
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
|
||||
.set(MediaMetrics.Property.STATE, MediaMetrics.Value.DISCONNECTED)
|
||||
.record();
|
||||
return false;
|
||||
}
|
||||
mConnectedDevices.put(deviceKey, new DeviceInfo(
|
||||
device, deviceName, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
|
||||
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
|
||||
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
|
||||
return true;
|
||||
} else if (!connect && isConnected) {
|
||||
mAudioSystem.setDeviceConnectionState(device,
|
||||
@@ -564,11 +698,13 @@ public class AudioDeviceInventory {
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
// always remove even if disconnection failed
|
||||
mConnectedDevices.remove(deviceKey);
|
||||
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
|
||||
return true;
|
||||
}
|
||||
Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey
|
||||
+ ", deviceSpec=" + di + ", connect=" + connect);
|
||||
}
|
||||
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.DISCONNECTED).record();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -582,6 +718,8 @@ public class AudioDeviceInventory {
|
||||
toRemove.add(deviceInfo.mDeviceAddress);
|
||||
}
|
||||
});
|
||||
new MediaMetrics.Item(mMetricsId + "disconnectA2dp")
|
||||
.record();
|
||||
if (toRemove.size() > 0) {
|
||||
final int delay = checkSendBecomingNoisyIntentInt(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
@@ -602,6 +740,8 @@ public class AudioDeviceInventory {
|
||||
toRemove.add(deviceInfo.mDeviceAddress);
|
||||
}
|
||||
});
|
||||
new MediaMetrics.Item(mMetricsId + "disconnectA2dpSink")
|
||||
.record();
|
||||
toRemove.stream().forEach(deviceAddress -> makeA2dpSrcUnavailable(deviceAddress));
|
||||
}
|
||||
}
|
||||
@@ -615,6 +755,8 @@ public class AudioDeviceInventory {
|
||||
toRemove.add(deviceInfo.mDeviceAddress);
|
||||
}
|
||||
});
|
||||
new MediaMetrics.Item(mMetricsId + "disconnectHearingAid")
|
||||
.record();
|
||||
if (toRemove.size() > 0) {
|
||||
final int delay = checkSendBecomingNoisyIntentInt(
|
||||
AudioSystem.DEVICE_OUT_HEARING_AID, 0, AudioSystem.DEVICE_NONE);
|
||||
@@ -743,6 +885,8 @@ public class AudioDeviceInventory {
|
||||
final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
|
||||
|
||||
// TODO: log in MediaMetrics once distinction between connection failure and
|
||||
// double connection is made.
|
||||
if (res != AudioSystem.AUDIO_STATUS_OK) {
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"APM failed to make available A2DP device addr=" + address
|
||||
@@ -771,7 +915,12 @@ public class AudioDeviceInventory {
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
private void makeA2dpDeviceUnavailableNow(String address, int a2dpCodec) {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "a2dp." + address)
|
||||
.set(MediaMetrics.Property.ENCODING, AudioSystem.audioFormatToString(a2dpCodec))
|
||||
.set(MediaMetrics.Property.EVENT, "makeA2dpDeviceUnavailableNow");
|
||||
|
||||
if (address == null) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "address null").record();
|
||||
return;
|
||||
}
|
||||
final String deviceToRemoveKey =
|
||||
@@ -783,6 +932,9 @@ public class AudioDeviceInventory {
|
||||
// removing A2DP device not currently used by AudioPolicy, log but don't act on it
|
||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
||||
"A2DP device " + address + " made unavailable, was not used")).printLog(TAG));
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN,
|
||||
"A2DP device made unavailable, was not used")
|
||||
.record();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -804,6 +956,7 @@ public class AudioDeviceInventory {
|
||||
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
|
||||
// Remove A2DP routes as well
|
||||
setCurrentAudioRouteNameIfPossible(null);
|
||||
mmi.record();
|
||||
}
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
@@ -862,6 +1015,14 @@ public class AudioDeviceInventory {
|
||||
mDeviceBroker.postApplyVolumeOnDevice(streamType,
|
||||
AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable");
|
||||
setCurrentAudioRouteNameIfPossible(name);
|
||||
new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceAvailable")
|
||||
.set(MediaMetrics.Property.ADDRESS, address != null ? address : "")
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_OUT_HEARING_AID))
|
||||
.set(MediaMetrics.Property.NAME, name)
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(streamType))
|
||||
.record();
|
||||
}
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
@@ -873,6 +1034,11 @@ public class AudioDeviceInventory {
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
|
||||
// Remove Hearing Aid routes as well
|
||||
setCurrentAudioRouteNameIfPossible(null);
|
||||
new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceUnavailable")
|
||||
.set(MediaMetrics.Property.ADDRESS, address != null ? address : "")
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_OUT_HEARING_AID))
|
||||
.record();
|
||||
}
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
@@ -919,10 +1085,18 @@ public class AudioDeviceInventory {
|
||||
@GuardedBy("mDevicesLock")
|
||||
private int checkSendBecomingNoisyIntentInt(int device,
|
||||
@AudioService.ConnectionState int state, int musicDevice) {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
||||
+ "checkSendBecomingNoisyIntentInt")
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(device))
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == AudioService.CONNECTION_STATE_CONNECTED
|
||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED);
|
||||
if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
|
||||
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record(); // OK to return
|
||||
return 0;
|
||||
}
|
||||
if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
|
||||
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record(); // OK to return
|
||||
return 0;
|
||||
}
|
||||
int delay = 0;
|
||||
@@ -950,12 +1124,14 @@ public class AudioDeviceInventory {
|
||||
// the pausing of some apps that are playing remotely
|
||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
||||
"dropping ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
|
||||
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record(); // OK to return
|
||||
return 0;
|
||||
}
|
||||
mDeviceBroker.postBroadcastBecomingNoisy();
|
||||
delay = AudioService.BECOMING_NOISY_DELAY_MS;
|
||||
}
|
||||
|
||||
mmi.set(MediaMetrics.Property.DELAY_MS, delay).record();
|
||||
return delay;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ import android.media.IStrategyPreferredDeviceDispatcher;
|
||||
import android.media.IVolumeController;
|
||||
import android.media.MediaExtractor;
|
||||
import android.media.MediaFormat;
|
||||
import android.media.MediaMetrics;
|
||||
import android.media.PlayerBase;
|
||||
import android.media.VolumePolicy;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
@@ -1880,6 +1881,16 @@ public class AudioService extends IAudioService.Stub
|
||||
synchronized (mExtVolumeControllerLock) {
|
||||
extVolCtlr = mExtVolumeController;
|
||||
}
|
||||
new MediaMetrics.Item(mMetricsId + "adjustSuggestedStreamVolume")
|
||||
.setUid(Binder.getCallingUid())
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackage)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, caller)
|
||||
.set(MediaMetrics.Property.DIRECTION, direction > 0
|
||||
? MediaMetrics.Value.UP : MediaMetrics.Value.DOWN)
|
||||
.set(MediaMetrics.Property.EXTERNAL, extVolCtlr != null
|
||||
? MediaMetrics.Value.YES : MediaMetrics.Value.NO)
|
||||
.set(MediaMetrics.Property.FLAGS, flags)
|
||||
.record();
|
||||
if (extVolCtlr != null) {
|
||||
sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
|
||||
direction, 0 /*ignored*/,
|
||||
@@ -3141,21 +3152,32 @@ public class AudioService extends IAudioService.Stub
|
||||
if (uid == android.os.Process.SYSTEM_UID) {
|
||||
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
|
||||
}
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
|
||||
.setUid(uid)
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackage)
|
||||
.set(MediaMetrics.Property.EVENT, "setMicrophoneMute")
|
||||
.set(MediaMetrics.Property.REQUEST, on
|
||||
? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE);
|
||||
|
||||
// If OP_MUTE_MICROPHONE is set, disallow unmuting.
|
||||
if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "disallow unmuting").record();
|
||||
return;
|
||||
}
|
||||
if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "!checkAudioSettingsPermission").record();
|
||||
return;
|
||||
}
|
||||
if (userId != UserHandle.getCallingUserId() &&
|
||||
mContext.checkCallingOrSelfPermission(
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "permission").record();
|
||||
return;
|
||||
}
|
||||
mMicMuteFromApi = on;
|
||||
mmi.record(); // record now, the no caller check will set the mute state.
|
||||
setMicrophoneMuteNoCallerCheck(userId);
|
||||
}
|
||||
|
||||
@@ -3167,6 +3189,12 @@ public class AudioService extends IAudioService.Stub
|
||||
return;
|
||||
}
|
||||
mMicMuteFromSwitch = on;
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
|
||||
.setUid(userId)
|
||||
.set(MediaMetrics.Property.EVENT, "setMicrophoneMuteFromSwitch")
|
||||
.set(MediaMetrics.Property.REQUEST, on
|
||||
? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE)
|
||||
.record();
|
||||
setMicrophoneMuteNoCallerCheck(userId);
|
||||
}
|
||||
|
||||
@@ -3207,6 +3235,17 @@ public class AudioService extends IAudioService.Stub
|
||||
Log.e(TAG, "Error changing mic mute state to " + muted + " current:"
|
||||
+ mMicMuteFromSystemCached);
|
||||
}
|
||||
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
|
||||
.setUid(userId)
|
||||
.set(MediaMetrics.Property.EVENT, "setMicrophoneMuteNoCallerCheck")
|
||||
.set(MediaMetrics.Property.MUTE, mMicMuteFromSystemCached
|
||||
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
||||
.set(MediaMetrics.Property.REQUEST, muted
|
||||
? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE)
|
||||
.set(MediaMetrics.Property.STATUS, ret)
|
||||
.record();
|
||||
|
||||
try {
|
||||
// send the intent even if there was a failure to change the actual mute state:
|
||||
// the AudioManager.setMicrophoneMute API doesn't have a return value to
|
||||
@@ -3941,10 +3980,20 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
|
||||
// for logging only
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/")
|
||||
.append(pid).toString();
|
||||
final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(on, eventSource);
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
||||
+ MediaMetrics.SEPARATOR + "setSpeakerphoneOn")
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.STATE, on
|
||||
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
||||
.record();
|
||||
|
||||
if (stateChanged) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -3975,9 +4024,19 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
|
||||
// for logging only
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/").append(pid).toString();
|
||||
|
||||
//bt sco
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
||||
+ MediaMetrics.SEPARATOR + "setBluetoothScoOn")
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.STATE, on
|
||||
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
||||
.record();
|
||||
|
||||
mDeviceBroker.setBluetoothScoOn(on, eventSource);
|
||||
}
|
||||
@@ -3993,9 +4052,20 @@ public class AudioService extends IAudioService.Stub
|
||||
/** @see AudioManager#setBluetoothA2dpOn(boolean) */
|
||||
public void setBluetoothA2dpOn(boolean on) {
|
||||
// for logging only
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/")
|
||||
.append(pid).toString();
|
||||
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
|
||||
+ MediaMetrics.SEPARATOR + "setBluetoothA2dpOn")
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.STATE, on
|
||||
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
|
||||
.record();
|
||||
|
||||
mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
|
||||
}
|
||||
|
||||
@@ -4006,31 +4076,59 @@ public class AudioService extends IAudioService.Stub
|
||||
|
||||
/** @see AudioManager#startBluetoothSco() */
|
||||
public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final int scoAudioMode =
|
||||
(targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
|
||||
BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
|
||||
final String eventSource = new StringBuilder("startBluetoothSco()")
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/")
|
||||
.append(pid).toString();
|
||||
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.EVENT, "startBluetoothSco")
|
||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||
BtHelper.scoAudioModeToString(scoAudioMode))
|
||||
.record();
|
||||
startBluetoothScoInt(cb, scoAudioMode, eventSource);
|
||||
|
||||
}
|
||||
|
||||
/** @see AudioManager#startBluetoothScoVirtualCall() */
|
||||
public void startBluetoothScoVirtualCall(IBinder cb) {
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/")
|
||||
.append(pid).toString();
|
||||
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.EVENT, "startBluetoothScoVirtualCall")
|
||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||
BtHelper.scoAudioModeToString(BtHelper.SCO_MODE_VIRTUAL_CALL))
|
||||
.record();
|
||||
startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
|
||||
}
|
||||
|
||||
void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
||||
.set(MediaMetrics.Property.EVENT, "startBluetoothScoInt")
|
||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||
BtHelper.scoAudioModeToString(scoAudioMode));
|
||||
|
||||
if (!checkAudioSettingsPermission("startBluetoothSco()") ||
|
||||
!mSystemReady) {
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "permission or systemReady").record();
|
||||
return;
|
||||
}
|
||||
synchronized (mDeviceBroker.mSetModeLock) {
|
||||
mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
|
||||
/** @see AudioManager#stopBluetoothSco() */
|
||||
@@ -4039,12 +4137,21 @@ public class AudioService extends IAudioService.Stub
|
||||
!mSystemReady) {
|
||||
return;
|
||||
}
|
||||
final int uid = Binder.getCallingUid();
|
||||
final int pid = Binder.getCallingPid();
|
||||
final String eventSource = new StringBuilder("stopBluetoothSco()")
|
||||
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
|
||||
.append(Binder.getCallingPid()).toString();
|
||||
.append(") from u/pid:").append(uid).append("/")
|
||||
.append(pid).toString();
|
||||
synchronized (mDeviceBroker.mSetModeLock) {
|
||||
mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
|
||||
}
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
|
||||
.setUid(uid)
|
||||
.setPid(pid)
|
||||
.set(MediaMetrics.Property.EVENT, "stopBluetoothSco")
|
||||
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
|
||||
BtHelper.scoAudioModeToString(BtHelper.SCO_MODE_UNDEFINED))
|
||||
.record();
|
||||
}
|
||||
|
||||
|
||||
@@ -4806,6 +4913,14 @@ public class AudioService extends IAudioService.Stub
|
||||
&& state != CONNECTION_STATE_DISCONNECTED) {
|
||||
throw new IllegalArgumentException("Invalid state " + state);
|
||||
}
|
||||
new MediaMetrics.Item(mMetricsId + "setWiredDeviceConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, caller)
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(type))
|
||||
.set(MediaMetrics.Property.NAME, name)
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == CONNECTION_STATE_CONNECTED ? "connected" : "disconnected")
|
||||
.record();
|
||||
mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
|
||||
}
|
||||
|
||||
@@ -5266,7 +5381,32 @@ public class AudioService extends IAudioService.Stub
|
||||
private String mVolumeIndexSettingName;
|
||||
private int mObservedDevices;
|
||||
|
||||
private final SparseIntArray mIndexMap = new SparseIntArray(8);
|
||||
private final SparseIntArray mIndexMap = new SparseIntArray(8) {
|
||||
@Override
|
||||
public void put(int key, int value) {
|
||||
super.put(key, value);
|
||||
record("put", key, value);
|
||||
}
|
||||
@Override
|
||||
public void setValueAt(int index, int value) {
|
||||
super.setValueAt(index, value);
|
||||
record("setValueAt", keyAt(index), value);
|
||||
}
|
||||
|
||||
// Record all changes in the VolumeStreamState
|
||||
private void record(String event, int key, int value) {
|
||||
final String device = key == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
|
||||
: AudioSystem.getOutputDeviceName(key);
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME + MediaMetrics.SEPARATOR
|
||||
+ AudioSystem.streamToString(mStreamType)
|
||||
+ "." + device)
|
||||
.set(MediaMetrics.Property.EVENT, event)
|
||||
.set(MediaMetrics.Property.INDEX, value)
|
||||
.set(MediaMetrics.Property.MIN_INDEX, mIndexMin)
|
||||
.set(MediaMetrics.Property.MAX_INDEX, mIndexMax)
|
||||
.record();
|
||||
}
|
||||
};
|
||||
private final Intent mVolumeChanged;
|
||||
private final Intent mStreamDevicesChanged;
|
||||
|
||||
@@ -5949,6 +6089,13 @@ public class AudioService extends IAudioService.Stub
|
||||
+ eventSource);
|
||||
break;
|
||||
}
|
||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE
|
||||
+ MediaMetrics.SEPARATOR + AudioSystem.forceUseUsageToString(useCase))
|
||||
.set(MediaMetrics.Property.EVENT, "setForceUse")
|
||||
.set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource)
|
||||
.set(MediaMetrics.Property.FORCE_USE_MODE,
|
||||
AudioSystem.forceUseConfigToString(config))
|
||||
.record();
|
||||
sForceUseLogger.log(
|
||||
new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
|
||||
AudioSystem.setForceUse(useCase, config);
|
||||
@@ -6450,23 +6597,42 @@ public class AudioService extends IAudioService.Stub
|
||||
public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
|
||||
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
|
||||
IAudioPolicyCallback pcb, int sdk) {
|
||||
final int uid = Binder.getCallingUid();
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "focus")
|
||||
.setUid(uid)
|
||||
//.putInt("durationHint", durationHint)
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, clientId)
|
||||
.set(MediaMetrics.Property.EVENT, "requestAudioFocus")
|
||||
.set(MediaMetrics.Property.FLAGS, flags);
|
||||
|
||||
// permission checks
|
||||
if (aa != null && !isValidAudioAttributesUsage(aa)) {
|
||||
Log.w(TAG, "Request using unsupported usage.");
|
||||
final String reason = "Request using unsupported usage";
|
||||
Log.w(TAG, reason);
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
|
||||
.record();
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
|
||||
if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
|
||||
if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
|
||||
android.Manifest.permission.MODIFY_PHONE_STATE)) {
|
||||
Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
|
||||
final String reason = "Invalid permission to (un)lock audio focus";
|
||||
Log.e(TAG, reason, new Exception());
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
|
||||
.record();
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
} else {
|
||||
// only a registered audio policy can be used to lock focus
|
||||
synchronized (mAudioPolicies) {
|
||||
if (!mAudioPolicies.containsKey(pcb.asBinder())) {
|
||||
Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
|
||||
final String reason =
|
||||
"Invalid unregistered AudioPolicy to (un)lock audio focus";
|
||||
Log.e(TAG, reason);
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
|
||||
.record();
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
}
|
||||
@@ -6474,25 +6640,40 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
|
||||
if (callingPackageName == null || clientId == null || aa == null) {
|
||||
Log.e(TAG, "Invalid null parameter to request audio focus");
|
||||
final String reason = "Invalid null parameter to request audio focus";
|
||||
Log.e(TAG, reason);
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
|
||||
.record();
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
|
||||
mmi.record();
|
||||
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
|
||||
clientId, callingPackageName, flags, sdk,
|
||||
forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
|
||||
forceFocusDuckingForAccessibility(aa, durationHint, uid));
|
||||
}
|
||||
|
||||
public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
|
||||
String callingPackageName) {
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "focus")
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, clientId)
|
||||
.set(MediaMetrics.Property.EVENT, "abandonAudioFocus");
|
||||
|
||||
if (aa != null && !isValidAudioAttributesUsage(aa)) {
|
||||
Log.w(TAG, "Request using unsupported usage.");
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "unsupported usage").record();
|
||||
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
mmi.record();
|
||||
return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
|
||||
}
|
||||
|
||||
public void unregisterAudioFocusClient(String clientId) {
|
||||
new MediaMetrics.Item(mMetricsId + "focus")
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, clientId)
|
||||
.set(MediaMetrics.Property.EVENT, "unregisterAudioFocusClient")
|
||||
.record();
|
||||
mMediaFocusControl.unregisterAudioFocusClient(clientId);
|
||||
}
|
||||
|
||||
@@ -7066,6 +7247,12 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio Analytics ids.
|
||||
*/
|
||||
private static final String mMetricsId = MediaMetrics.Name.AUDIO_SERVICE
|
||||
+ MediaMetrics.SEPARATOR;
|
||||
|
||||
private static String safeMediaVolumeStateToString(int state) {
|
||||
switch(state) {
|
||||
case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.audio;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.MediaMetrics;
|
||||
|
||||
import com.android.server.audio.AudioDeviceInventory.WiredDeviceConnectionState;
|
||||
|
||||
@@ -120,6 +121,7 @@ public class AudioServiceEvents {
|
||||
mCaller = caller;
|
||||
mGroupName = null;
|
||||
mAudioAttributes = null;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
/** used for VOL_SET_HEARING_AID_VOL*/
|
||||
@@ -132,6 +134,7 @@ public class AudioServiceEvents {
|
||||
mCaller = null;
|
||||
mGroupName = null;
|
||||
mAudioAttributes = null;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
/** used for VOL_SET_AVRCP_VOL */
|
||||
@@ -144,6 +147,7 @@ public class AudioServiceEvents {
|
||||
mCaller = null;
|
||||
mGroupName = null;
|
||||
mAudioAttributes = null;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
/** used for VOL_VOICE_ACTIVITY_HEARING_AID */
|
||||
@@ -156,6 +160,7 @@ public class AudioServiceEvents {
|
||||
mCaller = null;
|
||||
mGroupName = null;
|
||||
mAudioAttributes = null;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
/** used for VOL_MODE_CHANGE_HEARING_AID */
|
||||
@@ -168,6 +173,7 @@ public class AudioServiceEvents {
|
||||
mCaller = null;
|
||||
mGroupName = null;
|
||||
mAudioAttributes = null;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
/** used for VOL_SET_GROUP_VOL */
|
||||
@@ -179,6 +185,102 @@ public class AudioServiceEvents {
|
||||
mCaller = caller;
|
||||
mGroupName = group;
|
||||
mAudioAttributes = aa;
|
||||
logMetricEvent();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Audio Analytics unique Id.
|
||||
*/
|
||||
private static final String mMetricsId = MediaMetrics.Name.AUDIO_VOLUME_EVENT;
|
||||
|
||||
/**
|
||||
* Log mediametrics event
|
||||
*/
|
||||
private void logMetricEvent() {
|
||||
switch (mOp) {
|
||||
case VOL_ADJUST_SUGG_VOL:
|
||||
case VOL_ADJUST_VOL_UID:
|
||||
case VOL_ADJUST_STREAM_VOL: {
|
||||
String eventName;
|
||||
switch (mOp) {
|
||||
case VOL_ADJUST_SUGG_VOL:
|
||||
eventName = "adjustSuggestedStreamVolume";
|
||||
break;
|
||||
case VOL_ADJUST_STREAM_VOL:
|
||||
eventName = "adjustStreamVolume";
|
||||
break;
|
||||
case VOL_ADJUST_VOL_UID:
|
||||
eventName = "adjustStreamVolumeForUid";
|
||||
break;
|
||||
default:
|
||||
return; // not possible, just return here
|
||||
}
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
|
||||
.set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down")
|
||||
.set(MediaMetrics.Property.EVENT, eventName)
|
||||
.set(MediaMetrics.Property.FLAGS, mVal2)
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(mStream))
|
||||
.record();
|
||||
return;
|
||||
}
|
||||
case VOL_SET_STREAM_VOL:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
|
||||
.set(MediaMetrics.Property.EVENT, "setStreamVolume")
|
||||
.set(MediaMetrics.Property.FLAGS, mVal2)
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(mStream))
|
||||
.record();
|
||||
return;
|
||||
case VOL_SET_HEARING_AID_VOL:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.EVENT, "setHearingAidVolume")
|
||||
.set(MediaMetrics.Property.GAIN_DB, (double) mVal2)
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.record();
|
||||
return;
|
||||
case VOL_SET_AVRCP_VOL:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.EVENT, "setAvrcpVolume")
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.record();
|
||||
return;
|
||||
case VOL_VOICE_ACTIVITY_HEARING_AID:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.EVENT, "voiceActivityHearingAid")
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
mVal2 == 1 ? "active" : "inactive")
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(mStream))
|
||||
.record();
|
||||
return;
|
||||
case VOL_MODE_CHANGE_HEARING_AID:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.EVENT, "modeChangeHearingAid")
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mVal2))
|
||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||
AudioSystem.streamToString(mStream))
|
||||
.record();
|
||||
return;
|
||||
case VOL_SET_GROUP_VOL:
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.set(MediaMetrics.Property.ATTRIBUTES, mAudioAttributes.toString())
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
|
||||
.set(MediaMetrics.Property.EVENT, "setVolumeIndexForAttributes")
|
||||
.set(MediaMetrics.Property.FLAGS, mVal2)
|
||||
.set(MediaMetrics.Property.GROUP, mGroupName)
|
||||
.set(MediaMetrics.Property.INDEX, mVal1)
|
||||
.record();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -113,6 +113,24 @@ public class BtHelper {
|
||||
|
||||
private static final int BT_HEARING_AID_GAIN_MIN = -128;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the scoAudioMode.
|
||||
*/
|
||||
public static String scoAudioModeToString(int scoAudioMode) {
|
||||
switch (scoAudioMode) {
|
||||
case SCO_MODE_UNDEFINED:
|
||||
return "SCO_MODE_UNDEFINED";
|
||||
case SCO_MODE_VIRTUAL_CALL:
|
||||
return "SCO_MODE_VIRTUAL_CALL";
|
||||
case SCO_MODE_RAW:
|
||||
return "SCO_MODE_RAW";
|
||||
case SCO_MODE_VR:
|
||||
return "SCO_MODE_VR";
|
||||
default:
|
||||
return "SCO_MODE_(" + scoAudioMode + ")";
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/*package*/ static class BluetoothA2dpDeviceInfo {
|
||||
private final @NonNull BluetoothDevice mBtDevice;
|
||||
@@ -965,4 +983,27 @@ public class BtHelper {
|
||||
return AudioSystem.AUDIO_FORMAT_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String equivalent of the btCodecType.
|
||||
*
|
||||
* This uses an "ENCODING_" prefix for consistency with Audio;
|
||||
* we could alternately use the "SOURCE_CODEC_TYPE_" prefix from Bluetooth.
|
||||
*/
|
||||
public static String bluetoothCodecToEncodingString(int btCodecType) {
|
||||
switch (btCodecType) {
|
||||
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
|
||||
return "ENCODING_SBC";
|
||||
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC:
|
||||
return "ENCODING_AAC";
|
||||
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX:
|
||||
return "ENCODING_APTX";
|
||||
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD:
|
||||
return "ENCODING_APTX_HD";
|
||||
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
|
||||
return "ENCODING_LDAC";
|
||||
default:
|
||||
return "ENCODING_BT_CODEC_TYPE(" + btCodecType + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.media.AudioFocusInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IAudioFocusDispatcher;
|
||||
import android.media.MediaMetrics;
|
||||
import android.media.audiopolicy.IAudioPolicyCallback;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -144,6 +145,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
private static final AudioEventLogger mEventLogger = new AudioEventLogger(50,
|
||||
"focus commands as seen by MediaFocusControl");
|
||||
|
||||
private static final String mMetricsId = MediaMetrics.Name.AUDIO_FOCUS;
|
||||
|
||||
/*package*/ void noFocusForSuspendedApp(@NonNull String packageName, int uid) {
|
||||
synchronized (mAudioFocusLock) {
|
||||
final Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
|
||||
@@ -818,6 +821,17 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
|
||||
IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
|
||||
int flags, int sdk, boolean forceDuck) {
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.setUid(Binder.getCallingUid())
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, clientId)
|
||||
.set(MediaMetrics.Property.EVENT, "requestAudioFocus")
|
||||
.set(MediaMetrics.Property.FLAGS, flags)
|
||||
.set(MediaMetrics.Property.FOCUS_CHANGE_HINT,
|
||||
AudioManager.audioFocusToString(focusChangeHint))
|
||||
//.set(MediaMetrics.Property.SDK, sdk)
|
||||
.record();
|
||||
|
||||
mEventLogger.log((new AudioEventLogger.StringEvent(
|
||||
"requestAudioFocus() from uid/pid " + Binder.getCallingUid()
|
||||
+ "/" + Binder.getCallingPid()
|
||||
@@ -982,6 +996,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
* */
|
||||
protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
|
||||
String callingPackageName) {
|
||||
new MediaMetrics.Item(mMetricsId)
|
||||
.setUid(Binder.getCallingUid())
|
||||
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, clientId)
|
||||
.set(MediaMetrics.Property.EVENT, "abandonAudioFocus")
|
||||
.record();
|
||||
|
||||
// AudioAttributes are currently ignored, to be used for zones / a11y
|
||||
mEventLogger.log((new AudioEventLogger.StringEvent(
|
||||
"abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
|
||||
|
||||
Reference in New Issue
Block a user