diff --git a/AndroidManifest.xml b/AndroidManifest.xml index dec12ba4e5c..7b24600e85e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3213,19 +3213,9 @@ - - - - - diff --git a/res/drawable/tile_icon_layer_trace.xml b/res/drawable/tile_icon_layer_trace.xml deleted file mode 100644 index 21dafd39290..00000000000 --- a/res/drawable/tile_icon_layer_trace.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - diff --git a/res/drawable/tile_icon_window_trace.xml b/res/drawable/tile_icon_winscope_trace.xml similarity index 100% rename from res/drawable/tile_icon_window_trace.xml rename to res/drawable/tile_icon_winscope_trace.xml diff --git a/res/values/strings.xml b/res/values/strings.xml index d7a45865621..cbfcbf44b1c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8886,11 +8886,8 @@ Quick settings developer tiles - - Window Trace - - - Surface Trace + + Winscope Trace %1$s - %2$s diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java index 38f95655168..736c40cce1c 100644 --- a/src/com/android/settings/development/qstile/DevelopmentTiles.java +++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java @@ -142,26 +142,29 @@ public abstract class DevelopmentTiles extends TileService { } /** - * Tile to toggle Window Trace. + * Tile to toggle Winscope trace which consists of Window and Layer traces. */ - public static class WindowTrace extends DevelopmentTiles { + public static class WinscopeTrace extends DevelopmentTiles { @VisibleForTesting - IWindowManagerWrapper mWindowManager; + static final int SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE = 1025; @VisibleForTesting - Toast mToast; + static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026; + private IBinder mSurfaceFlinger; + private IWindowManagerWrapper mWindowManager; + private Toast mToast; @Override public void onCreate() { super.onCreate(); mWindowManager = new IWindowManagerWrapper(WindowManagerGlobal .getWindowManagerService()); + mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger"); Context context = getApplicationContext(); - CharSequence text = "Trace written to /data/misc/wmtrace/wm_trace.pb"; + CharSequence text = "Trace files written to /data/misc/wmtrace"; mToast = Toast.makeText(context, text, Toast.LENGTH_LONG); } - @Override - protected boolean isEnabled() { + private boolean isWindowTraceEnabled() { try { return mWindowManager.isWindowTraceEnabled(); } catch (RemoteException e) { @@ -171,46 +174,8 @@ public abstract class DevelopmentTiles extends TileService { return false; } - @Override - protected void setIsEnabled(boolean isEnabled) { - try { - if (isEnabled) { - mWindowManager.startWindowTrace(); - } else { - mWindowManager.stopWindowTrace(); - mToast.show(); - } - } catch (RemoteException e) { - Log.e(TAG, "Could not set window trace status." + e.toString()); - } - } - } - - /** - * Tile to toggle Layer Trace. - */ - public static class LayerTrace extends DevelopmentTiles { - @VisibleForTesting - static final int SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE = 1025; - @VisibleForTesting - static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026; - @VisibleForTesting - IBinder mSurfaceFlinger; - @VisibleForTesting - Toast mToast; - - @Override - public void onCreate() { - super.onCreate(); - mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger"); - Context context = getApplicationContext(); - CharSequence text = "Trace written to /data/misc/wmtrace/layers_trace.pb"; - mToast = Toast.makeText(context, text, Toast.LENGTH_LONG); - } - - @Override - protected boolean isEnabled() { - boolean surfaceTraceEnabled = false; + private boolean isLayerTraceEnabled() { + boolean layerTraceEnabled = false; Parcel reply = null; Parcel data = null; try { @@ -219,8 +184,8 @@ public abstract class DevelopmentTiles extends TileService { data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE, - data, reply, 0 /* flags */ ); - surfaceTraceEnabled = reply.readBoolean(); + data, reply, 0 /* flags */); + layerTraceEnabled = reply.readBoolean(); } } catch (RemoteException e) { Log.e(TAG, "Could not get layer trace status, defaulting to false." + e.toString()); @@ -230,11 +195,27 @@ public abstract class DevelopmentTiles extends TileService { reply.recycle(); } } - return surfaceTraceEnabled; + return layerTraceEnabled; } @Override - protected void setIsEnabled(boolean isEnabled) { + protected boolean isEnabled() { + return isWindowTraceEnabled() || isLayerTraceEnabled(); + } + + private void setWindowTraceEnabled(boolean isEnabled) { + try { + if (isEnabled) { + mWindowManager.startWindowTrace(); + } else { + mWindowManager.stopWindowTrace(); + } + } catch (RemoteException e) { + Log.e(TAG, "Could not set window trace status." + e.toString()); + } + } + + private void setLayerTraceEnabled(boolean isEnabled) { Parcel data = null; try { if (mSurfaceFlinger != null) { @@ -243,9 +224,6 @@ public abstract class DevelopmentTiles extends TileService { data.writeInt(isEnabled ? 1 : 0); mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE, data, null, 0 /* flags */); - if (!isEnabled){ - mToast.show(); - } } } catch (RemoteException e) { Log.e(TAG, "Could not set layer tracing." + e.toString()); @@ -255,5 +233,14 @@ public abstract class DevelopmentTiles extends TileService { } } } + + @Override + protected void setIsEnabled(boolean isEnabled) { + setWindowTraceEnabled(isEnabled); + setLayerTraceEnabled(isEnabled); + if (!isEnabled) { + mToast.show(); + } + } } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/development/qstile/LayerTraceTest.java b/tests/robotests/src/com/android/settings/development/qstile/LayerTraceTest.java deleted file mode 100644 index 0e42759ad28..00000000000 --- a/tests/robotests/src/com/android/settings/development/qstile/LayerTraceTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.development.qstile; - -import static com.android.settings.development.qstile.DevelopmentTiles.LayerTrace - .SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE; -import static com.android.settings.development.qstile.DevelopmentTiles.LayerTrace - .SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import android.os.IBinder; -import android.os.RemoteException; -import android.widget.Toast; - -import com.android.settings.TestConfig; -import com.android.settings.testutils.shadow.ShadowParcel; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class LayerTraceTest { - @Mock - private IBinder mSurfaceFlinger; - @Mock - private Toast mToast; - - private DevelopmentTiles.LayerTrace mLayerTraceTile; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mLayerTraceTile = spy(new DevelopmentTiles.LayerTrace()); - ReflectionHelpers.setField(mLayerTraceTile, "mSurfaceFlinger", mSurfaceFlinger); - ReflectionHelpers.setField(mLayerTraceTile, "mToast", mToast); - } - - @After - public void after() { - verifyNoMoreInteractions(mSurfaceFlinger); - verifyNoMoreInteractions(mToast); - } - - @Test - @Config(shadows = {ShadowParcel.class}) - public void sfReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { - ShadowParcel.sReadBoolResult = true; - assertThat(mLayerTraceTile.isEnabled()).isTrue(); - verify(mSurfaceFlinger) - .transact(eq(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE), any(), any(), - eq(0 /* flags */)); - } - - @Test - @Config(shadows = {ShadowParcel.class}) - public void sfReturnsTraceDisabled_shouldReturnDisabled() throws RemoteException { - ShadowParcel.sReadBoolResult = false; - assertThat(mLayerTraceTile.isEnabled()).isFalse(); - verify(mSurfaceFlinger) - .transact(eq(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE), any(), any(), - eq(0 /* flags */)); - } - - @Test - public void sfUnavailable_shouldReturnDisabled() throws RemoteException { - ReflectionHelpers.setField(mLayerTraceTile, "mSurfaceFlinger", null); - assertThat(mLayerTraceTile.isEnabled()).isFalse(); - } - - @Test - @Config(shadows = {ShadowParcel.class}) - public void setIsEnableTrue_shouldEnableLayerTrace() throws RemoteException { - mLayerTraceTile.setIsEnabled(true); - assertThat(ShadowParcel.sWriteIntResult).isEqualTo(1); - verify(mSurfaceFlinger) - .transact(eq(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE), any(), isNull(), - eq(0 /* flags */)); - } - - @Test - @Config(shadows = {ShadowParcel.class}) - public void setIsEnableFalse_shouldDisableLayerTraceAndShowToast() throws RemoteException { - mLayerTraceTile.setIsEnabled(false); - assertThat(ShadowParcel.sWriteIntResult).isEqualTo(0); - verify(mSurfaceFlinger) - .transact(eq(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE), any(), isNull(), - eq(0 /* flags */)); - verify(mToast).show(); - } - - @Test - public void setIsEnableAndSfUnavailable_shouldDoNothing() throws RemoteException { - ReflectionHelpers.setField(mLayerTraceTile, "mSurfaceFlinger", null); - mLayerTraceTile.setIsEnabled(true); - mLayerTraceTile.setIsEnabled(false); - } -} diff --git a/tests/robotests/src/com/android/settings/development/qstile/WindowTraceTest.java b/tests/robotests/src/com/android/settings/development/qstile/WindowTraceTest.java deleted file mode 100644 index d8a8084e102..00000000000 --- a/tests/robotests/src/com/android/settings/development/qstile/WindowTraceTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.development.qstile; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import android.os.RemoteException; -import android.widget.Toast; - -import com.android.settings.TestConfig; -import com.android.settings.testutils.shadow.ShadowParcel; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.wrapper.IWindowManagerWrapper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class WindowTraceTest { - @Mock - private IWindowManagerWrapper mWindowManager; - @Mock - private Toast mToast; - - private DevelopmentTiles.WindowTrace mWindowTrace; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mWindowTrace = spy(new DevelopmentTiles.WindowTrace()); - ReflectionHelpers.setField(mWindowTrace, "mWindowManager", mWindowManager); - ReflectionHelpers.setField(mWindowTrace, "mToast", mToast); - } - - @After - public void teardown() { - verifyNoMoreInteractions(mToast); - } - - @Test - public void wmReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { - doReturn(true).when(mWindowManager).isWindowTraceEnabled(); - assertThat(mWindowTrace.isEnabled()).isTrue(); - } - - @Test - public void wmReturnsTraceDisabled_shouldReturnDisabled() throws RemoteException { - doReturn(false).when(mWindowManager).isWindowTraceEnabled(); - assertThat(mWindowTrace.isEnabled()).isFalse(); - } - - @Test - public void wmThrowsRemoteException_shouldReturnDisabled() throws RemoteException { - doThrow(new RemoteException("Unknown")) - .when(mWindowManager).isWindowTraceEnabled(); - assertThat(mWindowTrace.isEnabled()).isFalse(); - } - - @Test - public void setIsEnableTrue_shouldEnableWindowTrace() throws RemoteException { - mWindowTrace.setIsEnabled(true); - verify(mWindowManager).startWindowTrace(); - verifyNoMoreInteractions(mWindowManager); - } - - @Test - @Config(shadows = {ShadowParcel.class}) - public void setIsEnableFalse_shouldDisableWindowTraceAndShowToast() throws RemoteException { - mWindowTrace.setIsEnabled(false); - verify(mWindowManager).stopWindowTrace(); - verify(mToast).show(); - verifyNoMoreInteractions(mWindowManager); - } - - @Test - public void setIsEnableAndWmThrowsRemoteException_shouldDoNothing() throws RemoteException { - doThrow(new RemoteException("Unknown")).when(mWindowManager).isWindowTraceEnabled(); - mWindowTrace.setIsEnabled(true); - } -} diff --git a/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java b/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java new file mode 100644 index 00000000000..92f5c228c06 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/qstile/WinscopeTraceTest.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.development.qstile; + +import static com.android.settings.development.qstile.DevelopmentTiles.WinscopeTrace + .SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE; +import static com.android.settings.development.qstile.DevelopmentTiles.WinscopeTrace + .SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.os.IBinder; +import android.os.RemoteException; +import android.widget.Toast; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.shadow.ShadowParcel; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.wrapper.IWindowManagerWrapper; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.util.ReflectionHelpers; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class WinscopeTraceTest { + @Mock + private IWindowManagerWrapper mWindowManager; + @Mock + private IBinder mSurfaceFlinger; + @Mock + private Toast mToast; + + private DevelopmentTiles.WinscopeTrace mWinscopeTrace; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mWinscopeTrace = spy(new DevelopmentTiles.WinscopeTrace()); + ReflectionHelpers.setField(mWinscopeTrace, "mWindowManager", mWindowManager); + ReflectionHelpers.setField(mWinscopeTrace, "mSurfaceFlinger", mSurfaceFlinger); + ReflectionHelpers.setField(mWinscopeTrace, "mToast", mToast); + } + + @After + public void teardown() { + verifyNoMoreInteractions(mToast); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void wmReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { + // Assume Surface Trace is disabled. + ShadowParcel.sReadBoolResult = false; + doReturn(true).when(mWindowManager).isWindowTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isTrue(); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void sfReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { + // Assume Window Trace is disabled. + doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + ShadowParcel.sReadBoolResult = true; + 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 sfAndWmReturnsTraceEnabled_shouldReturnEnabled() throws RemoteException { + ShadowParcel.sReadBoolResult = true; + doReturn(true).when(mWindowManager).isWindowTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isTrue(); + } + + @Test + public void wmAndSfReturnsTraceDisabled_shouldReturnDisabled() throws RemoteException { + ShadowParcel.sReadBoolResult = false; + doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isFalse(); + verify(mSurfaceFlinger) + .transact(eq(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE), any(), any(), + eq(0 /* flags */)); + verifyNoMoreInteractions(mSurfaceFlinger); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void wmThrowsRemoteExAndSfReturnsTraceDisabled_shouldReturnDisabled() + throws RemoteException { + ShadowParcel.sReadBoolResult = false; + doThrow(new RemoteException("Unknown")) + .when(mWindowManager).isWindowTraceEnabled(); + assertThat(mWinscopeTrace.isEnabled()).isFalse(); + } + + @Test + public void sfUnavailableAndWmReturnsTraceDisabled_shouldReturnDisabled() + throws RemoteException { + doReturn(false).when(mWindowManager).isWindowTraceEnabled(); + ReflectionHelpers.setField(mWinscopeTrace, "mSurfaceFlinger", null); + assertThat(mWinscopeTrace.isEnabled()).isFalse(); + } + + + @Test + public void setIsEnableTrue_shouldEnableWindowTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(true); + verify(mWindowManager).startWindowTrace(); + verifyNoMoreInteractions(mWindowManager); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void setIsEnableTrue_shouldEnableLayerTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(true); + assertThat(ShadowParcel.sWriteIntResult).isEqualTo(1); + verify(mSurfaceFlinger) + .transact(eq(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE), any(), isNull(), + eq(0 /* flags */)); + verifyNoMoreInteractions(mSurfaceFlinger); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void setIsEnableFalse_shouldDisableWindowTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(false); + verify(mWindowManager).stopWindowTrace(); + verifyNoMoreInteractions(mWindowManager); + verify(mToast).show(); + } + + @Test + @Config(shadows = {ShadowParcel.class}) + public void setIsEnableFalse_shouldDisableLayerTrace() throws RemoteException { + mWinscopeTrace.setIsEnabled(false); + assertThat(ShadowParcel.sWriteIntResult).isEqualTo(0); + verify(mSurfaceFlinger) + .transact(eq(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE), any(), isNull(), + eq(0 /* flags */)); + verifyNoMoreInteractions(mSurfaceFlinger); + verify(mToast).show(); + } + + @Test + public void setIsEnableFalse_shouldShowToast() throws RemoteException { + mWinscopeTrace.setIsEnabled(false); + verify(mToast).show(); + } + + /** + * Verify when window manager call throws a remote exception, it is handled without + * re-throwing the exception. + */ + @Test + public void setIsEnableAndWmThrowsRemoteException_shouldFailGracefully() + throws RemoteException { + doThrow(new RemoteException("Unknown")).when(mWindowManager).isWindowTraceEnabled(); + mWinscopeTrace.setIsEnabled(true); + } + + /** + * Verify is surface flinger is not available not calls are made to it. + */ + @Test + public void setIsEnableAndSfUnavailable_shouldFailGracefully() throws RemoteException { + ReflectionHelpers.setField(mWinscopeTrace, "mSurfaceFlinger", null); + mWinscopeTrace.setIsEnabled(true); + verifyNoMoreInteractions(mSurfaceFlinger); + } +}