Trusted Hotword: Allow disabling periodic restarts.
Mitigates quality risk that may arise due to mismanaged state around the
restarts (either on the platform or application side).
The duration will be flag-controlled in a follow-up cl so it can
actually be disabled by flag.
Bug: 224618257
Test: manual
Change-Id: I3b17b47fab4120b42d75443b213be3c1ef5491aa
(cherry picked from commit b8cd0a4286)
Merged-in: I3b17b47fab4120b42d75443b213be3c1ef5491aa
This commit is contained in:
@@ -115,6 +115,11 @@ final class HotwordDetectionConnection {
|
|||||||
private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
|
private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
|
||||||
Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
|
Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
|
||||||
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
|
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
|
||||||
|
/**
|
||||||
|
* Time after which each HotwordDetectionService process is stopped and replaced by a new one.
|
||||||
|
* 0 indicates no restarts.
|
||||||
|
*/
|
||||||
|
private static final int RESTART_PERIOD_SECONDS = 3600; // 60 minutes
|
||||||
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
|
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
|
||||||
|
|
||||||
// Hotword metrics
|
// Hotword metrics
|
||||||
@@ -133,6 +138,7 @@ final class HotwordDetectionConnection {
|
|||||||
// TODO: This may need to be a Handler(looper)
|
// TODO: This may need to be a Handler(looper)
|
||||||
private final ScheduledExecutorService mScheduledExecutorService =
|
private final ScheduledExecutorService mScheduledExecutorService =
|
||||||
Executors.newSingleThreadScheduledExecutor();
|
Executors.newSingleThreadScheduledExecutor();
|
||||||
|
@Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
|
||||||
private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
|
private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
|
||||||
private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
|
private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
|
||||||
private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
|
private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
|
||||||
@@ -148,7 +154,6 @@ final class HotwordDetectionConnection {
|
|||||||
private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
|
private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
|
||||||
private Instant mLastRestartInstant;
|
private Instant mLastRestartInstant;
|
||||||
|
|
||||||
private ScheduledFuture<?> mCancellationTaskFuture;
|
|
||||||
private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture;
|
private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture;
|
||||||
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
|
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
|
||||||
|
|
||||||
@@ -194,6 +199,9 @@ final class HotwordDetectionConnection {
|
|||||||
mLastRestartInstant = Instant.now();
|
mLastRestartInstant = Instant.now();
|
||||||
updateStateAfterProcessStart(options, sharedMemory);
|
updateStateAfterProcessStart(options, sharedMemory);
|
||||||
|
|
||||||
|
if (RESTART_PERIOD_SECONDS <= 0) {
|
||||||
|
mCancellationTaskFuture = null;
|
||||||
|
} else {
|
||||||
// TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
|
// TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
|
||||||
// until the current session is closed.
|
// until the current session is closed.
|
||||||
mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
|
mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
|
||||||
@@ -203,7 +211,8 @@ final class HotwordDetectionConnection {
|
|||||||
HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
|
HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
|
||||||
HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
|
HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
|
||||||
}
|
}
|
||||||
}, 30, 30, TimeUnit.MINUTES);
|
}, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initAudioFlingerLocked() {
|
private void initAudioFlingerLocked() {
|
||||||
@@ -341,7 +350,9 @@ final class HotwordDetectionConnection {
|
|||||||
.setHotwordDetectionServiceProvider(null);
|
.setHotwordDetectionServiceProvider(null);
|
||||||
mIdentity = null;
|
mIdentity = null;
|
||||||
updateServiceUidForAudioPolicy(Process.INVALID_UID);
|
updateServiceUidForAudioPolicy(Process.INVALID_UID);
|
||||||
|
if (mCancellationTaskFuture != null) {
|
||||||
mCancellationTaskFuture.cancel(/* may interrupt */ true);
|
mCancellationTaskFuture.cancel(/* may interrupt */ true);
|
||||||
|
}
|
||||||
if (mAudioFlinger != null) {
|
if (mAudioFlinger != null) {
|
||||||
mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
|
mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
|
||||||
}
|
}
|
||||||
@@ -759,6 +770,7 @@ final class HotwordDetectionConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dump(String prefix, PrintWriter pw) {
|
public void dump(String prefix, PrintWriter pw) {
|
||||||
|
pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS);
|
||||||
pw.print(prefix);
|
pw.print(prefix);
|
||||||
pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
|
pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
|
||||||
pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
|
pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
|
||||||
|
|||||||
Reference in New Issue
Block a user