Notify VIS the detector callback remote exception occurred

It's possible the VIMS fails to notify client because of the IPC
exception error, some unknown reason that causes the binder object
may have problem to callback. We assume the system still have binders
that is available to use, we try to notify the client procrss not use
callback object.

If the system is in a bad state that cannot get any binder, we do not
have a good solution to resolve this case now. More details can be
found in go/b244391070. The RemoteException for VQS if not be
included in this change, we focus on the hotword part.

Bug: 244391070
Test: manual. Force to call the method to trigger call path. The
onError() callback is called.

Change-Id: I30186d7efdb14c9ef0c7ed65bc089b89199d2e16
This commit is contained in:
Joanne Chung
2023-02-10 19:11:08 +08:00
parent 27e03dfce3
commit 3eb525997c
11 changed files with 196 additions and 42 deletions

View File

@@ -77,6 +77,13 @@ abstract class AbstractDetector implements HotwordDetector {
mIsDetectorActive = new AtomicBoolean(true);
}
boolean isSameToken(IBinder token) {
if (token == null) {
return false;
}
return mToken == token;
}
/**
* Method to be called for the detector to ready/register itself with underlying system
* services.

View File

@@ -1707,6 +1707,13 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
}
}
void onDetectorRemoteException() {
Message.obtain(mHandler, MSG_DETECTION_ERROR,
new HotwordDetectionServiceFailure(
HotwordDetectionServiceFailure.ERROR_CODE_REMOTE_EXCEPTION,
"Detector remote exception occurs")).sendToTarget();
}
class MyHandler extends Handler {
MyHandler(@NonNull Looper looper) {
super(looper);

View File

@@ -32,4 +32,5 @@ oneway interface IVoiceInteractionService {
in IVoiceActionCheckCallback callback);
void prepareToShowSession(in Bundle args, int flags);
void showSessionFailed(in Bundle args);
void detectorRemoteExceptionOccurred(in IBinder token, int detectorType);
}

View File

@@ -77,6 +77,13 @@ class SoftwareHotwordDetector extends AbstractDetector {
DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE);
}
void onDetectorRemoteException() {
Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
mCallback.onFailure(new HotwordDetectionServiceFailure(
HotwordDetectionServiceFailure.ERROR_CODE_REMOTE_EXCEPTION,
"Detector remote exception occurs"))));
}
@RequiresPermission(RECORD_AUDIO)
@Override
public boolean startRecognition() throws IllegalDetectorStateException {

View File

@@ -36,8 +36,8 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.voice.KeyphraseModelManager;
import android.media.permission.Identity;
import android.media.voice.KeyphraseModelManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -180,6 +180,14 @@ public class VoiceInteractionService extends Service {
VoiceInteractionService::onShowSessionFailed,
VoiceInteractionService.this, args));
}
@Override
public void detectorRemoteExceptionOccurred(@NonNull IBinder token, int detectorType) {
Log.d(TAG, "detectorRemoteExceptionOccurred");
Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
VoiceInteractionService::onDetectorRemoteException,
VoiceInteractionService.this, token, detectorType));
}
};
IVoiceInteractionManagerService mSystemService;
@@ -192,6 +200,28 @@ public class VoiceInteractionService extends Service {
private final Set<HotwordDetector> mActiveDetectors = new ArraySet<>();
private void onDetectorRemoteException(@NonNull IBinder token, int detectorType) {
Log.d(TAG, "onDetectorRemoteException for " + HotwordDetector.detectorTypeToString(
detectorType));
mActiveDetectors.forEach(detector -> {
// TODO: handle normal detector, VQD
if (detectorType == HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP
&& detector instanceof AlwaysOnHotwordDetector) {
AlwaysOnHotwordDetector alwaysOnDetector = (AlwaysOnHotwordDetector) detector;
if (alwaysOnDetector.isSameToken(token)) {
alwaysOnDetector.onDetectorRemoteException();
}
} else if (detectorType == HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE
&& detector instanceof SoftwareHotwordDetector) {
SoftwareHotwordDetector softwareDetector = (SoftwareHotwordDetector) detector;
if (softwareDetector.isSameToken(token)) {
softwareDetector.onDetectorRemoteException();
}
}
});
}
/**
* Called when a user has activated an affordance to launch voice assist from the Keyguard.
*

View File

@@ -83,6 +83,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.infra.AndroidFuture;
import com.android.server.LocalServices;
import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.Closeable;
import java.io.IOException;
@@ -203,12 +204,16 @@ abstract class DetectorSession {
boolean mPerformingExternalSourceHotwordDetection;
@NonNull final IBinder mToken;
@NonNull DetectorRemoteExceptionListener mRemoteExceptionListener;
DetectorSession(
@NonNull HotwordDetectionConnection.ServiceConnection remoteDetectionService,
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
@NonNull DetectorRemoteExceptionListener listener) {
mRemoteExceptionListener = listener;
mRemoteDetectionService = remoteDetectionService;
mLock = lock;
mContext = context;
@@ -237,6 +242,14 @@ abstract class DetectorSession {
}
}
void notifyOnDetectorRemoteException() {
Slog.d(TAG, "notifyOnDetectorRemoteException: mRemoteExceptionListener="
+ mRemoteExceptionListener);
if (mRemoteExceptionListener != null) {
mRemoteExceptionListener.onDetectorRemoteException(mToken, getDetectorType());
}
}
@SuppressWarnings("GuardedBy")
private void updateStateAfterProcessStartLocked(PersistableBundle options,
SharedMemory sharedMemory) {
@@ -280,6 +293,7 @@ abstract class DetectorSession {
METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
mVoiceInteractionServiceUid);
}
notifyOnDetectorRemoteException();
}
}
};
@@ -319,6 +333,7 @@ abstract class DetectorSession {
METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
mVoiceInteractionServiceUid);
}
notifyOnDetectorRemoteException();
}
} else if (err != null) {
Slog.w(TAG, "Failed to update state: " + err);
@@ -443,6 +458,7 @@ abstract class DetectorSession {
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
}
notifyOnDetectorRemoteException();
}
} finally {
synchronized (mLock) {
@@ -479,8 +495,12 @@ abstract class DetectorSession {
EXTERNAL_HOTWORD_CLEANUP_MILLIS,
TimeUnit.MILLISECONDS);
callback.onRejected(result);
try {
callback.onRejected(result);
} catch (RemoteException e) {
notifyOnDetectorRemoteException();
throw e;
}
if (result != null) {
Slog.i(TAG, "Egressed 'hotword rejected result' "
+ "from hotword trusted process");
@@ -516,10 +536,15 @@ abstract class DetectorSession {
getDetectorType(),
EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
callback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected"
+ " method."));
try {
callback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected"
+ " method."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
HotwordDetectedResult newResult;
@@ -530,13 +555,23 @@ abstract class DetectorSession {
Slog.w(TAG, "Ignoring #onDetected due to a "
+ "IOException", e);
// TODO: Write event
callback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
try {
callback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
callback.onDetected(newResult, /* audioFormat= */ null,
/* audioStream= */ null);
try {
callback.onDetected(newResult, /* audioFormat= */ null,
/* audioStream= */ null);
} catch (RemoteException e) {
notifyOnDetectorRemoteException();
throw e;
}
Slog.i(TAG, "Egressed "
+ HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
@@ -571,6 +606,7 @@ abstract class DetectorSession {
mDestroyed = true;
mDebugHotwordLogging = false;
mRemoteDetectionService = null;
mRemoteExceptionListener = null;
if (mAttentionManagerInternal != null) {
mAttentionManagerInternal.onStopProximityUpdates(mProximityCallbackInternal);
}
@@ -599,6 +635,7 @@ abstract class DetectorSession {
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
}
notifyOnDetectorRemoteException();
}
}

