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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user