From 3959b354c5435470bd29731a949ae552b1a21e39 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Tue, 22 Nov 2022 23:26:19 +0000 Subject: [PATCH 1/3] Allow setting buffer length for HotwordAudioStreamManager A HotwordDetectionService can specify a buffer length for each HotwordAudioStream in the HotwordDetectedResult by adding an int in the HotwordAudioStream's metadata PersistableBundle, with the key HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES. If the value is not specified or is an invalid value, the default buffer length is 2,560 bytes. Bug: 257509629 Test: Manually with test app, verified with logs Test: atest CtsVoiceInteractionTestCases Change-Id: I28c7f21bdf7c00b62c9cc6c29153d79ce9d85286 --- core/api/system-current.txt | 1 + .../service/voice/HotwordAudioStream.java | 19 ++++- .../HotwordAudioStreamManager.java | 77 ++++++++++++------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index eac990d671cd5..711281fcfc573 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -12219,6 +12219,7 @@ package android.service.voice { method @Nullable public android.media.AudioTimestamp getTimestamp(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES = "android.service.voice.key.AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES"; } public static final class HotwordAudioStream.Builder { diff --git a/core/java/android/service/voice/HotwordAudioStream.java b/core/java/android/service/voice/HotwordAudioStream.java index 1c57700d38e15..6ae952c045cb9 100644 --- a/core/java/android/service/voice/HotwordAudioStream.java +++ b/core/java/android/service/voice/HotwordAudioStream.java @@ -46,6 +46,21 @@ import java.util.Objects; @SystemApi public final class HotwordAudioStream implements Parcelable { + /** + * Key for int value to be read from {@link #getMetadata()}. The value is read by the system and + * is the length (in bytes) of the byte buffers created to copy bytes in the + * {@link #getAudioStreamParcelFileDescriptor()} written by the {@link HotwordDetectionService}. + * The buffer length should be chosen such that no additional latency is introduced. Typically, + * this should be at least the size of byte chunks written by the + * {@link HotwordDetectionService}. + * + *

If no value specified in the metadata for the buffer length, or if the value is less than + * 1, or if it is greater than 65,536, or if it is not an int, the default value of 2,560 will + * be used.