View File

@@ -42,6 +42,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.IOException;
import java.io.PrintWriter;
@@ -80,10 +81,11 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
@NonNull DetectorRemoteExceptionListener listener) {
super(remoteHotwordDetectionService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
logging);
logging, listener);
}
@SuppressWarnings("GuardedBy")
@@ -131,9 +133,14 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected method."));
try {
externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected method."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
saveProximityValueToBundle(result);
@@ -141,15 +148,25 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
try {
newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result);
} catch (IOException e) {
Slog.w(TAG, "Ignoring #onDetected due to a IOException", e);
externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
try {
Slog.w(TAG, "Ignoring #onDetected due to a IOException", e);
externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
try {
externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
} catch (RemoteException e) {
notifyOnDetectorRemoteException();
throw e;
}
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + newResult);
}
@@ -181,7 +198,12 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
return;
}
mValidatingDspTrigger = false;
externalCallback.onRejected(result);
try {
externalCallback.onRejected(result);
} catch (RemoteException e) {
notifyOnDetectorRemoteException();
throw e;
}
mLastHotwordRejectedResult = result;
if (mDebugHotwordLogging && result != null) {
Slog.i(TAG, "Egressed rejected result: " + result);
@@ -216,6 +238,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
notifyOnDetectorRemoteException();
}
},
MAX_VALIDATION_TIMEOUT_MILLIS,
@@ -248,6 +271,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_REJECTED_EXCEPTION,
mVoiceInteractionServiceUid);
notifyOnDetectorRemoteException();
}
mValidatingDspTrigger = false;
}
@@ -261,6 +285,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION,
mVoiceInteractionServiceUid);
notifyOnDetectorRemoteException();
}
mPerformingExternalSourceHotwordDetection = false;

