Merge changes I48279bba,I3baf29a5 into tm-qpr-dev

* changes:
  Populate data sizes in audio egress metrics
  Hotword: Use new Audio Egress metrics instead of older one
This commit is contained in:
Ivan Chiang
2022-12-16 12:56:55 +00:00
committed by Android (Google) Code Review
2 changed files with 99 additions and 33 deletions

View File

@@ -19,13 +19,13 @@ package com.android.server.voiceinteraction;
import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.service.voice.HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES; import static android.service.voice.HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__CLOSE_ERROR_FROM_SYSTEM;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__EMPTY_AUDIO_STREAM_LIST;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ENDED;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ILLEGAL_COPY_BUFFER_SIZE;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__INTERRUPTED_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__NO_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED;
import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG; import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -98,14 +98,17 @@ final class HotwordAudioStreamCopier {
throws IOException { throws IOException {
List<HotwordAudioStream> audioStreams = result.getAudioStreams(); List<HotwordAudioStream> audioStreams = result.getAudioStreams();
if (audioStreams.isEmpty()) { if (audioStreams.isEmpty()) {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__EMPTY_AUDIO_STREAM_LIST,
mVoiceInteractorUid); mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
/* streamCount= */ 0);
return result; return result;
} }
final int audioStreamCount = audioStreams.size();
List<HotwordAudioStream> newAudioStreams = new ArrayList<>(audioStreams.size()); List<HotwordAudioStream> newAudioStreams = new ArrayList<>(audioStreams.size());
List<CopyTaskInfo> copyTaskInfos = new ArrayList<>(audioStreams.size()); List<CopyTaskInfo> copyTaskInfos = new ArrayList<>(audioStreams.size());
int totalMetadataBundleSizeBytes = 0;
for (HotwordAudioStream audioStream : audioStreams) { for (HotwordAudioStream audioStream : audioStreams) {
ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe(); ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe();
ParcelFileDescriptor clientAudioSource = clientPipe[0]; ParcelFileDescriptor clientAudioSource = clientPipe[0];
@@ -117,12 +120,14 @@ final class HotwordAudioStreamCopier {
int copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; int copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES;
PersistableBundle metadata = audioStream.getMetadata(); PersistableBundle metadata = audioStream.getMetadata();
totalMetadataBundleSizeBytes += HotwordDetectedResult.getParcelableSize(metadata);
if (metadata.containsKey(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES)) { if (metadata.containsKey(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES)) {
copyBufferLength = metadata.getInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, -1); copyBufferLength = metadata.getInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, -1);
if (copyBufferLength < 1 || copyBufferLength > MAX_COPY_BUFFER_LENGTH_BYTES) { if (copyBufferLength < 1 || copyBufferLength > MAX_COPY_BUFFER_LENGTH_BYTES) {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ILLEGAL_COPY_BUFFER_SIZE,
mVoiceInteractorUid); mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
audioStreamCount);
Slog.w(TAG, "Attempted to set an invalid copy buffer length (" Slog.w(TAG, "Attempted to set an invalid copy buffer length ("
+ copyBufferLength + ") for: " + audioStream); + copyBufferLength + ") for: " + audioStream);
copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES;
@@ -139,7 +144,9 @@ final class HotwordAudioStreamCopier {
} }
String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result);
mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, copyTaskInfos)); mExecutorService.execute(
new HotwordDetectedResultCopyTask(resultTaskId, copyTaskInfos,
totalMetadataBundleSizeBytes));
return result.buildUpon().setAudioStreams(newAudioStreams).build(); return result.buildUpon().setAudioStreams(newAudioStreams).build();
} }
@@ -159,11 +166,14 @@ final class HotwordAudioStreamCopier {
private class HotwordDetectedResultCopyTask implements Runnable { private class HotwordDetectedResultCopyTask implements Runnable {
private final String mResultTaskId; private final String mResultTaskId;
private final List<CopyTaskInfo> mCopyTaskInfos; private final List<CopyTaskInfo> mCopyTaskInfos;
private final int mTotalMetadataSizeBytes;
private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos) { HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos,
int totalMetadataSizeBytes) {
mResultTaskId = resultTaskId; mResultTaskId = resultTaskId;
mCopyTaskInfos = copyTaskInfos; mCopyTaskInfos = copyTaskInfos;
mTotalMetadataSizeBytes = totalMetadataSizeBytes;
} }
@Override @Override
@@ -183,19 +193,38 @@ final class HotwordAudioStreamCopier {
mVoiceInteractorUid, mVoiceInteractorPackageName, mVoiceInteractorUid, mVoiceInteractorPackageName,
mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) {
try { try {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED,
mVoiceInteractorUid); mVoiceInteractorUid, /* streamSizeBytes= */ 0, mTotalMetadataSizeBytes,
size);
// TODO(b/244599891): Set timeout, close after inactivity // TODO(b/244599891): Set timeout, close after inactivity
mExecutorService.invokeAll(tasks); mExecutorService.invokeAll(tasks);
HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END, int totalStreamSizeBytes = 0;
mVoiceInteractorUid); for (SingleAudioStreamCopyTask task : tasks) {
totalStreamSizeBytes += task.mTotalCopiedBytes;
}
Slog.i(TAG, mResultTaskId + ": Task was completed. Total bytes streamed: "
+ totalStreamSizeBytes + ", total metadata bundle size bytes: "
+ mTotalMetadataSizeBytes);
HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ENDED,
mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes,
size);
} catch (InterruptedException e) { } catch (InterruptedException e) {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, int totalStreamSizeBytes = 0;
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION, for (SingleAudioStreamCopyTask task : tasks) {
mVoiceInteractorUid); totalStreamSizeBytes += task.mTotalCopiedBytes;
Slog.e(TAG, mResultTaskId + ": Task was interrupted", e); }
HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__INTERRUPTED_EXCEPTION,
mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes,
size);
Slog.e(TAG, mResultTaskId + ": Task was interrupted. Total bytes streamed: "
+ totalStreamSizeBytes + ", total metadata bundle size bytes: "
+ mTotalMetadataSizeBytes);
bestEffortPropagateError(e.getMessage()); bestEffortPropagateError(e.getMessage());
} finally { } finally {
mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD,
@@ -203,9 +232,10 @@ final class HotwordAudioStreamCopier {
mVoiceInteractorAttributionTag); mVoiceInteractorAttributionTag);
} }
} else { } else {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__NO_PERMISSION,
mVoiceInteractorUid); mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
size);
bestEffortPropagateError( bestEffortPropagateError(
"Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with" "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with"
+ " uid=" + mVoiceInteractorUid + " uid=" + mVoiceInteractorUid
@@ -220,9 +250,10 @@ final class HotwordAudioStreamCopier {
copyTaskInfo.mSource.closeWithError(errorMessage); copyTaskInfo.mSource.closeWithError(errorMessage);
copyTaskInfo.mSink.closeWithError(errorMessage); copyTaskInfo.mSink.closeWithError(errorMessage);
} }
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__CLOSE_ERROR_FROM_SYSTEM,
mVoiceInteractorUid); mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
mCopyTaskInfos.size());
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e); Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e);
} }
@@ -237,6 +268,8 @@ final class HotwordAudioStreamCopier {
private final int mDetectorType; private final int mDetectorType;
private final int mUid; private final int mUid;
private volatile int mTotalCopiedBytes = 0;
SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource, SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource,
ParcelFileDescriptor audioSink, int copyBufferLength, int detectorType, int uid) { ParcelFileDescriptor audioSink, int copyBufferLength, int detectorType, int uid) {
mStreamTaskId = streamTaskId; mStreamTaskId = streamTaskId;
@@ -281,6 +314,7 @@ final class HotwordAudioStreamCopier {
Arrays.copyOfRange(buffer, 0, 20))); Arrays.copyOfRange(buffer, 0, 20)));
} }
fos.write(buffer, 0, bytesRead); fos.write(buffer, 0, bytesRead);
mTotalCopiedBytes += bytesRead;
} }
// TODO(b/244599891): Close PFDs after inactivity // TODO(b/244599891): Close PFDs after inactivity
} }
@@ -288,8 +322,10 @@ final class HotwordAudioStreamCopier {
mAudioSource.closeWithError(e.getMessage()); mAudioSource.closeWithError(e.getMessage());
mAudioSink.closeWithError(e.getMessage()); mAudioSink.closeWithError(e.getMessage());
Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e); Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e);
HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, mUid); HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__CLOSE_ERROR_FROM_SYSTEM,
mUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
/* streamCount= */ 0);
} finally { } finally {
if (fis != null) { if (fis != null) {
fis.close(); fis.close();

View File

@@ -16,6 +16,9 @@
package com.android.server.voiceinteraction; package com.android.server.voiceinteraction;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE;
@@ -47,6 +50,12 @@ public final class HotwordMetricsLogger {
HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP;
private static final int METRICS_INIT_NORMAL_DETECTOR = private static final int METRICS_INIT_NORMAL_DETECTOR =
HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR;
private static final int AUDIO_EGRESS_DSP_DETECTOR =
HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP;
private static final int AUDIO_EGRESS_SOFTWARE_DETECTOR =
HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE;
private static final int AUDIO_EGRESS_NORMAL_DETECTOR =
HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR;
private HotwordMetricsLogger() { private HotwordMetricsLogger() {
// Class only contains static utility functions, and should not be instantiated // Class only contains static utility functions, and should not be instantiated
@@ -97,6 +106,16 @@ public final class HotwordMetricsLogger {
metricsDetectorType, event, uid); metricsDetectorType, event, uid);
} }
/**
* Logs information related to hotword audio egress events.
*/
public static void writeAudioEgressEvent(int detectorType, int event, int uid,
int streamSizeBytes, int bundleSizeBytes, int streamCount) {
int metricsDetectorType = getAudioEgressDetectorType(detectorType);
FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED,
metricsDetectorType, event, uid, streamSizeBytes, bundleSizeBytes, streamCount);
}
private static int getCreateMetricsDetectorType(int detectorType) { private static int getCreateMetricsDetectorType(int detectorType) {
switch (detectorType) { switch (detectorType) {
case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE:
@@ -151,4 +170,15 @@ public final class HotwordMetricsLogger {
return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR; return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR;
} }
} }
private static int getAudioEgressDetectorType(int detectorType) {
switch (detectorType) {
case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE:
return AUDIO_EGRESS_SOFTWARE_DETECTOR;
case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP:
return AUDIO_EGRESS_DSP_DETECTOR;
default:
return AUDIO_EGRESS_NORMAL_DETECTOR;
}
}
} }