+ */ + public static final String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES = + "android.service.voice.key.AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES"; + /** * The {@link AudioFormat} of the audio stream. */ @@ -414,10 +429,10 @@ public final class HotwordAudioStream implements Parcelable { } @DataClass.Generated( - time = 1669184301563L, + time = 1669916341034L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/service/voice/HotwordAudioStream.java", - inputSignatures = "private final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull android.os.ParcelFileDescriptor mAudioStreamParcelFileDescriptor\nprivate final @android.annotation.Nullable android.media.AudioTimestamp mTimestamp\nprivate final @android.annotation.NonNull android.os.PersistableBundle mMetadata\nprivate static android.media.AudioTimestamp defaultTimestamp()\nprivate static android.os.PersistableBundle defaultMetadata()\npublic android.service.voice.HotwordAudioStream.Builder buildUpon()\nclass HotwordAudioStream extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genParcelable=true, genToString=true)") + inputSignatures = "public static final java.lang.String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull android.os.ParcelFileDescriptor mAudioStreamParcelFileDescriptor\nprivate final @android.annotation.Nullable android.media.AudioTimestamp mTimestamp\nprivate final @android.annotation.NonNull android.os.PersistableBundle mMetadata\nprivate static android.media.AudioTimestamp defaultTimestamp()\nprivate static android.os.PersistableBundle defaultMetadata()\npublic android.service.voice.HotwordAudioStream.Builder buildUpon()\nclass HotwordAudioStream extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genParcelable=true, genToString=true)") @Deprecated private void __metadata() {} diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java index d5eea1f3ff355..5ce388c97261c 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java @@ -17,6 +17,7 @@ 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.server.voiceinteraction.HotwordDetectionConnection.DEBUG; @@ -24,9 +25,9 @@ import android.annotation.NonNull; import android.app.AppOpsManager; import android.media.permission.Identity; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.service.voice.HotwordAudioStream; import android.service.voice.HotwordDetectedResult; -import android.util.Pair; import android.util.Slog; import java.io.IOException; @@ -45,6 +46,10 @@ final class HotwordAudioStreamManager { private static final String OP_MESSAGE = "Streaming hotword audio to VoiceInteractionService"; private static final String TASK_ID_PREFIX = "HotwordDetectedResult@"; private static final String THREAD_NAME_PREFIX = "Copy-"; + private static final int DEFAULT_COPY_BUFFER_LENGTH_BYTES = 2_560; + + // Corresponds to the OS pipe capacity in bytes + private static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536; private final AppOpsManager mAppOpsManager; private final Identity mVoiceInteractorIdentity; @@ -76,8 +81,7 @@ final class HotwordAudioStreamManager { } List newAudioStreams = new ArrayList<>(audioStreams.size()); - List> sourcesAndSinks = new ArrayList<>( - audioStreams.size()); + List copyTaskInfos = new ArrayList<>(audioStreams.size()); for (HotwordAudioStream audioStream : audioStreams) { ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe(); ParcelFileDescriptor clientAudioSource = clientPipe[0]; @@ -87,41 +91,64 @@ final class HotwordAudioStreamManager { clientAudioSource).build(); newAudioStreams.add(newAudioStream); + int copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; + PersistableBundle metadata = audioStream.getMetadata(); + 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) { + Slog.w(TAG, "Attempted to set an invalid copy buffer length (" + + copyBufferLength + ") for: " + audioStream); + copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; + } else if (DEBUG) { + Slog.i(TAG, "Copy buffer length set to " + copyBufferLength + " for: " + + audioStream); + } + } + ParcelFileDescriptor serviceAudioSource = audioStream.getAudioStreamParcelFileDescriptor(); - sourcesAndSinks.add(new Pair<>(serviceAudioSource, clientAudioSink)); + copyTaskInfos.add(new CopyTaskInfo(serviceAudioSource, clientAudioSink, + copyBufferLength)); } String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); - mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, sourcesAndSinks)); + mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, copyTaskInfos)); return result.buildUpon().setAudioStreams(newAudioStreams).build(); } + private static class CopyTaskInfo { + private final ParcelFileDescriptor mSource; + private final ParcelFileDescriptor mSink; + private final int mCopyBufferLength; + + CopyTaskInfo(ParcelFileDescriptor source, ParcelFileDescriptor sink, int copyBufferLength) { + mSource = source; + mSink = sink; + mCopyBufferLength = copyBufferLength; + } + } + private class HotwordDetectedResultCopyTask implements Runnable { private final String mResultTaskId; - private final List> mSourcesAndSinks; + private final List mCopyTaskInfos; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - HotwordDetectedResultCopyTask(String resultTaskId, - List> sourcesAndSinks) { + HotwordDetectedResultCopyTask(String resultTaskId, List copyTaskInfos) { mResultTaskId = resultTaskId; - mSourcesAndSinks = sourcesAndSinks; + mCopyTaskInfos = copyTaskInfos; } @Override public void run() { Thread.currentThread().setName(THREAD_NAME_PREFIX + mResultTaskId); - int size = mSourcesAndSinks.size(); + int size = mCopyTaskInfos.size(); List tasks = new ArrayList<>(size); for (int i = 0; i < size; i++) { - Pair sourceAndSink = - mSourcesAndSinks.get(i); - ParcelFileDescriptor serviceAudioSource = sourceAndSink.first; - ParcelFileDescriptor clientAudioSink = sourceAndSink.second; + CopyTaskInfo copyTaskInfo = mCopyTaskInfos.get(i); String streamTaskId = mResultTaskId + "@" + i; - tasks.add(new SingleAudioStreamCopyTask(streamTaskId, serviceAudioSource, - clientAudioSink)); + tasks.add(new SingleAudioStreamCopyTask(streamTaskId, copyTaskInfo.mSource, + copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength)); } if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, @@ -148,12 +175,9 @@ final class HotwordAudioStreamManager { private void bestEffortPropagateError(@NonNull String errorMessage) { try { - for (Pair sourceAndSink : - mSourcesAndSinks) { - ParcelFileDescriptor serviceAudioSource = sourceAndSink.first; - ParcelFileDescriptor clientAudioSink = sourceAndSink.second; - serviceAudioSource.closeWithError(errorMessage); - clientAudioSink.closeWithError(errorMessage); + for (CopyTaskInfo copyTaskInfo : mCopyTaskInfos) { + copyTaskInfo.mSource.closeWithError(errorMessage); + copyTaskInfo.mSink.closeWithError(errorMessage); } } catch (IOException e) { Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e); @@ -162,18 +186,17 @@ final class HotwordAudioStreamManager { } private static class SingleAudioStreamCopyTask implements Callable { - // TODO: Make this buffer size customizable from updateState() - private static final int COPY_BUFFER_LENGTH = 2_560; - private final String mStreamTaskId; private final ParcelFileDescriptor mAudioSource; private final ParcelFileDescriptor mAudioSink; + private final int mCopyBufferLength; SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource, - ParcelFileDescriptor audioSink) { + ParcelFileDescriptor audioSink, int copyBufferLength) { mStreamTaskId = streamTaskId; mAudioSource = audioSource; mAudioSink = audioSink; + mCopyBufferLength = copyBufferLength; } @Override @@ -189,7 +212,7 @@ final class HotwordAudioStreamManager { try { fis = new ParcelFileDescriptor.AutoCloseInputStream(mAudioSource); fos = new ParcelFileDescriptor.AutoCloseOutputStream(mAudioSink); - byte[] buffer = new byte[COPY_BUFFER_LENGTH]; + byte[] buffer = new byte[mCopyBufferLength]; while (true) { if (Thread.interrupted()) { Slog.e(TAG, From 2e6c85187e5b47d4fa459c71ba80722a1d5d34e6 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Wed, 23 Nov 2022 00:45:32 +0000 Subject: [PATCH 2/3] Remove dependency on Identity in HotwordAudioStreamManager android.media.permission.Identity is not needed for AppOpsManager calls and is an unnecessary coupling. Bug: 258323047 Test: None with this change; pure refactoring Change-Id: I1c70f95a73e36c2793e87116b426d55ce359b74b --- .../HotwordAudioStreamManager.java | 27 +++++++++++-------- .../HotwordDetectionConnection.java | 3 ++- .../TrustedHotwordDetectorSession.java | 3 ++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java index 5ce388c97261c..57fabcc169a61 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java @@ -23,7 +23,6 @@ import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEB import android.annotation.NonNull; import android.app.AppOpsManager; -import android.media.permission.Identity; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.service.voice.HotwordAudioStream; @@ -52,13 +51,18 @@ final class HotwordAudioStreamManager { private static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536; private final AppOpsManager mAppOpsManager; - private final Identity mVoiceInteractorIdentity; + private final int mVoiceInteractorUid; + private final String mVoiceInteractorPackageName; + private final String mVoiceInteractorAttributionTag; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); HotwordAudioStreamManager(@NonNull AppOpsManager appOpsManager, - @NonNull Identity voiceInteractorIdentity) { + int voiceInteractorUid, @NonNull String voiceInteractorPackageName, + @NonNull String voiceInteractorAttributionTag) { mAppOpsManager = appOpsManager; - mVoiceInteractorIdentity = voiceInteractorIdentity; + mVoiceInteractorUid = voiceInteractorUid; + mVoiceInteractorPackageName = voiceInteractorPackageName; + mVoiceInteractorAttributionTag = voiceInteractorAttributionTag; } /** @@ -152,8 +156,8 @@ final class HotwordAudioStreamManager { } if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, - mVoiceInteractorIdentity.attributionTag, OP_MESSAGE) == MODE_ALLOWED) { + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { try { // TODO(b/244599891): Set timeout, close after inactivity mExecutorService.invokeAll(tasks); @@ -162,14 +166,15 @@ final class HotwordAudioStreamManager { bestEffortPropagateError(e.getMessage()); } finally { mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, - mVoiceInteractorIdentity.attributionTag); + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag); } } else { bestEffortPropagateError( - "Failed to obtain RECORD_AUDIO_HOTWORD permission for " - + SoundTriggerSessionPermissionsDecorator.toString( - mVoiceInteractorIdentity)); + "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with" + + " uid=" + mVoiceInteractorUid + + " packageName=" + mVoiceInteractorPackageName + + " attributionTag=" + mVoiceInteractorAttributionTag); } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 4151663285197..9903481cb360d 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -246,7 +246,8 @@ final class HotwordDetectionConnection { mVoiceInteractorIdentity = voiceInteractorIdentity; mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager, - mVoiceInteractorIdentity); + mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, + mVoiceInteractorIdentity.attributionTag); mDetectionComponentName = serviceName; mUser = userId; mCallback = callback; diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java index b87b8f790338e..9d451f4e62475 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java @@ -246,7 +246,8 @@ final class TrustedHotwordDetectorSession { mVoiceInteractorIdentity = voiceInteractorIdentity; mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager, - mVoiceInteractorIdentity); + mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, + mVoiceInteractorIdentity.attributionTag); mDetectionComponentName = serviceName; mUser = userId; mCallback = callback; From 585c555cc99e3f71cef2f6a1ee09407fe227993d Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Wed, 23 Nov 2022 08:51:27 +0000 Subject: [PATCH 3/3] Rename HotwordAudioStreamManager and add Javadoc "Manager" is a little vague and "Copier" is clearer with the class's purpose. Bug: 258323047 Test: None with this change; simple refactoring Change-Id: I43a24b27983838e0ef9798eef2f45d1d4b1c9ac8 --- ...anager.java => HotwordAudioStreamCopier.java} | 16 ++++++++++++---- .../HotwordDetectionConnection.java | 10 +++++----- .../TrustedHotwordDetectorSession.java | 10 +++++----- 3 files changed, 22 insertions(+), 14 deletions(-) rename services/voiceinteraction/java/com/android/server/voiceinteraction/{HotwordAudioStreamManager.java => HotwordAudioStreamCopier.java} (95%) diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java similarity index 95% rename from services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java rename to services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java index 57fabcc169a61..76574542da4f8 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java @@ -39,9 +39,17 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -final class HotwordAudioStreamManager { +/** + * Copies the audio streams in {@link HotwordDetectedResult}s. This allows the system to manage the + * lifetime of the {@link ParcelFileDescriptor}s and ensures that the flow of data is in the right + * direction from the {@link android.service.voice.HotwordDetectionService} to the client (i.e., the + * voice interactor). + * + * @hide + */ +final class HotwordAudioStreamCopier { - private static final String TAG = "HotwordAudioStreamManager"; + private static final String TAG = "HotwordAudioStreamCopier"; private static final String OP_MESSAGE = "Streaming hotword audio to VoiceInteractionService"; private static final String TASK_ID_PREFIX = "HotwordDetectedResult@"; private static final String THREAD_NAME_PREFIX = "Copy-"; @@ -56,7 +64,7 @@ final class HotwordAudioStreamManager { private final String mVoiceInteractorAttributionTag; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - HotwordAudioStreamManager(@NonNull AppOpsManager appOpsManager, + HotwordAudioStreamCopier(@NonNull AppOpsManager appOpsManager, int voiceInteractorUid, @NonNull String voiceInteractorPackageName, @NonNull String voiceInteractorAttributionTag) { mAppOpsManager = appOpsManager; @@ -70,7 +78,7 @@ final class HotwordAudioStreamManager { *

