From 585c555cc99e3f71cef2f6a1ee09407fe227993d Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Wed, 23 Nov 2022 08:51:27 +0000 Subject: 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 --- .../voiceinteraction/HotwordAudioStreamCopier.java | 269 +++++++++++++++++++++ .../HotwordAudioStreamManager.java | 261 -------------------- .../HotwordDetectionConnection.java | 10 +- .../TrustedHotwordDetectorSession.java | 10 +- 4 files changed, 279 insertions(+), 271 deletions(-) create mode 100644 services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java delete mode 100644 services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java new file mode 100644 index 000000000000..76574542da4f --- /dev/null +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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; + +import android.annotation.NonNull; +import android.app.AppOpsManager; +import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; +import android.service.voice.HotwordAudioStream; +import android.service.voice.HotwordDetectedResult; +import android.util.Slog; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * 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 = "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-"; + 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 int mVoiceInteractorUid; + private final String mVoiceInteractorPackageName; + private final String mVoiceInteractorAttributionTag; + private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); + + HotwordAudioStreamCopier(@NonNull AppOpsManager appOpsManager, + int voiceInteractorUid, @NonNull String voiceInteractorPackageName, + @NonNull String voiceInteractorAttributionTag) { + mAppOpsManager = appOpsManager; + mVoiceInteractorUid = voiceInteractorUid; + mVoiceInteractorPackageName = voiceInteractorPackageName; + mVoiceInteractorAttributionTag = voiceInteractorAttributionTag; + } + + /** + * Starts copying the audio streams in the given {@link HotwordDetectedResult}. + *

+ * 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 HotwordAudioStreamCopier}. The + * returned value should be passed on to the client (i.e., the voice interactor). + *

+ * + * @throws IOException If there was an error creating the managed pipe. + */ + @NonNull + public HotwordDetectedResult startCopyingAudioStreams(@NonNull HotwordDetectedResult result) + throws IOException { + List audioStreams = result.getAudioStreams(); + if (audioStreams.isEmpty()) { + return result; + } + + List newAudioStreams = new ArrayList<>(audioStreams.size()); + List copyTaskInfos = new ArrayList<>(audioStreams.size()); + for (HotwordAudioStream audioStream : audioStreams) { + ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe(); + ParcelFileDescriptor clientAudioSource = clientPipe[0]; + ParcelFileDescriptor clientAudioSink = clientPipe[1]; + HotwordAudioStream newAudioStream = + audioStream.buildUpon().setAudioStreamParcelFileDescriptor( + 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(); + copyTaskInfos.add(new CopyTaskInfo(serviceAudioSource, clientAudioSink, + copyBufferLength)); + } + + String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); + 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 mCopyTaskInfos; + private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); + + HotwordDetectedResultCopyTask(String resultTaskId, List copyTaskInfos) { + mResultTaskId = resultTaskId; + mCopyTaskInfos = copyTaskInfos; + } + + @Override + public void run() { + Thread.currentThread().setName(THREAD_NAME_PREFIX + mResultTaskId); + int size = mCopyTaskInfos.size(); + List tasks = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + CopyTaskInfo copyTaskInfo = mCopyTaskInfos.get(i); + String streamTaskId = mResultTaskId + "@" + i; + tasks.add(new SingleAudioStreamCopyTask(streamTaskId, copyTaskInfo.mSource, + copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength)); + } + + if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { + try { + // TODO(b/244599891): Set timeout, close after inactivity + mExecutorService.invokeAll(tasks); + } catch (InterruptedException e) { + Slog.e(TAG, mResultTaskId + ": Task was interrupted", e); + bestEffortPropagateError(e.getMessage()); + } finally { + mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag); + } + } else { + bestEffortPropagateError( + "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with" + + " uid=" + mVoiceInteractorUid + + " packageName=" + mVoiceInteractorPackageName + + " attributionTag=" + mVoiceInteractorAttributionTag); + } + } + + private void bestEffortPropagateError(@NonNull String errorMessage) { + try { + for (CopyTaskInfo copyTaskInfo : mCopyTaskInfos) { + copyTaskInfo.mSource.closeWithError(errorMessage); + copyTaskInfo.mSink.closeWithError(errorMessage); + } + } catch (IOException e) { + Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e); + } + } + } + + private static class SingleAudioStreamCopyTask implements Callable { + private final String mStreamTaskId; + private final ParcelFileDescriptor mAudioSource; + private final ParcelFileDescriptor mAudioSink; + private final int mCopyBufferLength; + + SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource, + ParcelFileDescriptor audioSink, int copyBufferLength) { + mStreamTaskId = streamTaskId; + mAudioSource = audioSource; + mAudioSink = audioSink; + mCopyBufferLength = copyBufferLength; + } + + @Override + public Void call() throws Exception { + Thread.currentThread().setName(THREAD_NAME_PREFIX + mStreamTaskId); + + // Note: We are intentionally NOT using try-with-resources here. If we did, + // the ParcelFileDescriptors will be automatically closed WITHOUT errors before we go + // into the IOException-catch block. We want to propagate the error while closing the + // PFDs. + InputStream fis = null; + OutputStream fos = null; + try { + fis = new ParcelFileDescriptor.AutoCloseInputStream(mAudioSource); + fos = new ParcelFileDescriptor.AutoCloseOutputStream(mAudioSink); + byte[] buffer = new byte[mCopyBufferLength]; + while (true) { + if (Thread.interrupted()) { + Slog.e(TAG, + mStreamTaskId + ": SingleAudioStreamCopyTask task was interrupted"); + break; + } + + int bytesRead = fis.read(buffer); + if (bytesRead < 0) { + Slog.i(TAG, mStreamTaskId + ": Reached end of audio stream"); + break; + } + if (bytesRead > 0) { + if (DEBUG) { + // TODO(b/244599440): Add proper logging + Slog.d(TAG, mStreamTaskId + ": Copied " + bytesRead + + " bytes from audio stream. First 20 bytes=" + Arrays.toString( + Arrays.copyOfRange(buffer, 0, 20))); + } + fos.write(buffer, 0, bytesRead); + } + // TODO(b/244599891): Close PFDs after inactivity + } + } catch (IOException e) { + mAudioSource.closeWithError(e.getMessage()); + mAudioSink.closeWithError(e.getMessage()); + Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e); + } finally { + if (fis != null) { + fis.close(); + } + if (fos != null) { + fos.close(); + } + } + + return null; + } + } + +} diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java deleted file mode 100644 index 57fabcc169a6..000000000000 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -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; - -import android.annotation.NonNull; -import android.app.AppOpsManager; -import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; -import android.service.voice.HotwordAudioStream; -import android.service.voice.HotwordDetectedResult; -import android.util.Slog; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -final class HotwordAudioStreamManager { - - private static final String TAG = "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 int mVoiceInteractorUid; - private final String mVoiceInteractorPackageName; - private final String mVoiceInteractorAttributionTag; - private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - - HotwordAudioStreamManager(@NonNull AppOpsManager appOpsManager, - int voiceInteractorUid, @NonNull String voiceInteractorPackageName, - @NonNull String voiceInteractorAttributionTag) { - mAppOpsManager = appOpsManager; - mVoiceInteractorUid = voiceInteractorUid; - mVoiceInteractorPackageName = voiceInteractorPackageName; - mVoiceInteractorAttributionTag = voiceInteractorAttributionTag; - } - - /** - * Starts copying the audio streams in the given {@link HotwordDetectedResult}. - *

- * 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 - * returned value should be passed on to the client (i.e., the voice interactor). - *

- * - * @throws IOException If there was an error creating the managed pipe. - */ - @NonNull - public HotwordDetectedResult startCopyingAudioStreams(@NonNull HotwordDetectedResult result) - throws IOException { - List audioStreams = result.getAudioStreams(); - if (audioStreams.isEmpty()) { - return result; - } - - List newAudioStreams = new ArrayList<>(audioStreams.size()); - List copyTaskInfos = new ArrayList<>(audioStreams.size()); - for (HotwordAudioStream audioStream : audioStreams) { - ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe(); - ParcelFileDescriptor clientAudioSource = clientPipe[0]; - ParcelFileDescriptor clientAudioSink = clientPipe[1]; - HotwordAudioStream newAudioStream = - audioStream.buildUpon().setAudioStreamParcelFileDescriptor( - 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(); - copyTaskInfos.add(new CopyTaskInfo(serviceAudioSource, clientAudioSink, - copyBufferLength)); - } - - String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); - 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 mCopyTaskInfos; - private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - - HotwordDetectedResultCopyTask(String resultTaskId, List copyTaskInfos) { - mResultTaskId = resultTaskId; - mCopyTaskInfos = copyTaskInfos; - } - - @Override - public void run() { - Thread.currentThread().setName(THREAD_NAME_PREFIX + mResultTaskId); - int size = mCopyTaskInfos.size(); - List tasks = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - CopyTaskInfo copyTaskInfo = mCopyTaskInfos.get(i); - String streamTaskId = mResultTaskId + "@" + i; - tasks.add(new SingleAudioStreamCopyTask(streamTaskId, copyTaskInfo.mSource, - copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength)); - } - - if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorUid, mVoiceInteractorPackageName, - mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { - try { - // TODO(b/244599891): Set timeout, close after inactivity - mExecutorService.invokeAll(tasks); - } catch (InterruptedException e) { - Slog.e(TAG, mResultTaskId + ": Task was interrupted", e); - bestEffortPropagateError(e.getMessage()); - } finally { - mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorUid, mVoiceInteractorPackageName, - mVoiceInteractorAttributionTag); - } - } else { - bestEffortPropagateError( - "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with" - + " uid=" + mVoiceInteractorUid - + " packageName=" + mVoiceInteractorPackageName - + " attributionTag=" + mVoiceInteractorAttributionTag); - } - } - - private void bestEffortPropagateError(@NonNull String errorMessage) { - try { - for (CopyTaskInfo copyTaskInfo : mCopyTaskInfos) { - copyTaskInfo.mSource.closeWithError(errorMessage); - copyTaskInfo.mSink.closeWithError(errorMessage); - } - } catch (IOException e) { - Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e); - } - } - } - - private static class SingleAudioStreamCopyTask implements Callable { - private final String mStreamTaskId; - private final ParcelFileDescriptor mAudioSource; - private final ParcelFileDescriptor mAudioSink; - private final int mCopyBufferLength; - - SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource, - ParcelFileDescriptor audioSink, int copyBufferLength) { - mStreamTaskId = streamTaskId; - mAudioSource = audioSource; - mAudioSink = audioSink; - mCopyBufferLength = copyBufferLength; - } - - @Override - public Void call() throws Exception { - Thread.currentThread().setName(THREAD_NAME_PREFIX + mStreamTaskId); - - // Note: We are intentionally NOT using try-with-resources here. If we did, - // the ParcelFileDescriptors will be automatically closed WITHOUT errors before we go - // into the IOException-catch block. We want to propagate the error while closing the - // PFDs. - InputStream fis = null; - OutputStream fos = null; - try { - fis = new ParcelFileDescriptor.AutoCloseInputStream(mAudioSource); - fos = new ParcelFileDescriptor.AutoCloseOutputStream(mAudioSink); - byte[] buffer = new byte[mCopyBufferLength]; - while (true) { - if (Thread.interrupted()) { - Slog.e(TAG, - mStreamTaskId + ": SingleAudioStreamCopyTask task was interrupted"); - break; - } - - int bytesRead = fis.read(buffer); - if (bytesRead < 0) { - Slog.i(TAG, mStreamTaskId + ": Reached end of audio stream"); - break; - } - if (bytesRead > 0) { - if (DEBUG) { - // TODO(b/244599440): Add proper logging - Slog.d(TAG, mStreamTaskId + ": Copied " + bytesRead - + " bytes from audio stream. First 20 bytes=" + Arrays.toString( - Arrays.copyOfRange(buffer, 0, 20))); - } - fos.write(buffer, 0, bytesRead); - } - // TODO(b/244599891): Close PFDs after inactivity - } - } catch (IOException e) { - mAudioSource.closeWithError(e.getMessage()); - mAudioSink.closeWithError(e.getMessage()); - Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e); - } finally { - if (fis != null) { - fis.close(); - } - if (fos != null) { - fos.close(); - } - } - - return null; - } - } - -} diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 9903481cb360..3bcba6c1af65 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 9d451f4e6247..eeafe910e13e 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 -- cgit v1.2.3-59-g8ed1b