Merge changes I212ad58c,Idf5dd82d into sc-dev

* changes:
  Provide the way to enable/disable debug mode for logging egressed data
  Set the Debug flag to false
This commit is contained in:
Ahaan Ugale
2021-07-24 06:54:24 +00:00
committed by Android (Google) Code Review
6 changed files with 103 additions and 45 deletions

View File

@@ -72,8 +72,7 @@ import java.util.function.IntConsumer;
@SystemApi @SystemApi
public abstract class HotwordDetectionService extends Service { public abstract class HotwordDetectionService extends Service {
private static final String TAG = "HotwordDetectionService"; private static final String TAG = "HotwordDetectionService";
// TODO (b/177502877): Set the Debug flag to false before shipping. private static final boolean DBG = false;
private static final boolean DBG = true;
private static final long UPDATE_TIMEOUT_MILLIS = 5000; private static final long UPDATE_TIMEOUT_MILLIS = 5000;
@@ -151,9 +150,7 @@ public abstract class HotwordDetectionService extends Service {
@Override @Override
public void updateState(PersistableBundle options, SharedMemory sharedMemory, public void updateState(PersistableBundle options, SharedMemory sharedMemory,
IRemoteCallback callback) throws RemoteException { IRemoteCallback callback) throws RemoteException {
if (DBG) { Log.v(TAG, "#updateState" + (callback != null ? " with callback" : ""));
Log.d(TAG, "#updateState");
}
HotwordDetectionService.this.onUpdateStateInternal( HotwordDetectionService.this.onUpdateStateInternal(
options, options,
sharedMemory, sharedMemory,

View File

@@ -47,7 +47,7 @@ import java.io.PrintWriter;
**/ **/
class SoftwareHotwordDetector extends AbstractHotwordDetector { class SoftwareHotwordDetector extends AbstractHotwordDetector {
private static final String TAG = SoftwareHotwordDetector.class.getSimpleName(); private static final String TAG = SoftwareHotwordDetector.class.getSimpleName();
private static final boolean DEBUG = true; private static final boolean DEBUG = false;
private final IVoiceInteractionManagerService mManagerService; private final IVoiceInteractionManagerService mManagerService;
private final HotwordDetector.Callback mCallback; private final HotwordDetector.Callback mCallback;

View File

@@ -87,14 +87,14 @@ import java.util.function.Function;
*/ */
final class HotwordDetectionConnection { final class HotwordDetectionConnection {
private static final String TAG = "HotwordDetectionConnection"; private static final String TAG = "HotwordDetectionConnection";
// TODO (b/177502877): Set the Debug flag to false before shipping. static final boolean DEBUG = false;
static final boolean DEBUG = true;
// TODO: These constants need to be refined. // TODO: These constants need to be refined.
private static final long VALIDATION_TIMEOUT_MILLIS = 3000; private static final long VALIDATION_TIMEOUT_MILLIS = 3000;
private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000; private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
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 final Executor mAudioCopyExecutor = Executors.newCachedThreadPool(); private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool();
// TODO: This may need to be a Handler(looper) // TODO: This may need to be a Handler(looper)
@@ -115,6 +115,7 @@ final class HotwordDetectionConnection {
private Instant mLastRestartInstant; private Instant mLastRestartInstant;
private ScheduledFuture<?> mCancellationTaskFuture; private ScheduledFuture<?> mCancellationTaskFuture;
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
/** Identity used for attributing app ops when delivering data to the Interactor. */ /** Identity used for attributing app ops when delivering data to the Interactor. */
@GuardedBy("mLock") @GuardedBy("mLock")
@@ -128,6 +129,7 @@ final class HotwordDetectionConnection {
private boolean mPerformingSoftwareHotwordDetection; private boolean mPerformingSoftwareHotwordDetection;
private @NonNull ServiceConnection mRemoteHotwordDetectionService; private @NonNull ServiceConnection mRemoteHotwordDetectionService;
private IBinder mAudioFlinger; private IBinder mAudioFlinger;
private boolean mDebugHotwordLogging = false;
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid, HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity, ComponentName serviceName, int userId, Identity voiceInteractorIdentity, ComponentName serviceName, int userId,
@@ -159,10 +161,7 @@ final class HotwordDetectionConnection {
// 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(() -> {
if (DEBUG) { Slog.v(TAG, "Time to restart the process, TTL has passed");
Slog.i(TAG, "Time to restart the process, TTL has passed");
}
synchronized (mLock) { synchronized (mLock) {
restartProcessLocked(); restartProcessLocked();
} }
@@ -268,9 +267,9 @@ final class HotwordDetectionConnection {
} }
void cancelLocked() { void cancelLocked() {
if (DEBUG) { Slog.v(TAG, "cancelLocked");
Slog.d(TAG, "cancelLocked"); clearDebugHotwordLoggingTimeoutLocked();
} mDebugHotwordLogging = false;
if (mRemoteHotwordDetectionService.isBound()) { if (mRemoteHotwordDetectionService.isBound()) {
mRemoteHotwordDetectionService.unbind(); mRemoteHotwordDetectionService.unbind();
LocalServices.getService(PermissionManagerServiceInternal.class) LocalServices.getService(PermissionManagerServiceInternal.class)
@@ -288,6 +287,7 @@ final class HotwordDetectionConnection {
// TODO(b/191742511): this logic needs a test // TODO(b/191742511): this logic needs a test
if (!mUpdateStateAfterStartFinished.get() if (!mUpdateStateAfterStartFinished.get()
&& Instant.now().minus(MAX_UPDATE_TIMEOUT_DURATION).isBefore(mLastRestartInstant)) { && Instant.now().minus(MAX_UPDATE_TIMEOUT_DURATION).isBefore(mLastRestartInstant)) {
Slog.v(TAG, "call updateStateAfterProcessStart");
updateStateAfterProcessStart(options, sharedMemory); updateStateAfterProcessStart(options, sharedMemory);
} else { } else {
mRemoteHotwordDetectionService.run( mRemoteHotwordDetectionService.run(
@@ -330,6 +330,9 @@ final class HotwordDetectionConnection {
if (result != null) { if (result != null) {
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
+ " bits from hotword trusted process"); + " bits from hotword trusted process");
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + result);
}
} }
} else { } else {
Slog.i(TAG, "Hotword detection has already completed"); Slog.i(TAG, "Hotword detection has already completed");
@@ -407,15 +410,11 @@ final class HotwordDetectionConnection {
private void detectFromDspSourceForTest(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent, private void detectFromDspSourceForTest(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
IHotwordRecognitionStatusCallback externalCallback) { IHotwordRecognitionStatusCallback externalCallback) {
if (DEBUG) { Slog.v(TAG, "detectFromDspSourceForTest");
Slog.d(TAG, "detectFromDspSourceForTest");
}
IDspHotwordDetectionCallback internalCallback = new IDspHotwordDetectionCallback.Stub() { IDspHotwordDetectionCallback internalCallback = new IDspHotwordDetectionCallback.Stub() {
@Override @Override
public void onDetected(HotwordDetectedResult result) throws RemoteException { public void onDetected(HotwordDetectedResult result) throws RemoteException {
if (DEBUG) { Slog.v(TAG, "onDetected");
Slog.d(TAG, "onDetected");
}
synchronized (mLock) { synchronized (mLock) {
if (mValidatingDspTrigger) { if (mValidatingDspTrigger) {
mValidatingDspTrigger = false; mValidatingDspTrigger = false;
@@ -424,6 +423,9 @@ final class HotwordDetectionConnection {
if (result != null) { if (result != null) {
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
+ " bits from hotword trusted process"); + " bits from hotword trusted process");
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + result);
}
} }
} else { } else {
Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); Slog.i(TAG, "Ignored hotword detected since trigger has been handled");
@@ -433,13 +435,14 @@ final class HotwordDetectionConnection {
@Override @Override
public void onRejected(HotwordRejectedResult result) throws RemoteException { public void onRejected(HotwordRejectedResult result) throws RemoteException {
if (DEBUG) { Slog.v(TAG, "onRejected");
Slog.d(TAG, "onRejected");
}
synchronized (mLock) { synchronized (mLock) {
if (mValidatingDspTrigger) { if (mValidatingDspTrigger) {
mValidatingDspTrigger = false; mValidatingDspTrigger = false;
externalCallback.onRejected(result); externalCallback.onRejected(result);
if (mDebugHotwordLogging && result != null) {
Slog.i(TAG, "Egressed rejected result: " + result);
}
} else { } else {
Slog.i(TAG, "Ignored hotword rejected since trigger has been handled"); Slog.i(TAG, "Ignored hotword rejected since trigger has been handled");
} }
@@ -482,6 +485,9 @@ final class HotwordDetectionConnection {
if (result != null) { if (result != null) {
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
+ " bits from hotword trusted process"); + " bits from hotword trusted process");
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + result);
}
} }
} }
} }
@@ -498,6 +504,9 @@ final class HotwordDetectionConnection {
} }
mValidatingDspTrigger = false; mValidatingDspTrigger = false;
externalCallback.onRejected(result); externalCallback.onRejected(result);
if (mDebugHotwordLogging && result != null) {
Slog.i(TAG, "Egressed rejected result: " + result);
}
} }
} }
}; };
@@ -514,19 +523,37 @@ final class HotwordDetectionConnection {
} }
void forceRestart() { void forceRestart() {
if (DEBUG) { Slog.v(TAG, "Requested to restart the service internally. Performing the restart");
Slog.i(TAG, "Requested to restart the service internally. Performing the restart");
}
synchronized (mLock) { synchronized (mLock) {
restartProcessLocked(); restartProcessLocked();
} }
} }
private void restartProcessLocked() { void setDebugHotwordLoggingLocked(boolean logging) {
if (DEBUG) { Slog.v(TAG, "setDebugHotwordLoggingLocked: " + logging);
Slog.i(TAG, "Restarting hotword detection process"); clearDebugHotwordLoggingTimeoutLocked();
} mDebugHotwordLogging = logging;
if (logging) {
// Reset mDebugHotwordLogging to false after one hour
mDebugHotwordLoggingTimeoutFuture = mScheduledExecutorService.schedule(() -> {
Slog.v(TAG, "Timeout to reset mDebugHotwordLogging to false");
synchronized (mLock) {
mDebugHotwordLogging = false;
}
}, RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
}
}
private void clearDebugHotwordLoggingTimeoutLocked() {
if (mDebugHotwordLoggingTimeoutFuture != null) {
mDebugHotwordLoggingTimeoutFuture.cancel(/* mayInterruptIfRunning= */true);
mDebugHotwordLoggingTimeoutFuture = null;
}
}
private void restartProcessLocked() {
Slog.v(TAG, "Restarting hotword detection process");
ServiceConnection oldConnection = mRemoteHotwordDetectionService; ServiceConnection oldConnection = mRemoteHotwordDetectionService;
// TODO(volnov): this can be done after connect() has been successful. // TODO(volnov): this can be done after connect() has been successful.
@@ -547,9 +574,7 @@ final class HotwordDetectionConnection {
// Recreate connection to reset the cache. // Recreate connection to reset the cache.
mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked(); mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked();
if (DEBUG) { Slog.v(TAG, "Started the new process, issuing #onProcessRestarted");
Slog.i(TAG, "Started the new process, issuing #onProcessRestarted");
}
try { try {
mCallback.onProcessRestarted(); mCallback.onProcessRestarted();
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -700,6 +725,9 @@ final class HotwordDetectionConnection {
bestEffortClose(serviceAudioSource); bestEffortClose(serviceAudioSource);
bestEffortClose(audioSource); bestEffortClose(audioSource);
if (mDebugHotwordLogging && result != null) {
Slog.i(TAG, "Egressed rejected result: " + result);
}
// TODO: Propagate the HotwordRejectedResult. // TODO: Propagate the HotwordRejectedResult.
} }
@@ -714,6 +742,9 @@ final class HotwordDetectionConnection {
if (triggerResult != null) { if (triggerResult != null) {
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize( Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(
triggerResult) + " bits from hotword trusted process"); triggerResult) + " bits from hotword trusted process");
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + triggerResult);
}
} }
// TODO: Add a delay before closing. // TODO: Add a delay before closing.
bestEffortClose(audioSource); bestEffortClose(audioSource);
@@ -773,9 +804,7 @@ final class HotwordDetectionConnection {
} }
synchronized (mLock) { synchronized (mLock) {
if (!mRespectServiceConnectionStatusChanged) { if (!mRespectServiceConnectionStatusChanged) {
if (DEBUG) { Slog.v(TAG, "Ignored onServiceConnectionStatusChanged event");
Slog.d(TAG, "Ignored onServiceConnectionStatusChanged event");
}
return; return;
} }
mIsBound = connected; mIsBound = connected;
@@ -792,9 +821,7 @@ final class HotwordDetectionConnection {
super.binderDied(); super.binderDied();
synchronized (mLock) { synchronized (mLock) {
if (!mRespectServiceConnectionStatusChanged) { if (!mRespectServiceConnectionStatusChanged) {
if (DEBUG) { Slog.v(TAG, "Ignored #binderDied event");
Slog.d(TAG, "Ignored #binderDied event");
}
return; return;
} }

View File

@@ -832,6 +832,17 @@ public class VoiceInteractionManagerService extends SystemService {
mImpl.forceRestartHotwordDetector(); mImpl.forceRestartHotwordDetector();
} }
// Called by Shell command
void setDebugHotwordLogging(boolean logging) {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "setTemporaryLogging without running voice interaction service");
return;
}
mImpl.setDebugHotwordLoggingLocked(logging);
}
}
@Override @Override
public void showSession(Bundle args, int flags) { public void showSession(Bundle args, int flags) {
synchronized (this) { synchronized (this) {

View File

@@ -79,8 +79,7 @@ import java.util.List;
class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback { class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback {
final static String TAG = "VoiceInteractionServiceManager"; final static String TAG = "VoiceInteractionServiceManager";
// TODO (b/177502877): Set the Debug flag to false before shipping. static final boolean DEBUG = false;
static final boolean DEBUG = true;
final static String CLOSE_REASON_VOICE_INTERACTION = "voiceinteraction"; final static String CLOSE_REASON_VOICE_INTERACTION = "voiceinteraction";
@@ -420,9 +419,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
@Nullable PersistableBundle options, @Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory, @Nullable SharedMemory sharedMemory,
IHotwordRecognitionStatusCallback callback) { IHotwordRecognitionStatusCallback callback) {
if (DEBUG) { Slog.v(TAG, "updateStateLocked");
Slog.d(TAG, "updateStateLocked");
}
if (mHotwordDetectionComponentName == null) { if (mHotwordDetectionComponentName == null) {
Slog.w(TAG, "Hotword detection service name not found"); Slog.w(TAG, "Hotword detection service name not found");
throw new IllegalStateException("Hotword detection service name not found"); throw new IllegalStateException("Hotword detection service name not found");
@@ -584,6 +581,14 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.forceRestart(); mHotwordDetectionConnection.forceRestart();
} }
void setDebugHotwordLoggingLocked(boolean logging) {
if (mHotwordDetectionConnection == null) {
Slog.w(TAG, "Failed to set temporary debug logging: no hotword detection active");
return;
}
mHotwordDetectionConnection.setDebugHotwordLoggingLocked(logging);
}
void resetHotwordDetectionConnectionLocked() { void resetHotwordDetectionConnectionLocked() {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "resetHotwordDetectionConnectionLocked"); Slog.d(TAG, "resetHotwordDetectionConnectionLocked");

View File

@@ -56,6 +56,8 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
return requestDisable(pw); return requestDisable(pw);
case "restart-detection": case "restart-detection":
return requestRestartDetection(pw); return requestRestartDetection(pw);
case "set-debug-hotword-logging":
return setDebugHotwordLogging(pw);
default: default:
return handleDefaultCommands(cmd); return handleDefaultCommands(cmd);
} }
@@ -76,9 +78,14 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
pw.println(""); pw.println("");
pw.println(" disable [true|false]"); pw.println(" disable [true|false]");
pw.println(" Temporarily disable (when true) service"); pw.println(" Temporarily disable (when true) service");
pw.println("");
pw.println(" restart-detection"); pw.println(" restart-detection");
pw.println(" Force a restart of a hotword detection service"); pw.println(" Force a restart of a hotword detection service");
pw.println(""); pw.println("");
pw.println(" set-debug-hotword-logging [true|false]");
pw.println(" Temporarily enable or disable debug logging for hotword result.");
pw.println(" The debug logging will be reset after one hour from last enable.");
pw.println("");
} }
} }
@@ -157,6 +164,17 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
return 0; return 0;
} }
private int setDebugHotwordLogging(PrintWriter pw) {
boolean logging = Boolean.parseBoolean(getNextArgRequired());
Slog.i(TAG, "setDebugHotwordLogging(): " + logging);
try {
mService.setDebugHotwordLogging(logging);
} catch (Exception e) {
return handleError(pw, "setDebugHotwordLogging()", e);
}
return 0;
}
private static int handleError(PrintWriter pw, String message, Exception e) { private static int handleError(PrintWriter pw, String message, Exception e) {
Slog.e(TAG, "error calling " + message, e); Slog.e(TAG, "error calling " + message, e);
pw.printf("Error calling %s: %s\n", message, e); pw.printf("Error calling %s: %s\n", message, e);