* The returned {@link HotwordDetectedResult} is identical the one that was passed in, except * that the {@link ParcelFileDescriptor}s within {@link HotwordDetectedResult#getAudioStreams()} - * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamManager}. The + * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamCopier}. The * returned value should be passed on to the client (i.e., the voice interactor). *

* diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 9903481cb360d..3bcba6c1af654 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -183,7 +183,7 @@ final class HotwordDetectionConnection { private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final AppOpsManager mAppOpsManager; - private final HotwordAudioStreamManager mHotwordAudioStreamManager; + private final HotwordAudioStreamCopier mHotwordAudioStreamCopier; @Nullable private final ScheduledFuture mCancellationTaskFuture; private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; @@ -245,7 +245,7 @@ final class HotwordDetectionConnection { mVoiceInteractionServiceUid = voiceInteractionServiceUid; mVoiceInteractorIdentity = voiceInteractorIdentity; mAppOpsManager = mContext.getSystemService(AppOpsManager.class); - mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager, + mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, mVoiceInteractorIdentity.attributionTag); mDetectionComponentName = serviceName; @@ -507,7 +507,7 @@ final class HotwordDetectionConnection { saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event mSoftwareCallback.onError(); @@ -642,7 +642,7 @@ final class HotwordDetectionConnection { saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event externalCallback.onError(CALLBACK_ONDETECTED_STREAM_COPY_ERROR); @@ -1001,7 +1001,7 @@ final class HotwordDetectionConnection { HotwordDetectedResult newResult; try { newResult = - mHotwordAudioStreamManager.startCopyingAudioStreams( + mHotwordAudioStreamCopier.startCopyingAudioStreams( triggerResult); } catch (IOException e) { // TODO: Write event diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java index 9d451f4e62475..eeafe910e13e2 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java @@ -183,7 +183,7 @@ final class TrustedHotwordDetectorSession { private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final AppOpsManager mAppOpsManager; - private final HotwordAudioStreamManager mHotwordAudioStreamManager; + private final HotwordAudioStreamCopier mHotwordAudioStreamCopier; @Nullable private final ScheduledFuture mCancellationTaskFuture; private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; @@ -245,7 +245,7 @@ final class TrustedHotwordDetectorSession { mVoiceInteractionServiceUid = voiceInteractionServiceUid; mVoiceInteractorIdentity = voiceInteractorIdentity; mAppOpsManager = mContext.getSystemService(AppOpsManager.class); - mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager, + mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, mVoiceInteractorIdentity.attributionTag); mDetectionComponentName = serviceName; @@ -507,7 +507,7 @@ final class TrustedHotwordDetectorSession { saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event mSoftwareCallback.onError(); @@ -642,7 +642,7 @@ final class TrustedHotwordDetectorSession { saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event externalCallback.onError(CALLBACK_ONDETECTED_STREAM_COPY_ERROR); @@ -1001,7 +1001,7 @@ final class TrustedHotwordDetectorSession { HotwordDetectedResult newResult; try { newResult = - mHotwordAudioStreamManager.startCopyingAudioStreams( + mHotwordAudioStreamCopier.startCopyingAudioStreams( triggerResult); } catch (IOException e) { // TODO: Write event