Merge "Close audio source after getting callback from HotwordDetectionService" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-05-05 10:00:56 +00:00
committed by Android (Google) Code Review
2 changed files with 27 additions and 67 deletions

View File

@@ -270,14 +270,9 @@ final class HotwordDetectionConnection {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "startListeningFromExternalSource"); Slog.d(TAG, "startListeningFromExternalSource");
} }
handleExternalSourceHotwordDetection(
ParcelFileDescriptor.AutoCloseInputStream audioReader = audioStream,
new ParcelFileDescriptor.AutoCloseInputStream(audioStream);
handleSoftwareHotwordDetection(
audioFormat, audioFormat,
AudioReader.createFromInputStream(audioReader),
AUDIO_SOURCE_EXTERNAL,
options, options,
callback); callback);
} }
@@ -556,14 +551,18 @@ final class HotwordDetectionConnection {
} }
} }
private void handleSoftwareHotwordDetection( private void handleExternalSourceHotwordDetection(
ParcelFileDescriptor audioStream,
AudioFormat audioFormat, AudioFormat audioFormat,
AudioReader audioSource,
int audioSourceValue,
@Nullable PersistableBundle options, @Nullable PersistableBundle options,
IMicrophoneHotwordDetectionVoiceInteractionCallback callback) { IMicrophoneHotwordDetectionVoiceInteractionCallback callback) {
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe(); if (DEBUG) {
Slog.d(TAG, "#handleExternalSourceHotwordDetection");
}
AudioReader audioSource = AudioReader.createFromInputStream(
new ParcelFileDescriptor.AutoCloseInputStream(audioStream));
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
if (clientPipe == null) { if (clientPipe == null) {
// TODO: Need to propagate as unknown error or something? // TODO: Need to propagate as unknown error or something?
return; return;
@@ -579,8 +578,8 @@ final class HotwordDetectionConnection {
try (AudioReader source = audioSource; try (AudioReader source = audioSource;
OutputStream fos = OutputStream fos =
new ParcelFileDescriptor.AutoCloseOutputStream(serviceAudioSink)) { new ParcelFileDescriptor.AutoCloseOutputStream(serviceAudioSink)) {
byte[] buffer = new byte[1024];
byte[] buffer = new byte[1024];
while (true) { while (true) {
int bytesRead = source.read(buffer, 0, 1024); int bytesRead = source.read(buffer, 0, 1024);
@@ -608,76 +607,32 @@ final class HotwordDetectionConnection {
service -> service.detectFromMicrophoneSource( service -> service.detectFromMicrophoneSource(
serviceAudioSource, serviceAudioSource,
// TODO: consider making a proxy callback + copy of audio format // TODO: consider making a proxy callback + copy of audio format
audioSourceValue, audioFormat, options, AUDIO_SOURCE_EXTERNAL,
audioFormat,
options,
new IDspHotwordDetectionCallback.Stub() { new IDspHotwordDetectionCallback.Stub() {
@Override @Override
public void onRejected(@Nullable HotwordRejectedResult result) public void onRejected(@Nullable HotwordRejectedResult result)
throws RemoteException { throws RemoteException {
bestEffortClose(serviceAudioSink);
bestEffortClose(serviceAudioSource);
bestEffortClose(audioSource);
// TODO: Propagate the HotwordRejectedResult. // TODO: Propagate the HotwordRejectedResult.
} }
@Override @Override
public void onDetected(@Nullable HotwordDetectedResult triggerResult) public void onDetected(@Nullable HotwordDetectedResult triggerResult)
throws RemoteException { throws RemoteException {
// Stop
bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSink);
bestEffortClose(serviceAudioSource);
if (audioSourceValue == AUDIO_SOURCE_EXTERNAL) {
callback.onDetected(triggerResult, null, null);
// TODO: Add a delay before closing.
bestEffortClose(audioSource);
}
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe =
createPipe();
if (clientPipe == null) {
// Error.
// Need to propagate as unknown error or something?
return;
}
ParcelFileDescriptor callbackAudioSink = clientPipe.second;
ParcelFileDescriptor callbackClientRead = clientPipe.first;
mAudioCopyExecutor.execute(() -> {
try (AudioReader source = audioSource;
OutputStream fos =
new ParcelFileDescriptor.AutoCloseOutputStream(
callbackAudioSink)) {
// TODO: get ring buffer suffix here
// fos.write(lastSeveralSeconds);
byte[] buffer = new byte[1024];
while (true) {
int bytesRead = source.read(buffer, 0, 1024);
if (bytesRead < 0) {
break;
}
fos.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
Slog.w(TAG, "Failed supplying audio data to validator", e);
} finally {
synchronized (mLock) {
mCurrentAudioSink = null;
}
}
});
// TODO: noteOp here. // TODO: noteOp here.
// Remove hotword offset from trigger result callback.onDetected(triggerResult, null /* audioFormat */,
// TODO: consider propagating only capture session. null /* audioStream */);
callback.onDetected(triggerResult, null, callbackClientRead);
// TODO: Add a delay before closing. // TODO: Add a delay before closing.
bestEffortClose(callbackClientRead); bestEffortClose(audioSource);
} }
})); }));
// TODO: verify this is the right thing to do here.
bestEffortClose(serviceAudioSource);
} }
private static void bestEffortClose(Closeable closeable) { private static void bestEffortClose(Closeable closeable) {

View File

@@ -477,6 +477,11 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return; return;
} }
if (audioStream == null) {
Slog.w(TAG, "External source is null for hotword detector");
throw new IllegalStateException("External source is null for hotword detector");
}
mHotwordDetectionConnection mHotwordDetectionConnection
.startListeningFromExternalSource(audioStream, audioFormat, options, callback); .startListeningFromExternalSource(audioStream, audioFormat, options, callback);
} }