MediaMetrics instrumentation am: df02382bea
Change-Id: I7c18211f21671b86e89b25f919456f9f9b021631
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index c17ed3e..c72674a 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -33,6 +33,7 @@
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,6 +65,10 @@
// lock to synchronize all access to mConnectedDevices and mApmConnectedDevices
private final Object mDevicesLock = new Object();
+ //Audio Analytics ids.
+ private static final String mAnalyticsId = "audio.deviceInventory.";
+ private static final String mAnalyticsPropEarlyReturn = "earlyReturn";
+
// List of connected devices
// Key for map created from DeviceInfo.makeDeviceListKey()
@GuardedBy("mDevicesLock")
@@ -242,6 +247,15 @@
final DeviceInfo di = mConnectedDevices.get(key);
boolean isConnected = di != null;
+ new MediaMetrics.Item(mAnalyticsId + "onSetA2dpSinkConnectionState")
+ .putInt("state", state)
+ .putString("address", address)
+ .putInt("a2dpCodec", a2dpCodec)
+ .putInt("a2dpVolume", a2dpVolume)
+ .putString("key", key)
+ .putInt("isConnected", isConnected ? 1 : 0)
+ .record();
+
if (isConnected) {
if (state == BluetoothProfile.STATE_CONNECTED) {
// device is already connected, but we are receiving a connection again,
@@ -284,6 +298,13 @@
final DeviceInfo di = mConnectedDevices.get(key);
boolean isConnected = di != null;
+ new MediaMetrics.Item(mAnalyticsId + "onSetA2dpSourceConnectionState")
+ .putInt("state", state)
+ .putString("address", address)
+ .putString("key", key)
+ .putInt("isConnected", isConnected ? 1 : 0)
+ .record();
+
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
makeA2dpSrcUnavailable(address);
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
@@ -307,6 +328,14 @@
final DeviceInfo di = mConnectedDevices.get(key);
boolean isConnected = di != null;
+ new MediaMetrics.Item(mAnalyticsId + "onSetHearingAidConnectionState")
+ .putInt("state", state)
+ .putInt("streamType", streamType)
+ .putString("address", address)
+ .putString("key", key)
+ .putInt("isConnected", isConnected ? 1 : 0)
+ .record();
+
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
makeHearingAidDeviceUnavailable(address);
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
@@ -319,8 +348,13 @@
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void onBluetoothA2dpActiveDeviceChange(
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId
+ + "onBluetoothA2dpActiveDeviceChange")
+ .putInt("event", event);
+
final BluetoothDevice btDevice = btInfo.getBtDevice();
if (btDevice == null) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "btDevice null").record();
return;
}
if (AudioService.DEBUG_DEVICES) {
@@ -341,6 +375,7 @@
if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"A2dp config change ignored (scheduled connection change)"));
+ mmi.putString(mAnalyticsPropEarlyReturn, "A2dp config change ignored").record();
return;
}
final String key = DeviceInfo.makeDeviceListKey(
@@ -348,9 +383,15 @@
final DeviceInfo di = mConnectedDevices.get(key);
if (di == null) {
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
+ mmi.putString(mAnalyticsPropEarlyReturn, "null DeviceInfo").record();
return;
}
+ mmi.putString("address", address)
+ .putInt("a2dpCodec", a2dpCodec)
+ .putInt("a2dpVolume", a2dpVolume)
+ .putString("key", key);
+
if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
// Device is connected
if (a2dpVolume != -1) {
@@ -382,12 +423,14 @@
btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
false /* suppressNoisyIntent */, musicDevice,
-1 /* a2dpVolume */);
+ mmi.putInt("musicDevice", musicDevice);
} else {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"APM handleDeviceConfigChange success for A2DP device addr="
+ address + " codec=" + a2dpCodec).printLog(TAG));
}
}
+ mmi.record();
}
/*package*/ void onMakeA2dpDeviceUnavailableNow(String address, int a2dpCodec) {
@@ -399,6 +442,8 @@
/*package*/ void onReportNewRoutes() {
int n = mRoutesObservers.beginBroadcast();
if (n > 0) {
+ new MediaMetrics.Item(mAnalyticsId + "onReportNewRoutes")
+ .putInt("routesObservers", n).record();
AudioRoutesInfo routes;
synchronized (mCurAudioRoutes) {
routes = new AudioRoutesInfo(mCurAudioRoutes);
@@ -428,16 +473,24 @@
AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
AudioService.sDeviceLogger.log(new AudioServiceEvents.WiredDevConnectEvent(wdcs));
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId
+ + "onSetWiredDeviceConnectionState")
+ .putInt("wdcs.mState", wdcs.mState)
+ .putInt("wdcs.mType", wdcs.mType);
+
synchronized (mDevicesLock) {
if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
&& DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
mDeviceBroker.setBluetoothA2dpOnInt(true,
"onSetWiredDeviceConnectionState state DISCONNECTED");
+ mmi.putInt("setBluetoothA2dpOnInt", 1);
}
if (!handleDeviceConnection(wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED,
wdcs.mType, wdcs.mAddress, wdcs.mName)) {
// change of connection state failed, bailout
+ mmi.putString(mAnalyticsPropEarlyReturn, "change of connection state failed")
+ .record();
return;
}
if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
@@ -446,22 +499,30 @@
"onSetWiredDeviceConnectionState state not DISCONNECTED");
}
mDeviceBroker.checkMusicActive(wdcs.mType, wdcs.mCaller);
+ mmi.putInt("setBluetoothA2dpOnInt", 0);
}
if (wdcs.mType == AudioSystem.DEVICE_OUT_HDMI) {
mDeviceBroker.checkVolumeCecOnHdmiConnection(wdcs.mState, wdcs.mCaller);
}
sendDeviceConnectionIntent(wdcs.mType, wdcs.mState, wdcs.mAddress, wdcs.mName);
updateAudioRoutes(wdcs.mType, wdcs.mState);
+
+ mmi.putString("wdcs.mAddress", wdcs.mAddress != null ? wdcs.mAddress : "")
+ .putString("wdcs.mName", wdcs.mName != null ? wdcs.mName : "")
+ .record();
}
}
/*package*/ void onToggleHdmi() {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "onToggleHdmi");
synchronized (mDevicesLock) {
// Is HDMI connected?
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
final DeviceInfo di = mConnectedDevices.get(key);
+ mmi.putString("key", key);
if (di == null) {
Log.e(TAG, "invalid null DeviceInfo in onToggleHdmi");
+ mmi.putString(mAnalyticsPropEarlyReturn, "invalid null DeviceInfo").record();
return;
}
// Toggle HDMI to retrigger broadcast with proper formats.
@@ -472,6 +533,7 @@
AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
"android"); // reconnect
}
+ mmi.record();
}
/*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDeviceAttributes device) {
@@ -535,6 +597,11 @@
+ Integer.toHexString(device) + " address:" + address
+ " name:" + deviceName + ")");
}
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "handleDeviceConnection")
+ .putInt("connect", connect ? 1 : 0)
+ .putInt("device", device)
+ .putString("address", address != null ? address : "")
+ .putString("deviceName", deviceName != null ? deviceName : "");
synchronized (mDevicesLock) {
final String deviceKey = DeviceInfo.makeDeviceListKey(device, address);
if (AudioService.DEBUG_DEVICES) {
@@ -545,6 +612,8 @@
if (AudioService.DEBUG_DEVICES) {
Slog.i(TAG, "deviceInfo:" + di + " is(already)Connected:" + isConnected);
}
+ mmi.putString("deviceKey", deviceKey)
+ .putInt("isConnected", isConnected ? 1 : 0);
if (connect && !isConnected) {
final int res = mAudioSystem.setDeviceConnectionState(device,
AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
@@ -552,11 +621,14 @@
if (res != AudioSystem.AUDIO_STATUS_OK) {
Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device)
+ " due to command error " + res);
+ mmi.putInt("command error", res)
+ .putInt("result", 0).record();
return false;
}
mConnectedDevices.put(deviceKey, new DeviceInfo(
device, deviceName, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+ mmi.putInt("result", 1).record();
return true;
} else if (!connect && isConnected) {
mAudioSystem.setDeviceConnectionState(device,
@@ -564,11 +636,13 @@
AudioSystem.AUDIO_FORMAT_DEFAULT);
// always remove even if disconnection failed
mConnectedDevices.remove(deviceKey);
+ mmi.putInt("result", 1).record();
return true;
}
Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey
+ ", deviceSpec=" + di + ", connect=" + connect);
}
+ mmi.putInt("result", 0).record();
return false;
}
@@ -582,6 +656,8 @@
toRemove.add(deviceInfo.mDeviceAddress);
}
});
+ new MediaMetrics.Item(mAnalyticsId + "disconnectA2dp")
+ .putInt("toRemove.size", toRemove.size()).record();
if (toRemove.size() > 0) {
final int delay = checkSendBecomingNoisyIntentInt(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
@@ -602,6 +678,8 @@
toRemove.add(deviceInfo.mDeviceAddress);
}
});
+ new MediaMetrics.Item(mAnalyticsId + "disconnectA2dpSink")
+ .putInt("toRemove.size", toRemove.size()).record();
toRemove.stream().forEach(deviceAddress -> makeA2dpSrcUnavailable(deviceAddress));
}
}
@@ -615,6 +693,8 @@
toRemove.add(deviceInfo.mDeviceAddress);
}
});
+ new MediaMetrics.Item(mAnalyticsId + "disconnectHearingAid")
+ .putInt("toRemove.size", toRemove.size()).record();
if (toRemove.size() > 0) {
final int delay = checkSendBecomingNoisyIntentInt(
AudioSystem.DEVICE_OUT_HEARING_AID, 0, AudioSystem.DEVICE_NONE);
@@ -771,18 +851,27 @@
@GuardedBy("mDevicesLock")
private void makeA2dpDeviceUnavailableNow(String address, int a2dpCodec) {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId
+ + "makeA2dpDeviceUnavailableNow")
+ .putInt("a2dpCodec", a2dpCodec);
if (address == null) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "address null").record();
return;
}
final String deviceToRemoveKey =
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
+ mmi.putString("address", address)
+ .putString("deviceToRemoveKey", deviceToRemoveKey);
+
mConnectedDevices.remove(deviceToRemoveKey);
if (!deviceToRemoveKey
.equals(mApmConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP))) {
// 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.putString(mAnalyticsPropEarlyReturn, "A2DP device made unavailable, was not used")
+ .record();
return;
}
@@ -804,6 +893,7 @@
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null);
+ mmi.record();
}
@GuardedBy("mDevicesLock")
@@ -873,6 +963,8 @@
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
// Remove Hearing Aid routes as well
setCurrentAudioRouteNameIfPossible(null);
+ new MediaMetrics.Item(mAnalyticsId + "makeHearingAidDeviceUnavailable")
+ .putString("address", address != null ? address : "").record();
}
@GuardedBy("mDevicesLock")
@@ -919,10 +1011,17 @@
@GuardedBy("mDevicesLock")
private int checkSendBecomingNoisyIntentInt(int device,
@AudioService.ConnectionState int state, int musicDevice) {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId
+ + "checkSendBecomingNoisyIntentInt")
+ .putInt("device", device)
+ .putInt("state", state)
+ .putInt("musicDevice", musicDevice);
if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "CONNECTION_STATE_DISCONNECTED").record();
return 0;
}
if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "doesn't contains device").record();
return 0;
}
int delay = 0;
@@ -950,12 +1049,14 @@
// the pausing of some apps that are playing remotely
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"dropping ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
+ mmi.putString(mAnalyticsPropEarlyReturn, "no media playback").record();
return 0;
}
mDeviceBroker.postBroadcastBecomingNoisy();
delay = AudioService.BECOMING_NOISY_DELAY_MS;
}
+ mmi.putInt("delay", delay).record();
return delay;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 600277c..3fd6f8f 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -88,6 +88,7 @@
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;
@@ -1884,6 +1885,15 @@
sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
direction, 0 /*ignored*/,
extVolCtlr, 0 /*delay*/);
+
+ new MediaMetrics.Item(mAnalyticsId + "adjustSuggestedStreamVolume")
+ .setUid(Binder.getCallingUid())
+ .putInt("extVolCtlr", extVolCtlr != null ? 1 : 0)
+ .putInt("direction", direction)
+ .putInt("flags", flags)
+ .putString("callingPackage", callingPackage)
+ .putString("caller", caller)
+ .record();
} else {
adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
caller, Binder.getCallingUid());
@@ -1970,12 +1980,22 @@
if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
+ ", flags=" + flags + ", caller=" + caller);
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "adjustStreamVolume")
+ .setUid(uid)
+ .setPid(Binder.getCallingPid())
+ .putInt("streamType", streamType)
+ .putInt("direction", direction)
+ .putInt("flags", flags)
+ .putString("callingPackage", callingPackage)
+ .putString("caller", caller);
+
ensureValidDirection(direction);
ensureValidStreamType(streamType);
boolean isMuteAdjust = isMuteAdjust(direction);
if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "isMuteAdjust").record();
return;
}
@@ -1989,6 +2009,7 @@
!= PackageManager.PERMISSION_GRANTED) {
Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ mmi.putString(mAnalyticsPropEarlyReturn, "Permission Denial").record();
return;
}
@@ -2020,6 +2041,7 @@
// is not an a2dp device
if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
&& (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "skip a2dp").record();
return;
}
@@ -2030,6 +2052,7 @@
}
if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "mode not allowed").record();
return;
}
@@ -2140,6 +2163,15 @@
0,
streamState,
0);
+
+ mmi.putInt("device", device)
+ .putInt("streamType2", streamState.mStreamType)
+ .putInt("isMuted", streamState.mIsMuted ? 1 : 0)
+ .putInt("indexMin", streamState.mIndexMin)
+ .putInt("indexMax", streamState.mIndexMax)
+ .putInt("observedDevices", streamState.mObservedDevices)
+ .putInt("flags2", flags)
+ .putInt("streamTypeAlias", streamTypeAlias);
}
int newIndex = mStreamStates[streamType].getIndex(device);
@@ -2153,6 +2185,7 @@
+ newIndex + "stream=" + streamType);
}
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
+ mmi.putInt("postSetAvrcpAbsoluteVolumeIndex", newIndex / 10);
}
// Check if volume update should be send to Hearing Aid
@@ -2198,6 +2231,7 @@
try {
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, true);
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, false);
+ mmi.putInt("HDMI.sendVolumeKeyEvent", keyCode);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2211,6 +2245,7 @@
}
}
}
+ mmi.record();
int index = mStreamStates[streamType].getIndex(device);
sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
@@ -2850,6 +2885,14 @@
}
}
mVolumeController.postVolumeChanged(streamType, flags);
+
+ new MediaMetrics.Item(mAnalyticsId + "sendVolumeUpdate")
+ .putInt("streamType", streamType)
+ .putInt("oldIndex", oldIndex)
+ .putInt("index", index)
+ .putInt("flags", flags)
+ .putInt("device", device)
+ .record();
}
// If Hdmi-CEC system audio mode is on and we are a TV panel, never show volume bar.
@@ -2891,12 +2934,21 @@
int device,
boolean force,
String caller) {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "setStreamVolumeInt")
+ .putInt("streamType", streamType)
+ .putInt("index", index)
+ .putInt("device", device)
+ .putInt("force", force ? 1 : 0)
+ .putString("caller", caller);
+
if (isFullVolumeDevice(device)) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "mFullVolumeDevices");
return;
}
VolumeStreamState streamState = mStreamStates[streamType];
if (streamState.setIndex(index, device, caller) || force) {
+ mmi.putInt("sendMsg", 1);
// Post message to set system volume (it in turn will post a message
// to persist).
sendMsg(mAudioHandler,
@@ -2907,6 +2959,7 @@
streamState,
0);
}
+ mmi.record();
}
private void setSystemAudioMute(boolean state) {
@@ -3141,22 +3194,34 @@
if (uid == android.os.Process.SYSTEM_UID) {
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
}
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "setMicrophoneMute")
+ .setUid(uid)
+ .putInt("userId", userId)
+ .putString("callingPackage", callingPackage);
+
// If OP_MUTE_MICROPHONE is set, disallow unmuting.
if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "disallow unmuting").record();
return;
}
if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "!checkAudioSettingsPermission").record();
return;
}
if (userId != UserHandle.getCallingUserId() &&
mContext.checkCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "permission").record();
return;
}
mMicMuteFromApi = on;
+
setMicrophoneMuteNoCallerCheck(userId);
+
+ mmi.putInt("mMicMuteFromApi", mMicMuteFromApi ? 1 : 0)
+ .record();
}
/** @see AudioManager#setMicrophoneMuteFromSwitch(boolean) */
@@ -3167,6 +3232,10 @@
return;
}
mMicMuteFromSwitch = on;
+ new MediaMetrics.Item(mAnalyticsId + "setMicrophoneMuteFromSwitch")
+ .setUid(userId)
+ .putInt("mMicMuteFromSwitch", mMicMuteFromSwitch ? 1 : 0)
+ .record();
setMicrophoneMuteNoCallerCheck(userId);
}
@@ -3174,6 +3243,9 @@
InputManager im = mContext.getSystemService(InputManager.class);
final int isMicMuted = im.isMicMuted();
if (isMicMuted != InputManager.SWITCH_STATE_UNKNOWN) {
+ new MediaMetrics.Item(mAnalyticsId + "setMicMuteFromSwitchInput")
+ .putInt("isMicMuted", isMicMuted)
+ .record();
setMicrophoneMuteFromSwitch(im.isMicMuted() != InputManager.SWITCH_STATE_OFF);
}
}
@@ -3207,6 +3279,14 @@
Log.e(TAG, "Error changing mic mute state to " + muted + " current:"
+ mMicMuteFromSystemCached);
}
+
+ new MediaMetrics.Item(mAnalyticsId + "setMicrophoneMuteNoCallerCheck")
+ .setUid(userId)
+ .putInt("muted", muted ? 1 : 0)
+ .putInt("currentMute", mMicMuteFromSystemCached ? 1 : 0)
+ .putLong("identity", identity)
+ .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
@@ -3326,6 +3406,13 @@
synchronized (mSettingsLock) {
final int ringerModeInternal = getRingerModeInternal();
final int ringerModeExternal = getRingerModeExternal();
+ new MediaMetrics.Item(mAnalyticsId + "setRingerMode")
+ .putInt("ringerMode", ringerMode)
+ .putInt("external", external ? 1 : 0)
+ .putString("caller", caller)
+ .putInt("ringerModeInternal", ringerModeInternal)
+ .putInt("ringerModeExternal", ringerModeExternal)
+ .record();
if (external) {
setRingerModeExt(ringerMode);
if (mRingerModeDelegate != null) {
@@ -3839,6 +3926,10 @@
Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
return;
}
+ new MediaMetrics.Item(mAnalyticsId + "playSoundEffectVolume")
+ .putInt("effectType", effectType)
+ .putDouble("volume", volume)
+ .record();
sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
effectType, (int) (volume * 1000), null, 0);
@@ -3851,7 +3942,12 @@
public boolean loadSoundEffects() {
LoadSoundEffectReply reply = new LoadSoundEffectReply();
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
- return reply.waitForLoaded(3 /*attempts*/);
+
+ boolean loaded = reply.waitForLoaded(3 /*attempts*/);
+ new MediaMetrics.Item(mAnalyticsId + "loadSoundEffects")
+ .putInt("loaded", loaded ? 1 : 0)
+ .record();
+ return loaded;
}
/**
@@ -3860,6 +3956,8 @@
*/
protected void scheduleLoadSoundEffects() {
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
+ new MediaMetrics.Item(mAnalyticsId + "scheduleLoadSoundEffects")
+ .record();
}
/**
@@ -3869,6 +3967,8 @@
*/
public void unloadSoundEffects() {
sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
+ new MediaMetrics.Item(mAnalyticsId + "unloadSoundEffects")
+ .record();
}
/** @see AudioManager#reloadAudioSettings() */
@@ -3941,10 +4041,19 @@
}
// 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(mAnalyticsId + "setSpeakerphoneOn")
+ .setUid(uid)
+ .setPid(pid)
+ .putInt("on", on ? 1 : 0)
+ .putInt("stateChanged", stateChanged ? 1 : 0)
+ .record();
+
if (stateChanged) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -3975,9 +4084,17 @@
}
// 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(mAnalyticsId + "setBluetoothScoOn")
+ .setUid(uid)
+ .setPid(pid)
+ .putInt("on", on ? 1 : 0)
+ .record();
mDeviceBroker.setBluetoothScoOn(on, eventSource);
}
@@ -3993,9 +4110,18 @@
/** @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(mAnalyticsId + "setBluetoothA2dpOn")
+ .setUid(uid)
+ .setPid(pid)
+ .putInt("on", on ? 1 : 0)
+ .record();
+
mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
}
@@ -4006,31 +4132,52 @@
/** @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(mAnalyticsId + "startBluetoothSco")
+ .setUid(uid)
+ .setPid(pid)
+ .putInt("scoAudioMode", 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(mAnalyticsId + "startBluetoothScoVirtualCall")
+ .setUid(uid)
+ .setPid(pid)
+ .record();
startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
}
void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
+ MediaMetrics.Item mmi = new MediaMetrics.Item(mAnalyticsId + "startBluetoothScoInt")
+ .putInt("scoAudioMode", scoAudioMode);
+
if (!checkAudioSettingsPermission("startBluetoothSco()") ||
!mSystemReady) {
+ mmi.putString(mAnalyticsPropEarlyReturn, "permission or systemReady").record();
return;
}
synchronized (mDeviceBroker.mSetModeLock) {
mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
}
+ mmi.record();
}
/** @see AudioManager#stopBluetoothSco() */
@@ -4039,12 +4186,18 @@
!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(mAnalyticsId + "stopBluetoothSco")
+ .setUid(uid)
+ .setPid(pid)
+ .record();
}
@@ -4806,6 +4959,13 @@
&& state != CONNECTION_STATE_DISCONNECTED) {
throw new IllegalArgumentException("Invalid state " + state);
}
+ new MediaMetrics.Item(mAnalyticsId + "setWiredDeviceConnectionState")
+ .putInt("type", type)
+ .putInt("state", state)
+ .putString("address", address)
+ .putString("name", name)
+ .putString("caller", caller)
+ .record();
mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
}
@@ -6477,22 +6637,41 @@
Log.e(TAG, "Invalid null parameter to request audio focus");
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
+ int uid = Binder.getCallingUid();
+ new MediaMetrics.Item(mAnalyticsId + "requestAudioFocus")
+ .setUid(uid)
+ .putInt("durationHint", durationHint)
+ .putString("clientId", clientId)
+ .putString("callingPackage", callingPackageName)
+ .putInt("flags", flags)
+ .putInt("sdk", sdk)
+ .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(mAnalyticsId + "abandonAudioFocus")
+ .putString("clientId", clientId)
+ .putString("callingPackage", callingPackageName);
+
if (aa != null && !isValidAudioAttributesUsage(aa)) {
Log.w(TAG, "Request using unsupported usage.");
+ mmi.putString(mAnalyticsPropEarlyReturn, "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(mAnalyticsId + "unregisterAudioFocusClient")
+ .putString("clientId", clientId)
+ .record();
mMediaFocusControl.unregisterAudioFocusClient(clientId);
}
@@ -7066,6 +7245,12 @@
}
}
+ /**
+ * Audio Analytics ids.
+ */
+ private static final String mAnalyticsId = "audio.service.";
+ private static final String mAnalyticsPropEarlyReturn = "earlyReturn";
+
private static String safeMediaVolumeStateToString(int state) {
switch(state) {
case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index add620e..5fdc3e4 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -19,6 +19,7 @@
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
+import android.media.MediaMetrics;
import com.android.server.audio.AudioDeviceInventory.WiredDeviceConnectionState;
@@ -108,6 +109,11 @@
final String mGroupName;
final AudioAttributes mAudioAttributes;
+ /**
+ * Audio Analytics unique Id.
+ */
+ private static final String mAnalyticsIdRoot = "audio.volumeEvent.";
+
/** used for VOL_ADJUST_VOL_UID,
* VOL_ADJUST_SUGG_VOL,
* VOL_ADJUST_STREAM_VOL,
@@ -120,6 +126,13 @@
mCaller = caller;
mGroupName = null;
mAudioAttributes = null;
+
+ new MediaMetrics.Item(mAnalyticsIdRoot + mStream)
+ .putInt("op", mOp)
+ .putInt("dir", mVal1)
+ .putInt("flags", mVal2)
+ .putString("from", mCaller)
+ .record();
}
/** used for VOL_SET_HEARING_AID_VOL*/
@@ -132,6 +145,12 @@
mCaller = null;
mGroupName = null;
mAudioAttributes = null;
+
+ new MediaMetrics.Item(mAnalyticsIdRoot + "HA")
+ .putInt("op", mOp)
+ .putInt("index", mVal1)
+ .putInt("gainDb", mVal2)
+ .record();
}
/** used for VOL_SET_AVRCP_VOL */
@@ -144,6 +163,11 @@
mCaller = null;
mGroupName = null;
mAudioAttributes = null;
+
+ new MediaMetrics.Item(mAnalyticsIdRoot + "AVRCP")
+ .putInt("op", mOp)
+ .putInt("index", mVal1)
+ .record();
}
/** used for VOL_VOICE_ACTIVITY_HEARING_AID */
@@ -156,6 +180,12 @@
mCaller = null;
mGroupName = null;
mAudioAttributes = null;
+
+ new MediaMetrics.Item(mAnalyticsIdRoot + mStream)
+ .putInt("op", mOp)
+ .putInt("index", mVal1)
+ .putInt("voiceActive", mVal2)
+ .record();
}
/** used for VOL_MODE_CHANGE_HEARING_AID */
@@ -179,6 +209,12 @@
mCaller = caller;
mGroupName = group;
mAudioAttributes = aa;
+
+ new MediaMetrics.Item(mAnalyticsIdRoot + mStream)
+ .putInt("op", mOp)
+ .putInt("index", mVal1)
+ .putInt("mode", mVal2)
+ .record();
}
@Override