Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 633e182f authored by Mark Punzalan's avatar Mark Punzalan Committed by Android (Google) Code Review
Browse files

Merge changes I48279bba,I3baf29a5

* changes:
  Populate data sizes in audio egress metrics
  Hotword: Use new Audio Egress metrics instead of older one
parents f5f7dd1f 0059e51a
Loading
Loading
Loading
Loading
+69 −32
Original line number Diff line number Diff line
@@ -19,13 +19,13 @@ package com.android.server.voiceinteraction;
import static android.app.AppOpsManager.MODE_ALLOWED;
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_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_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_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_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_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_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__CLOSE_ERROR_FROM_SYSTEM;
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_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ENDED;
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_AUDIO_EGRESS_EVENT_REPORTED__EVENT__INTERRUPTED_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__NO_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED;
import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG;

import android.annotation.NonNull;
@@ -98,14 +98,17 @@ final class HotwordAudioStreamCopier {
            throws IOException {
        List<HotwordAudioStream> audioStreams = result.getAudioStreams();
        if (audioStreams.isEmpty()) {
            HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                    HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST,
                    mVoiceInteractorUid);
            HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                    HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__EMPTY_AUDIO_STREAM_LIST,
                    mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
                    /* streamCount= */ 0);
            return result;
        }

        final int audioStreamCount = audioStreams.size();
        List<HotwordAudioStream> newAudioStreams = new ArrayList<>(audioStreams.size());
        List<CopyTaskInfo> copyTaskInfos = new ArrayList<>(audioStreams.size());
        int totalMetadataBundleSizeBytes = 0;
        for (HotwordAudioStream audioStream : audioStreams) {
            ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe();
            ParcelFileDescriptor clientAudioSource = clientPipe[0];
@@ -117,12 +120,14 @@ final class HotwordAudioStreamCopier {

            int copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES;
            PersistableBundle metadata = audioStream.getMetadata();
            totalMetadataBundleSizeBytes += HotwordDetectedResult.getParcelableSize(metadata);
            if (metadata.containsKey(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES)) {
                copyBufferLength = metadata.getInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, -1);
                if (copyBufferLength < 1 || copyBufferLength > MAX_COPY_BUFFER_LENGTH_BYTES) {
                    HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                            HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE,
                            mVoiceInteractorUid);
                    HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                            HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ILLEGAL_COPY_BUFFER_SIZE,
                            mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
                            audioStreamCount);
                    Slog.w(TAG, "Attempted to set an invalid copy buffer length ("
                            + copyBufferLength + ") for: " + audioStream);
                    copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES;
@@ -139,7 +144,9 @@ final class HotwordAudioStreamCopier {
        }

        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();
    }
@@ -159,11 +166,14 @@ final class HotwordAudioStreamCopier {
    private class HotwordDetectedResultCopyTask implements Runnable {
        private final String mResultTaskId;
        private final List<CopyTaskInfo> mCopyTaskInfos;
        private final int mTotalMetadataSizeBytes;
        private final ExecutorService mExecutorService = Executors.newCachedThreadPool();

        HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos) {
        HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos,
                int totalMetadataSizeBytes) {
            mResultTaskId = resultTaskId;
            mCopyTaskInfos = copyTaskInfos;
            mTotalMetadataSizeBytes = totalMetadataSizeBytes;
        }

        @Override
@@ -183,18 +193,38 @@ final class HotwordAudioStreamCopier {
                    mVoiceInteractorUid, mVoiceInteractorPackageName,
                    mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) {
                try {
                    HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                            HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START,
                            mVoiceInteractorUid);
                    HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                            HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED,
                            mVoiceInteractorUid, /* streamSizeBytes= */ 0, mTotalMetadataSizeBytes,
                            size);
                    // TODO(b/244599891): Set timeout, close after inactivity
                    mExecutorService.invokeAll(tasks);
                    HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                            HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END, mVoiceInteractorUid);

                    int totalStreamSizeBytes = 0;
                    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) {
                    HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                            HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION,
                            mVoiceInteractorUid);
                    Slog.e(TAG, mResultTaskId + ": Task was interrupted", e);
                    int totalStreamSizeBytes = 0;
                    for (SingleAudioStreamCopyTask task : tasks) {
                        totalStreamSizeBytes += task.mTotalCopiedBytes;
                    }

                    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());
                } finally {
                    mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD,
@@ -202,9 +232,10 @@ final class HotwordAudioStreamCopier {
                            mVoiceInteractorAttributionTag);
                }
            } else {
                HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                        HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION,
                        mVoiceInteractorUid);
                HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                        HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__NO_PERMISSION,
                        mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
                        size);
                bestEffortPropagateError(
                        "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with"
                                + " uid=" + mVoiceInteractorUid
@@ -219,9 +250,10 @@ final class HotwordAudioStreamCopier {
                    copyTaskInfo.mSource.closeWithError(errorMessage);
                    copyTaskInfo.mSink.closeWithError(errorMessage);
                }
                HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                        HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM,
                        mVoiceInteractorUid);
                HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                        HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__CLOSE_ERROR_FROM_SYSTEM,
                        mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
                        mCopyTaskInfos.size());
            } catch (IOException e) {
                Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e);
            }
@@ -237,6 +269,8 @@ final class HotwordAudioStreamCopier {
        private final int mDetectorType;
        private final int mUid;

        private volatile int mTotalCopiedBytes = 0;

        SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource,
                ParcelFileDescriptor audioSink, int copyBufferLength, int detectorType, int uid) {
            mStreamTaskId = streamTaskId;
@@ -281,6 +315,7 @@ final class HotwordAudioStreamCopier {
                                    Arrays.copyOfRange(buffer, 0, 20)));
                        }
                        fos.write(buffer, 0, bytesRead);
                        mTotalCopiedBytes += bytesRead;
                    }
                    // TODO(b/244599891): Close PFDs after inactivity
                }
@@ -288,8 +323,10 @@ final class HotwordAudioStreamCopier {
                mAudioSource.closeWithError(e.getMessage());
                mAudioSink.closeWithError(e.getMessage());
                Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e);
                HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
                        HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, mUid);
                HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType,
                        HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__CLOSE_ERROR_FROM_SYSTEM,
                        mUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0,
                        /* streamCount= */ 0);
            } finally {
                if (fis != null) {
                    fis.close();
+30 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

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__TRUSTED_DETECTOR_DSP;
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;
    private static final int METRICS_INIT_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() {
        // Class only contains static utility functions, and should not be instantiated
@@ -97,6 +106,16 @@ public final class HotwordMetricsLogger {
                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) {
        switch (detectorType) {
            case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE:
@@ -151,4 +170,15 @@ public final class HotwordMetricsLogger {
                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;
        }
    }
}