1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.audio; 18 19 import android.annotation.NonNull; 20 import android.media.AudioDeviceAttributes; 21 import android.media.AudioManager; 22 import android.media.AudioSystem; 23 import android.media.MediaMetrics; 24 25 import com.android.server.audio.AudioDeviceInventory.WiredDeviceConnectionState; 26 27 28 public class AudioServiceEvents { 29 30 final static class PhoneStateEvent extends AudioEventLogger.Event { 31 static final int MODE_SET = 0; 32 static final int MODE_IN_COMMUNICATION_TIMEOUT = 1; 33 34 final int mOp; 35 final String mPackage; 36 final int mOwnerPid; 37 final int mRequesterPid; 38 final int mRequestedMode; 39 final int mActualMode; 40 41 /** used for MODE_SET */ PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode, int ownerPid, int actualMode)42 PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode, 43 int ownerPid, int actualMode) { 44 mOp = MODE_SET; 45 mPackage = callingPackage; 46 mRequesterPid = requesterPid; 47 mRequestedMode = requestedMode; 48 mOwnerPid = ownerPid; 49 mActualMode = actualMode; 50 logMetricEvent(); 51 } 52 53 /** used for MODE_IN_COMMUNICATION_TIMEOUT */ PhoneStateEvent(String callingPackage, int ownerPid)54 PhoneStateEvent(String callingPackage, int ownerPid) { 55 mOp = MODE_IN_COMMUNICATION_TIMEOUT; 56 mPackage = callingPackage; 57 mOwnerPid = ownerPid; 58 mRequesterPid = 0; 59 mRequestedMode = 0; 60 mActualMode = 0; 61 logMetricEvent(); 62 } 63 64 @Override eventToString()65 public String eventToString() { 66 switch (mOp) { 67 case MODE_SET: 68 return new StringBuilder("setMode(") 69 .append(AudioSystem.modeToString(mRequestedMode)) 70 .append(") from package=").append(mPackage) 71 .append(" pid=").append(mRequesterPid) 72 .append(" selected mode=") 73 .append(AudioSystem.modeToString(mActualMode)) 74 .append(" by pid=").append(mOwnerPid).toString(); 75 case MODE_IN_COMMUNICATION_TIMEOUT: 76 return new StringBuilder("mode IN COMMUNICATION timeout") 77 .append(" for package=").append(mPackage) 78 .append(" pid=").append(mOwnerPid).toString(); 79 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString(); 80 } 81 } 82 83 /** 84 * Audio Analytics unique Id. 85 */ 86 private static final String mMetricsId = MediaMetrics.Name.AUDIO_MODE; 87 logMetricEvent()88 private void logMetricEvent() { 89 switch (mOp) { 90 case MODE_SET: 91 new MediaMetrics.Item(mMetricsId) 92 .set(MediaMetrics.Property.EVENT, "set") 93 .set(MediaMetrics.Property.REQUESTED_MODE, 94 AudioSystem.modeToString(mRequestedMode)) 95 .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mActualMode)) 96 .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage) 97 .record(); 98 return; 99 case MODE_IN_COMMUNICATION_TIMEOUT: 100 new MediaMetrics.Item(mMetricsId) 101 .set(MediaMetrics.Property.EVENT, "inCommunicationTimeout") 102 .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage) 103 .record(); 104 return; 105 default: return; 106 } 107 } 108 } 109 110 final static class WiredDevConnectEvent extends AudioEventLogger.Event { 111 final WiredDeviceConnectionState mState; 112 WiredDevConnectEvent(WiredDeviceConnectionState state)113 WiredDevConnectEvent(WiredDeviceConnectionState state) { 114 mState = state; 115 } 116 117 @Override eventToString()118 public String eventToString() { 119 return new StringBuilder("setWiredDeviceConnectionState(") 120 .append(" type:").append( 121 Integer.toHexString(mState.mAttributes.getInternalType())) 122 .append(" state:").append(AudioSystem.deviceStateToString(mState.mState)) 123 .append(" addr:").append(mState.mAttributes.getAddress()) 124 .append(" name:").append(mState.mAttributes.getName()) 125 .append(") from ").append(mState.mCaller).toString(); 126 } 127 } 128 129 final static class ForceUseEvent extends AudioEventLogger.Event { 130 final int mUsage; 131 final int mConfig; 132 final String mReason; 133 ForceUseEvent(int usage, int config, String reason)134 ForceUseEvent(int usage, int config, String reason) { 135 mUsage = usage; 136 mConfig = config; 137 mReason = reason; 138 } 139 140 @Override eventToString()141 public String eventToString() { 142 return new StringBuilder("setForceUse(") 143 .append(AudioSystem.forceUseUsageToString(mUsage)) 144 .append(", ").append(AudioSystem.forceUseConfigToString(mConfig)) 145 .append(") due to ").append(mReason).toString(); 146 } 147 } 148 149 static final class VolChangedBroadcastEvent extends AudioEventLogger.Event { 150 final int mStreamType; 151 final int mAliasStreamType; 152 final int mIndex; 153 VolChangedBroadcastEvent(int stream, int alias, int index)154 VolChangedBroadcastEvent(int stream, int alias, int index) { 155 mStreamType = stream; 156 mAliasStreamType = alias; 157 mIndex = index; 158 } 159 160 @Override eventToString()161 public String eventToString() { 162 return new StringBuilder("sending VOLUME_CHANGED stream:") 163 .append(AudioSystem.streamToString(mStreamType)) 164 .append(" index:").append(mIndex) 165 .append(" alias:").append(AudioSystem.streamToString(mAliasStreamType)) 166 .toString(); 167 } 168 } 169 170 static final class DeviceVolumeEvent extends AudioEventLogger.Event { 171 final int mStream; 172 final int mVolIndex; 173 final String mDeviceNativeType; 174 final String mDeviceAddress; 175 final String mCaller; 176 final int mDeviceForStream; 177 final boolean mSkipped; 178 DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device, int deviceForStream, String callingPackage, boolean skipped)179 DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device, 180 int deviceForStream, String callingPackage, boolean skipped) { 181 mStream = streamType; 182 mVolIndex = index; 183 mDeviceNativeType = "0x" + Integer.toHexString(device.getInternalType()); 184 mDeviceAddress = device.getAddress(); 185 mDeviceForStream = deviceForStream; 186 mCaller = callingPackage; 187 mSkipped = skipped; 188 // log metrics 189 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME_EVENT) 190 .set(MediaMetrics.Property.EVENT, "setDeviceVolume") 191 .set(MediaMetrics.Property.STREAM_TYPE, 192 AudioSystem.streamToString(mStream)) 193 .set(MediaMetrics.Property.INDEX, mVolIndex) 194 .set(MediaMetrics.Property.DEVICE, mDeviceNativeType) 195 .set(MediaMetrics.Property.ADDRESS, mDeviceAddress) 196 .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller) 197 .record(); 198 } 199 200 @Override eventToString()201 public String eventToString() { 202 final StringBuilder sb = new StringBuilder("setDeviceVolume(stream:") 203 .append(AudioSystem.streamToString(mStream)) 204 .append(" index:").append(mVolIndex) 205 .append(" device:").append(mDeviceNativeType) 206 .append(" addr:").append(mDeviceAddress) 207 .append(") from ").append(mCaller); 208 if (mSkipped) { 209 sb.append(" skipped [device in use]"); 210 } else { 211 sb.append(" currDevForStream:Ox").append(Integer.toHexString(mDeviceForStream)); 212 } 213 return sb.toString(); 214 } 215 } 216 217 final static class VolumeEvent extends AudioEventLogger.Event { 218 static final int VOL_ADJUST_SUGG_VOL = 0; 219 static final int VOL_ADJUST_STREAM_VOL = 1; 220 static final int VOL_SET_STREAM_VOL = 2; 221 static final int VOL_SET_HEARING_AID_VOL = 3; 222 static final int VOL_SET_AVRCP_VOL = 4; 223 static final int VOL_ADJUST_VOL_UID = 5; 224 static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6; 225 static final int VOL_MODE_CHANGE_HEARING_AID = 7; 226 static final int VOL_SET_GROUP_VOL = 8; 227 static final int VOL_MUTE_STREAM_INT = 9; 228 static final int VOL_SET_LE_AUDIO_VOL = 10; 229 static final int VOL_ADJUST_GROUP_VOL = 11; 230 231 final int mOp; 232 final int mStream; 233 final int mVal1; 234 final int mVal2; 235 final String mCaller; 236 final String mGroupName; 237 238 /** used for VOL_ADJUST_VOL_UID, 239 * VOL_ADJUST_SUGG_VOL, 240 * VOL_ADJUST_STREAM_VOL, 241 * VOL_SET_STREAM_VOL */ VolumeEvent(int op, int stream, int val1, int val2, String caller)242 VolumeEvent(int op, int stream, int val1, int val2, String caller) { 243 mOp = op; 244 mStream = stream; 245 mVal1 = val1; 246 mVal2 = val2; 247 mCaller = caller; 248 mGroupName = null; 249 logMetricEvent(); 250 } 251 252 /** used for VOL_SET_HEARING_AID_VOL*/ VolumeEvent(int op, int index, int gainDb)253 VolumeEvent(int op, int index, int gainDb) { 254 mOp = op; 255 mVal1 = index; 256 mVal2 = gainDb; 257 // unused 258 mStream = -1; 259 mCaller = null; 260 mGroupName = null; 261 logMetricEvent(); 262 } 263 264 /** used for VOL_SET_AVRCP_VOL */ VolumeEvent(int op, int index)265 VolumeEvent(int op, int index) { 266 mOp = op; 267 mVal1 = index; 268 // unused 269 mVal2 = 0; 270 mStream = -1; 271 mCaller = null; 272 mGroupName = null; 273 logMetricEvent(); 274 } 275 276 /** used for VOL_VOICE_ACTIVITY_HEARING_AID */ VolumeEvent(int op, boolean voiceActive, int stream, int index)277 VolumeEvent(int op, boolean voiceActive, int stream, int index) { 278 mOp = op; 279 mStream = stream; 280 mVal1 = index; 281 mVal2 = voiceActive ? 1 : 0; 282 // unused 283 mCaller = null; 284 mGroupName = null; 285 logMetricEvent(); 286 } 287 288 /** used for VOL_MODE_CHANGE_HEARING_AID */ VolumeEvent(int op, int mode, int stream, int index)289 VolumeEvent(int op, int mode, int stream, int index) { 290 mOp = op; 291 mStream = stream; 292 mVal1 = index; 293 mVal2 = mode; 294 // unused 295 mCaller = null; 296 mGroupName = null; 297 logMetricEvent(); 298 } 299 300 /** used for VOL_SET_GROUP_VOL, 301 * VOL_ADJUST_GROUP_VOL */ VolumeEvent(int op, String group, int index, int flags, String caller)302 VolumeEvent(int op, String group, int index, int flags, String caller) { 303 mOp = op; 304 mStream = -1; 305 mVal1 = index; 306 mVal2 = flags; 307 mCaller = caller; 308 mGroupName = group; 309 logMetricEvent(); 310 } 311 312 /** used for VOL_MUTE_STREAM_INT */ VolumeEvent(int op, int stream, boolean state)313 VolumeEvent(int op, int stream, boolean state) { 314 mOp = op; 315 mStream = stream; 316 mVal1 = state ? 1 : 0; 317 mVal2 = 0; 318 mCaller = null; 319 mGroupName = null; 320 logMetricEvent(); 321 } 322 323 324 /** 325 * Audio Analytics unique Id. 326 */ 327 private static final String mMetricsId = MediaMetrics.Name.AUDIO_VOLUME_EVENT; 328 329 /** 330 * Log mediametrics event 331 */ logMetricEvent()332 private void logMetricEvent() { 333 switch (mOp) { 334 case VOL_ADJUST_SUGG_VOL: 335 case VOL_ADJUST_VOL_UID: 336 case VOL_ADJUST_STREAM_VOL: { 337 String eventName; 338 switch (mOp) { 339 case VOL_ADJUST_SUGG_VOL: 340 eventName = "adjustSuggestedStreamVolume"; 341 break; 342 case VOL_ADJUST_STREAM_VOL: 343 eventName = "adjustStreamVolume"; 344 break; 345 case VOL_ADJUST_VOL_UID: 346 eventName = "adjustStreamVolumeForUid"; 347 break; 348 default: 349 return; // not possible, just return here 350 } 351 new MediaMetrics.Item(mMetricsId) 352 .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller) 353 .set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down") 354 .set(MediaMetrics.Property.EVENT, eventName) 355 .set(MediaMetrics.Property.FLAGS, mVal2) 356 .set(MediaMetrics.Property.STREAM_TYPE, 357 AudioSystem.streamToString(mStream)) 358 .record(); 359 return; 360 } 361 case VOL_ADJUST_GROUP_VOL: 362 new MediaMetrics.Item(mMetricsId) 363 .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller) 364 .set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down") 365 .set(MediaMetrics.Property.EVENT, "adjustVolumeGroupVolume") 366 .set(MediaMetrics.Property.FLAGS, mVal2) 367 .set(MediaMetrics.Property.GROUP, mGroupName) 368 .record(); 369 return; 370 case VOL_SET_STREAM_VOL: 371 new MediaMetrics.Item(mMetricsId) 372 .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller) 373 .set(MediaMetrics.Property.EVENT, "setStreamVolume") 374 .set(MediaMetrics.Property.FLAGS, mVal2) 375 .set(MediaMetrics.Property.INDEX, mVal1) 376 .set(MediaMetrics.Property.STREAM_TYPE, 377 AudioSystem.streamToString(mStream)) 378 .record(); 379 return; 380 case VOL_SET_HEARING_AID_VOL: 381 new MediaMetrics.Item(mMetricsId) 382 .set(MediaMetrics.Property.EVENT, "setHearingAidVolume") 383 .set(MediaMetrics.Property.GAIN_DB, (double) mVal2) 384 .set(MediaMetrics.Property.INDEX, mVal1) 385 .record(); 386 return; 387 case VOL_SET_LE_AUDIO_VOL: 388 new MediaMetrics.Item(mMetricsId) 389 .set(MediaMetrics.Property.EVENT, "setLeAudioVolume") 390 .set(MediaMetrics.Property.INDEX, mVal1) 391 .set(MediaMetrics.Property.MAX_INDEX, mVal2) 392 .record(); 393 return; 394 case VOL_SET_AVRCP_VOL: 395 new MediaMetrics.Item(mMetricsId) 396 .set(MediaMetrics.Property.EVENT, "setAvrcpVolume") 397 .set(MediaMetrics.Property.INDEX, mVal1) 398 .record(); 399 return; 400 case VOL_VOICE_ACTIVITY_HEARING_AID: 401 new MediaMetrics.Item(mMetricsId) 402 .set(MediaMetrics.Property.EVENT, "voiceActivityHearingAid") 403 .set(MediaMetrics.Property.INDEX, mVal1) 404 .set(MediaMetrics.Property.STATE, 405 mVal2 == 1 ? "active" : "inactive") 406 .set(MediaMetrics.Property.STREAM_TYPE, 407 AudioSystem.streamToString(mStream)) 408 .record(); 409 return; 410 case VOL_MODE_CHANGE_HEARING_AID: 411 new MediaMetrics.Item(mMetricsId) 412 .set(MediaMetrics.Property.EVENT, "modeChangeHearingAid") 413 .set(MediaMetrics.Property.INDEX, mVal1) 414 .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mVal2)) 415 .set(MediaMetrics.Property.STREAM_TYPE, 416 AudioSystem.streamToString(mStream)) 417 .record(); 418 return; 419 case VOL_SET_GROUP_VOL: 420 new MediaMetrics.Item(mMetricsId) 421 .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller) 422 .set(MediaMetrics.Property.EVENT, "setVolumeIndexForAttributes") 423 .set(MediaMetrics.Property.FLAGS, mVal2) 424 .set(MediaMetrics.Property.GROUP, mGroupName) 425 .set(MediaMetrics.Property.INDEX, mVal1) 426 .record(); 427 return; 428 case VOL_MUTE_STREAM_INT: 429 // No value in logging metrics for this internal event 430 return; 431 default: 432 return; 433 } 434 } 435 436 @Override eventToString()437 public String eventToString() { 438 switch (mOp) { 439 case VOL_ADJUST_SUGG_VOL: 440 return new StringBuilder("adjustSuggestedStreamVolume(sugg:") 441 .append(AudioSystem.streamToString(mStream)) 442 .append(" dir:").append(AudioManager.adjustToString(mVal1)) 443 .append(" flags:0x").append(Integer.toHexString(mVal2)) 444 .append(") from ").append(mCaller) 445 .toString(); 446 case VOL_ADJUST_GROUP_VOL: 447 return new StringBuilder("adjustVolumeGroupVolume(group:") 448 .append(mGroupName) 449 .append(" dir:").append(AudioManager.adjustToString(mVal1)) 450 .append(" flags:0x").append(Integer.toHexString(mVal2)) 451 .append(") from ").append(mCaller) 452 .toString(); 453 case VOL_ADJUST_STREAM_VOL: 454 return new StringBuilder("adjustStreamVolume(stream:") 455 .append(AudioSystem.streamToString(mStream)) 456 .append(" dir:").append(AudioManager.adjustToString(mVal1)) 457 .append(" flags:0x").append(Integer.toHexString(mVal2)) 458 .append(") from ").append(mCaller) 459 .toString(); 460 case VOL_SET_STREAM_VOL: 461 return new StringBuilder("setStreamVolume(stream:") 462 .append(AudioSystem.streamToString(mStream)) 463 .append(" index:").append(mVal1) 464 .append(" flags:0x").append(Integer.toHexString(mVal2)) 465 .append(") from ").append(mCaller) 466 .toString(); 467 case VOL_SET_HEARING_AID_VOL: 468 return new StringBuilder("setHearingAidVolume:") 469 .append(" index:").append(mVal1) 470 .append(" gain dB:").append(mVal2) 471 .toString(); 472 case VOL_SET_LE_AUDIO_VOL: 473 return new StringBuilder("setLeAudioVolume:") 474 .append(" index:").append(mVal1) 475 .append(" maxIndex:").append(mVal2) 476 .toString(); 477 case VOL_SET_AVRCP_VOL: 478 return new StringBuilder("setAvrcpVolume:") 479 .append(" index:").append(mVal1) 480 .toString(); 481 case VOL_ADJUST_VOL_UID: 482 return new StringBuilder("adjustStreamVolumeForUid(stream:") 483 .append(AudioSystem.streamToString(mStream)) 484 .append(" dir:").append(AudioManager.adjustToString(mVal1)) 485 .append(" flags:0x").append(Integer.toHexString(mVal2)) 486 .append(") from ").append(mCaller) 487 .toString(); 488 case VOL_VOICE_ACTIVITY_HEARING_AID: 489 return new StringBuilder("Voice activity change (") 490 .append(mVal2 == 1 ? "active" : "inactive") 491 .append(") causes setting HEARING_AID volume to idx:").append(mVal1) 492 .append(" stream:").append(AudioSystem.streamToString(mStream)) 493 .toString(); 494 case VOL_MODE_CHANGE_HEARING_AID: 495 return new StringBuilder("setMode(") 496 .append(AudioSystem.modeToString(mVal2)) 497 .append(") causes setting HEARING_AID volume to idx:").append(mVal1) 498 .append(" stream:").append(AudioSystem.streamToString(mStream)) 499 .toString(); 500 case VOL_SET_GROUP_VOL: 501 return new StringBuilder("setVolumeIndexForAttributes(group:") 502 .append(" group: ").append(mGroupName) 503 .append(" index:").append(mVal1) 504 .append(" flags:0x").append(Integer.toHexString(mVal2)) 505 .append(") from ").append(mCaller) 506 .toString(); 507 case VOL_MUTE_STREAM_INT: 508 return new StringBuilder("VolumeStreamState.muteInternally(stream:") 509 .append(AudioSystem.streamToString(mStream)) 510 .append(mVal1 == 1 ? ", muted)" : ", unmuted)") 511 .toString(); 512 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString(); 513 } 514 } 515 } 516 } 517