View File

@@ -69,6 +69,7 @@ import com.android.internal.app.IVisualQueryDetectionAttentionListener;
import com.android.internal.infra.ServiceConnector;
import com.android.server.LocalServices;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.PrintWriter;
import java.time.Instant;
@@ -147,6 +148,8 @@ final class HotwordDetectionConnection {
@GuardedBy("mLock")
private boolean mDebugHotwordLogging = false;
private DetectorRemoteExceptionListener mRemoteExceptionListener;
/**
* For multiple detectors feature, we only support one AlwaysOnHotwordDetector and one
* SoftwareHotwordDetector at the same time. We use SparseArray with detector type as the key
@@ -159,7 +162,8 @@ final class HotwordDetectionConnection {
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity, ComponentName hotwordDetectionServiceName,
ComponentName visualQueryDetectionServiceName, int userId,
boolean bindInstantServiceAllowed, int detectorType) {
boolean bindInstantServiceAllowed, int detectorType,
DetectorRemoteExceptionListener listener) {
mLock = lock;
mContext = context;
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
@@ -168,6 +172,7 @@ final class HotwordDetectionConnection {
mVisualQueryDetectionComponentName = visualQueryDetectionServiceName;
mUser = userId;
mDetectorType = detectorType;
mRemoteExceptionListener = listener;
mReStartPeriodSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
KEY_RESTART_PERIOD_IN_SECONDS, 0);
@@ -251,6 +256,7 @@ final class HotwordDetectionConnection {
void cancelLocked() {
Slog.v(TAG, "cancelLocked");
clearDebugHotwordLoggingTimeoutLocked();
mRemoteExceptionListener = null;
runForEachDetectorSessionLocked((session) -> {
session.destroyLocked();
});
@@ -772,7 +778,8 @@ final class HotwordDetectionConnection {
}
session = new DspTrustedHotwordDetectorSession(mRemoteHotwordDetectionService,
mLock, mContext, token, callback, mVoiceInteractionServiceUid,
mVoiceInteractorIdentity, mScheduledExecutorService, mDebugHotwordLogging);
mVoiceInteractorIdentity, mScheduledExecutorService, mDebugHotwordLogging,
mRemoteExceptionListener);
} else if (detectorType == HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
if (mRemoteVisualQueryDetectionService == null) {
mRemoteVisualQueryDetectionService =
@@ -781,7 +788,7 @@ final class HotwordDetectionConnection {
session = new VisualQueryDetectorSession(
mRemoteVisualQueryDetectionService, mLock, mContext, token, callback,
mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
mScheduledExecutorService, mDebugHotwordLogging);
mScheduledExecutorService, mDebugHotwordLogging, mRemoteExceptionListener);
} else {
if (mRemoteHotwordDetectionService == null) {
mRemoteHotwordDetectionService =
@@ -790,7 +797,7 @@ final class HotwordDetectionConnection {
session = new SoftwareTrustedHotwordDetectorSession(
mRemoteHotwordDetectionService, mLock, mContext, token, callback,
mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
mScheduledExecutorService, mDebugHotwordLogging);
mScheduledExecutorService, mDebugHotwordLogging, mRemoteExceptionListener);
}
mDetectorSessions.put(detectorType, session);
session.initialize(options, sharedMemory);

View File

@@ -43,6 +43,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.IOException;
import java.io.PrintWriter;
@@ -68,10 +69,11 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
@NonNull DetectorRemoteExceptionListener listener) {
super(remoteHotwordDetectionService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
logging);
logging, listener);
}
@SuppressWarnings("GuardedBy")
@@ -123,9 +125,14 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected method."));
try {
mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
"Security exception occurs in #onDetected method."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
saveProximityValueToBundle(result);
@@ -135,12 +142,22 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
} catch (IOException e) {
Slog.w(TAG, "Ignoring #onDetected due to a IOException", e);
// TODO: Write event
mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
try {
mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
"Copy audio stream failure."));
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
return;
}
mSoftwareCallback.onDetected(newResult, null, null);
try {
mSoftwareCallback.onDetected(newResult, null, null);
} catch (RemoteException e1) {
notifyOnDetectorRemoteException();
throw e1;
}
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
if (mDebugHotwordLogging) {
@@ -206,6 +223,7 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION,
mVoiceInteractionServiceUid);
notifyOnDetectorRemoteException();
}
// Restart listening from microphone if the hotword process has been restarted.

View File

@@ -38,6 +38,7 @@ import android.util.Slog;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.app.IVisualQueryDetectionAttentionListener;
import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.PrintWriter;
import java.util.Objects;
@@ -64,13 +65,15 @@ final class VisualQueryDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
@NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
@NonNull DetectorRemoteExceptionListener listener) {
super(remoteService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
logging);
logging, listener);
mEgressingData = false;
mQueryStreaming = false;
mAttentionListener = null;
// TODO: handle notify RemoteException to client
}
@Override

View File

@@ -743,7 +743,15 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
mInfo.getServiceInfo().applicationInfo.uid, voiceInteractorIdentity,
mHotwordDetectionComponentName, mVisualQueryDetectionComponentName, mUser,
/* bindInstantServiceAllowed= */ false, detectorType);
/* bindInstantServiceAllowed= */ false, detectorType,
(token1, detectorType1) -> {
try {
mService.detectorRemoteExceptionOccurred(token1, detectorType1);
} catch (RemoteException e) {
Slog.w(TAG, "Fail to notify client detector remote "
+ "exception occurred.");
}
});
} else if (detectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
// TODO: Logger events should be handled in session instead. Temporary adding the
// checking to prevent confusion so VisualQueryDetection events won't be logged if the
@@ -1080,4 +1088,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
// client always get the callback even if session is unexpectedly closed.
mServiceStub.setSessionWindowVisible(connection.mToken, false);
}
interface DetectorRemoteExceptionListener {
void onDetectorRemoteException(@NonNull IBinder token, int detectorType);
}
}