diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java index b8af7403254..e64c8c05756 100644 --- a/src/com/android/settings/development/qstile/DevelopmentTiles.java +++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java @@ -49,6 +49,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.app.LocalePicker; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.view.IInputMethodManager; import com.android.settings.R; import com.android.settings.development.WirelessDebuggingPreferenceController; import com.android.settings.overlay.FeatureFactory; @@ -197,6 +198,7 @@ public abstract class DevelopmentTiles extends TileService { static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026; private IBinder mSurfaceFlinger; private IWindowManager mWindowManager; + private IInputMethodManager mInputMethodManager; private Toast mToast; @Override @@ -204,6 +206,8 @@ public abstract class DevelopmentTiles extends TileService { super.onCreate(); mWindowManager = WindowManagerGlobal.getWindowManagerService(); mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + mInputMethodManager = IInputMethodManager.Stub.asInterface( + ServiceManager.getService("input_method")); Context context = getApplicationContext(); CharSequence text = "Trace files written to /data/misc/wmtrace"; mToast = Toast.makeText(context, text, Toast.LENGTH_LONG); @@ -256,9 +260,19 @@ public abstract class DevelopmentTiles extends TileService { return false; } + private boolean isImeTraceEnabled() { + try { + return mInputMethodManager.isImeTraceEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "Could not get ime trace status, defaulting to false.", e); + } + return false; + } + @Override protected boolean isEnabled() { - return isWindowTraceEnabled() || isLayerTraceEnabled() || isSystemUiTracingEnabled(); + return isWindowTraceEnabled() || isLayerTraceEnabled() || isSystemUiTracingEnabled() + || isImeTraceEnabled(); } private void setWindowTraceEnabled(boolean isEnabled) { @@ -308,11 +322,24 @@ public abstract class DevelopmentTiles extends TileService { } } + private void setImeTraceEnabled(boolean isEnabled) { + try { + if (isEnabled) { + mInputMethodManager.startImeTrace(); + } else { + mInputMethodManager.stopImeTrace(); + } + } catch (RemoteException e) { + Log.e(TAG, "Could not set ime trace status." + e.toString()); + } + } + @Override protected void setIsEnabled(boolean isEnabled) { setWindowTraceEnabled(isEnabled); setLayerTraceEnabled(isEnabled); setSystemUiTracing(isEnabled); + setImeTraceEnabled(isEnabled); if (!isEnabled) { mToast.show(); } diff --git a/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java b/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java index cafebe44c0b..b4dab0d7cbd 100644 --- a/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java +++ b/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java @@ -37,6 +37,7 @@ import android.os.RemoteException; import android.view.IWindowManager; import android.widget.Toast; +import com.android.internal.view.IInputMethodManager; import com.android.settings.testutils.shadow.ShadowParcel; import org.junit.After; @@ -55,6 +56,8 @@ public class WinscopeTraceTest { @Mock private IWindowManager mWindowManager; @Mock + private IInputMethodManager mInputMethodManager; + @Mock private IBinder mSurfaceFlinger; @Mock private Toast mToast; @@ -66,6 +69,7 @@ public class WinscopeTraceTest { MockitoAnnotations.initMocks(this); mWinscopeTrace = spy(new DevelopmentTiles.WinscopeTrace()); ReflectionHelpers.setField(mWinscopeTrace, "mWindowManager", mWindowManager); + ReflectionHelpers.setField(mWinscopeTrace, "mInputMethodManager", mInputMethodManager); ReflectionHelpers.setField(mWinscopeTrace, "mSurfaceFlinger", mSurfaceFlinger); ReflectionHelpers.setField(mWinscopeTrace, "mToast", mToast); } @@ -78,7 +82,7 @@ public class WinscopeTraceTest { @Test @Config(shadows = ShadowParcel.class) public void wmReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { - // Assume Surface Trace is disabled. + // Assume Surface Trace and Input Method Manager are disabled. ShadowParcel.sReadBoolResult = false; doReturn(true).when(mWindowManager).isWindowTraceEnabled(); assertThat(mWinscopeTrace.isEnabled()).isTrue(); @@ -87,8 +91,9 @@ public class WinscopeTraceTest { @Test @Config(shadows = ShadowParcel.class) public void sfReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { - // Assume Window Trace is disabled. + // Assume Window Trace and Input Method Manager are disabled. doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + doReturn(false).when(mInputMethodManager).isImeTraceEnabled(); ShadowParcel.sReadBoolResult = true; assertThat(mWinscopeTrace.isEnabled()).isTrue(); verify(mSurfaceFlinger) @@ -106,16 +111,48 @@ public class WinscopeTraceTest { } @Test - public void wmAndSfReturnsTraceDisabled_shouldReturnDisabled() throws RemoteException { + public void wmAndSfAndImmReturnTraceDisabled_shouldReturnDisabled() throws RemoteException { ShadowParcel.sReadBoolResult = false; doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + doReturn(false).when(mInputMethodManager).isImeTraceEnabled(); assertThat(mWinscopeTrace.isEnabled()).isFalse(); verify(mSurfaceFlinger) .transact(eq(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE), any(), any(), - eq(0 /* flags */)); + eq(0 /* flags */)); verifyNoMoreInteractions(mSurfaceFlinger); } + @Test + public void wmAndSfReturnTraceDisabled_immReturnsTraceEnabled_shouldReturnEnabled() + throws RemoteException { + ShadowParcel.sReadBoolResult = false; + doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + doReturn(true).when(mInputMethodManager).isImeTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isTrue(); + verify(mSurfaceFlinger) + .transact(eq(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE), any(), any(), + eq(0 /* flags */)); + verifyNoMoreInteractions(mSurfaceFlinger); + } + + @Test + @Config(shadows = ShadowParcel.class) + public void immReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { + // Assume Window Manager and Surface Trace are disabled. + ShadowParcel.sReadBoolResult = false; + doReturn(true).when(mInputMethodManager).isImeTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isTrue(); + } + + @Test + @Config(shadows = ShadowParcel.class) + public void immReturnsTraceDisabled_shouldReturnDisabled() throws RemoteException { + // Assume Window Manager and Surface Trace are disabled. + ShadowParcel.sReadBoolResult = false; + doReturn(false).when(mInputMethodManager).isImeTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isFalse(); + } + @Test @Config(shadows = ShadowParcel.class) public void wmThrowsRemoteExAndSfReturnsTraceDisabled_shouldReturnDisabled() @@ -127,9 +164,10 @@ public class WinscopeTraceTest { } @Test - public void sfUnavailableAndWmReturnsTraceDisabled_shouldReturnDisabled() + public void sfUnavailableAndWmAndImmReturnTraceDisabled_shouldReturnDisabled() throws RemoteException { doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + doReturn(false).when(mInputMethodManager).isImeTraceEnabled(); ReflectionHelpers.setField(mWinscopeTrace, "mSurfaceFlinger", null); assertThat(mWinscopeTrace.isEnabled()).isFalse(); } @@ -141,6 +179,13 @@ public class WinscopeTraceTest { verifyNoMoreInteractions(mWindowManager); } + @Test + public void setIsEnableTrue_shouldEnableImeTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(true); + verify(mInputMethodManager).startImeTrace(); + verifyNoMoreInteractions(mInputMethodManager); + } + @Test @Config(shadows = ShadowParcel.class) public void setIsEnableTrue_shouldEnableLayerTrace() throws RemoteException { @@ -161,6 +206,15 @@ public class WinscopeTraceTest { verify(mToast).show(); } + @Test + @Config(shadows = ShadowParcel.class) + public void setIsEnableFalse_shouldDisableImeTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(false); + verify(mInputMethodManager).stopImeTrace(); + verifyNoMoreInteractions(mInputMethodManager); + verify(mToast).show(); + } + @Test @Config(shadows = ShadowParcel.class) public void setIsEnableFalse_shouldDisableLayerTrace() throws RemoteException { @@ -190,6 +244,17 @@ public class WinscopeTraceTest { mWinscopeTrace.setIsEnabled(true); } + /** + * Verify when input method manager call throws a remote exception, it is handled without + * re-throwing the exception. + */ + @Test + public void setIsEnableAndImmThrowsRemoteException_shouldFailGracefully() + throws RemoteException { + doThrow(new RemoteException("Unknown")).when(mInputMethodManager).isImeTraceEnabled(); + mWinscopeTrace.setIsEnabled(true); + } + /** * Verify is surface flinger is not available not calls are made to it. */