Improved implementation of VoiceInteractionManagerService.setDisabled()

This method is called by CarService when the system goes into suspend
state and the initial implementation completely disabled the service
(and unbound system server from it), which had 2 drawbacks:
- It adds extra work when the system resumes as it has to rebind.
- It can cause memory leaks if the service implementation doesn't
  handle it well.

This CL changes how the API is implemented: rather than disabling the
service, it just ignores new sessions.

To test it:

1. Disable

$ adb shell cmd voiceinteraction disable true

2. Start a session

$ adb shell cmd voiceinteraction show

3. Check logcat

I VoiceInteractionManager: showSessionForActiveService(): ignored while temporarily disabled

Bug: 190051449
Test: manual verification (see above)

Change-Id: Idbc4881b92d9254fb07ea5af1370ea600fc10b80
This commit is contained in:
Felipe Leme
2021-06-10 14:10:39 -07:00
parent 1a49d4f799
commit 07848e302b
2 changed files with 34 additions and 24 deletions

View File

@@ -562,11 +562,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
void switchImplementationIfNeededLocked(boolean force) {
if (!mCurUserSupported || mTemporarilyDisabled) {
if (!mCurUserSupported) {
if (DEBUG_USER) {
Slog.d(TAG, "switchImplementationIfNeeded(): skipping: force= " + force
+ "mCurUserSupported=" + mCurUserSupported
+ "mTemporarilyDisabled=" + mTemporarilyDisabled);
+ "mCurUserSupported=" + mCurUserSupported);
}
if (mImpl != null) {
mImpl.shutdownLocked();
@@ -1048,13 +1047,16 @@ public class VoiceInteractionManagerService extends SystemService {
if (DEBUG) Slog.d(TAG, "setDisabled(): already " + disabled);
return;
}
Slog.i(TAG, "setDisabled(): changing to " + disabled);
final long caller = Binder.clearCallingIdentity();
try {
mTemporarilyDisabled = disabled;
switchImplementationIfNeeded(/* force= */ false);
} finally {
Binder.restoreCallingIdentity(caller);
mTemporarilyDisabled = disabled;
if (mTemporarilyDisabled) {
Slog.i(TAG, "setDisabled(): temporarily disabling and hiding current session");
try {
hideCurrentSession();
} catch (RemoteException e) {
Log.w(TAG, "Failed to call hideCurrentSession", e);
}
} else {
Slog.i(TAG, "setDisabled(): re-enabling");
}
}
}
@@ -1508,12 +1510,20 @@ public class VoiceInteractionManagerService extends SystemService {
public boolean showSessionForActiveService(Bundle args, int sourceFlags,
IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
if (DEBUG_USER) Slog.d(TAG, "showSessionForActiveService()");
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "showSessionForActiveService without running voice interaction"
+ "service");
return false;
}
if (mTemporarilyDisabled) {
Slog.i(TAG, "showSessionForActiveService(): ignored while temporarily "
+ "disabled");
return false;
}
final long caller = Binder.clearCallingIdentity();
try {
return mImpl.showSessionLocked(args,
@@ -1530,22 +1540,21 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public void hideCurrentSession() throws RemoteException {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
if (mImpl == null) {
return;
}
final long caller = Binder.clearCallingIdentity();
try {
if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
try {
mImpl.mActiveSession.mSession.closeSystemDialogs();
} catch (RemoteException e) {
Log.w(TAG, "Failed to call closeSystemDialogs", e);
}
if (mImpl == null) {
return;
}
final long caller = Binder.clearCallingIdentity();
try {
if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
try {
mImpl.mActiveSession.mSession.closeSystemDialogs();
} catch (RemoteException e) {
Log.w(TAG, "Failed to call closeSystemDialogs", e);
}
} finally {
Binder.restoreCallingIdentity(caller);
}
} finally {
Binder.restoreCallingIdentity(caller);
}
}

View File

@@ -71,6 +71,7 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
pw.println("");
pw.println(" hide");
pw.println(" Hides the current session");
pw.println("");
pw.println(" disable [true|false]");
pw.println(" Temporarily disable (when true) service");
pw.println("");