cancel VI latency tracking for non ST triggers

The VoiceInteraction UI latency is limited to measuring the
SoundTrigger HAL invocation latency. This change cancels the latency
measurment when the VoiceInteraction UI is shown due to a invocation
outside of VoiceInteractionService#showSession.

Bug: 265850090
Test: manual invocation of system UI and gesture to confirm latency is
canceled

Change-Id: Ib1c9464217e8a66fbd96d2192b13cf13713362e9
This commit is contained in:
Nicholas Ambur
2023-02-13 18:51:43 +00:00
parent 91701dd240
commit 0f8bbf882b
2 changed files with 64 additions and 3 deletions

View File

@@ -34,10 +34,13 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENT
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE;
import static com.android.internal.util.LatencyTracker.ACTION_SHOW_VOICE_INTERACTION;
import android.content.Context;
import android.service.voice.HotwordDetector; import android.service.voice.HotwordDetector;
import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.LatencyTracker;
/** /**
* A utility class for logging hotword statistics event. * A utility class for logging hotword statistics event.
@@ -116,6 +119,46 @@ public final class HotwordMetricsLogger {
metricsDetectorType, event, uid, streamSizeBytes, bundleSizeBytes, streamCount); metricsDetectorType, event, uid, streamSizeBytes, bundleSizeBytes, streamCount);
} }
/**
* Starts a {@link LatencyTracker} log for the time it takes to show the
* {@link android.service.voice.VoiceInteractionSession} system UI after a voice trigger.
*
* @see LatencyTracker
*
* @param tag Extra tag to separate different sessions from each other.
*/
public static void startHotwordTriggerToUiLatencySession(Context context, String tag) {
LatencyTracker.getInstance(context).onActionStart(ACTION_SHOW_VOICE_INTERACTION, tag);
}
/**
* Completes a {@link LatencyTracker} log for the time it takes to show the
* {@link android.service.voice.VoiceInteractionSession} system UI after a voice trigger.
*
* <p>Completing this session will result in logging metric data.</p>
*
* @see LatencyTracker
*/
public static void stopHotwordTriggerToUiLatencySession(Context context) {
LatencyTracker.getInstance(context).onActionEnd(ACTION_SHOW_VOICE_INTERACTION);
}
/**
* Cancels a {@link LatencyTracker} log for the time it takes to show the
* {@link android.service.voice.VoiceInteractionSession} system UI after a voice trigger.
*
* <p>Cancels typically occur when the VoiceInteraction session UI is shown for reasons outside
* of a {@link android.hardware.soundtrigger.SoundTrigger.RecognitionEvent} such as an
* invocation from an external source or service.</p>
*
* <p>Canceling this session will not result in logging metric data.
*
* @see LatencyTracker
*/
public static void cancelHotwordTriggerToUiLatencySession(Context context) {
LatencyTracker.getInstance(context).onActionCancel(ACTION_SHOW_VOICE_INTERACTION);
}
private static int getCreateMetricsDetectorType(int detectorType) { private static int getCreateMetricsDetectorType(int detectorType) {
switch (detectorType) { switch (detectorType) {
case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE:

View File

@@ -97,7 +97,6 @@ import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread; import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.internal.util.LatencyTracker;
import com.android.server.FgThread; import com.android.server.FgThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.SystemService; import com.android.server.SystemService;
@@ -443,6 +442,10 @@ public class VoiceInteractionManagerService extends SystemService {
final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
// HotwordDetector trigger uses VoiceInteractionService#showSession
// We need to cancel here because UI is not being shown due to a SoundTrigger
// HAL event.
HotwordMetricsLogger.cancelHotwordTriggerToUiLatencySession(mContext);
mImpl.showSessionLocked(options, mImpl.showSessionLocked(options,
VoiceInteractionSession.SHOW_SOURCE_ACTIVITY, attributionTag, VoiceInteractionSession.SHOW_SOURCE_ACTIVITY, attributionTag,
new IVoiceInteractionSessionShowCallback.Stub() { new IVoiceInteractionSessionShowCallback.Stub() {
@@ -994,6 +997,13 @@ public class VoiceInteractionManagerService extends SystemService {
Slog.w(TAG, "showSessionFromSession without running voice interaction service"); Slog.w(TAG, "showSessionFromSession without running voice interaction service");
return false; return false;
} }
// If the token is null, then the request to show the session is not coming from
// the active VoiceInteractionService session.
// We need to cancel here because UI is not being shown due to a SoundTrigger
// HAL event.
if (token == null) {
HotwordMetricsLogger.cancelHotwordTriggerToUiLatencySession(mContext);
}
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
return mImpl.showSessionLocked(sessionArgs, flags, attributionTag, null, null); return mImpl.showSessionLocked(sessionArgs, flags, attributionTag, null, null);
@@ -1862,6 +1872,11 @@ public class VoiceInteractionManagerService extends SystemService {
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
// HotwordDetector trigger uses VoiceInteractionService#showSession
// We need to cancel here because UI is not being shown due to a SoundTrigger
// HAL event.
HotwordMetricsLogger.cancelHotwordTriggerToUiLatencySession(mContext);
return mImpl.showSessionLocked(args, return mImpl.showSessionLocked(args,
sourceFlags sourceFlags
| VoiceInteractionSession.SHOW_WITH_ASSIST | VoiceInteractionSession.SHOW_WITH_ASSIST
@@ -2521,8 +2536,11 @@ public class VoiceInteractionManagerService extends SystemService {
public void onVoiceSessionWindowVisibilityChanged(boolean visible) public void onVoiceSessionWindowVisibilityChanged(boolean visible)
throws RemoteException { throws RemoteException {
if (visible) { if (visible) {
LatencyTracker.getInstance(mContext) // The AlwaysOnHotwordDetector trigger latency is always completed here even
.onActionEnd(LatencyTracker.ACTION_SHOW_VOICE_INTERACTION); // if the reason the window was shown was not due to a SoundTrigger HAL
// event. It is expected that the latency will be canceled if shown for
// other invocation reasons, and this call becomes a noop.
HotwordMetricsLogger.stopHotwordTriggerToUiLatencySession(mContext);
} }
} }