diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 78f9351cfbf..73637956f5c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3420,11 +3420,41 @@ + android:enabled="false"> + + + + + + + + + + + + + + + @@ -3433,11 +3463,7 @@ android:name=".qstile.DevelopmentTileConfigActivity" android:excludeFromRecents="true" android:launchMode="singleInstance" - android:label="@string/developer_tile"> - - - - + android:label="@string/quick_settings_developer_tiles" /> + + + diff --git a/res/drawable/tile_icon_force_rtl.xml b/res/drawable/tile_icon_force_rtl.xml new file mode 100644 index 00000000000..e87bddeeb0e --- /dev/null +++ b/res/drawable/tile_icon_force_rtl.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + diff --git a/res/drawable/tile_icon_graphics.xml b/res/drawable/tile_icon_graphics.xml new file mode 100644 index 00000000000..af611aca947 --- /dev/null +++ b/res/drawable/tile_icon_graphics.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/tile_icon_show_layout.xml b/res/drawable/tile_icon_show_layout.xml new file mode 100644 index 00000000000..e23b24cd945 --- /dev/null +++ b/res/drawable/tile_icon_show_layout.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/development_tile_config_header.xml b/res/layout/development_tile_config_header.xml deleted file mode 100644 index 5169da23c05..00000000000 --- a/res/layout/development_tile_config_header.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index cd9da3b97e2..625b5a310b1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7757,12 +7757,6 @@ Smallest width - - Development mode - - - No active state selected - No installed apps have requested Premium SMS access @@ -7778,6 +7772,9 @@ System UI demo mode + + Quick settings developer tiles + We\'re here to help diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml index b8043c9657e..4d039a6072c 100644 --- a/res/xml/development_prefs.xml +++ b/res/xml/development_prefs.xml @@ -102,6 +102,14 @@ + + + + diff --git a/res/xml/development_tile_prefs.xml b/res/xml/development_tile_prefs.xml deleted file mode 100644 index 26f1c24e051..00000000000 --- a/res/xml/development_tile_prefs.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 8869c5da6b5..179b31bd132 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -62,7 +62,6 @@ import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardSummary; import com.android.settings.dashboard.SearchResultsSummary; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.qstile.DevelopmentModeTile; import com.android.settings.search.DynamicIndexableContentMonitor; import com.android.settings.search2.SearchFeatureProvider; import com.android.settings.widget.SwitchBar; @@ -941,9 +940,6 @@ public class SettingsActivity extends SettingsDrawerActivity Settings.DevelopmentSettingsActivity.DASHBOARD_ALIAS), showDev, isAdmin); - // Reveal development-only quick settings tiles - setTileEnabled(new ComponentName(this, DevelopmentModeTile.class), showDev); - if (UserHandle.MU_ENABLED && !isAdmin) { // When on restricted users, disable all extra categories (but only the settings ones). List categories; diff --git a/src/com/android/settings/qstile/DevelopmentModeTile.java b/src/com/android/settings/qstile/DevelopmentModeTile.java deleted file mode 100644 index 578ffd8f291..00000000000 --- a/src/com/android/settings/qstile/DevelopmentModeTile.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2016 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.qstile; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.provider.Settings; -import android.service.quicksettings.Tile; -import android.service.quicksettings.TileService; -import android.view.IWindowManager; -import android.view.ThreadedRenderer; -import android.view.View; - -import android.view.WindowManagerGlobal; -import com.android.internal.app.LocalePicker; -import com.android.settings.DevelopmentSettings; - -import java.util.Map; - -public class DevelopmentModeTile extends TileService { - - static final String SHARED_PREFERENCES_NAME = "development_mode_tile_settings"; - - private static final String SHOW_TOUCHES_KEY = "show_touches"; - private static final String POINTER_LOCATION_KEY = "pointer_location"; - private static final String DEBUG_LAYOUT_KEY = "debug_layout"; - private static final String FORCE_RTL_LAYOUT_KEY = "force_rtl_layout_all_locales"; - private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale"; - private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale"; - private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale"; - private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates"; - private static final String SHOW_HW_LAYERS_UPDATES_KEY = "show_hw_layers_udpates"; - private static final String DEBUG_HW_OVERDRAW_KEY = "debug_hw_overdraw"; - private static final String TRACK_FRAME_TIME_KEY = "track_frame_time"; - - private DevModeProperties mProps = new DevModeProperties(); - - @Override - public void onStartListening() { - super.onStartListening(); - refresh(); - } - - public void refresh() { - mProps.refreshState(this); - getQsTile().setState(mProps.isSet ? (mProps.allMatch - ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE) : Tile.STATE_UNAVAILABLE); - getQsTile().updateTile(); - } - - @Override - public void onClick() { - if (getQsTile().getState() == Tile.STATE_UNAVAILABLE) { - startActivityAndCollapse(new Intent(this, DevelopmentTileConfigActivity.class)); - return; - } - - boolean active = getQsTile().getState() == Tile.STATE_INACTIVE; - Map values = - getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE).getAll(); - ContentResolver cr = getContentResolver(); - for (Property prop : mProps.mSysProps) { - Object expected = values.get(prop.prefKey); - String value = active && !prop.isDefault(expected) ? expected.toString() : "false"; - SystemProperties.set(prop.key, value); - } - for (Property prop : mProps.mSysSettings) { - boolean expectedTrue = active && !prop.isDefault(values.get(prop.prefKey)); - Settings.System.putInt(cr, prop.key, expectedTrue ? 1 : 0); - } - - boolean expectedGlobPropTrue = active && - !mProps.mGlobProp.isDefault(values.get(mProps.mGlobProp.prefKey)); - Settings.Global.putInt(cr, mProps.mGlobProp.key, expectedGlobPropTrue ? 1 : 0); - SystemProperties.set(mProps.mGlobProp.key, expectedGlobPropTrue ? "1" : "0"); - LocalePicker.updateLocales(getResources().getConfiguration().getLocales()); - - IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - try { - // Update the various animation scale values to expected values or 1. mProps.mAnimScales - // is an ordered array, where the index corresponds to the individual property. - for (int i = 0; i < mProps.mAnimScales.length; i++) { - Object expected = values.get(mProps.mAnimScales[i]); - float expectedFloat = active && expected != null ? - Float.parseFloat(expected.toString()) : 1; - wm.setAnimationScale(i, expectedFloat); - } - } catch (RemoteException e) { } - - new DevelopmentSettings.SystemPropPoker().execute(); // Settings app magic - refresh(); - } - - static class DevModeProperties { - - private final Property[] mSysProps = new Property[] { - new Property(View.DEBUG_LAYOUT_PROPERTY, DEBUG_LAYOUT_KEY), - new Property(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, - SHOW_HW_SCREEN_UPDATES_KEY), - new Property(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, - SHOW_HW_LAYERS_UPDATES_KEY), - new Property(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY, DEBUG_HW_OVERDRAW_KEY), - new Property(ThreadedRenderer.PROFILE_PROPERTY, TRACK_FRAME_TIME_KEY), - }; - - private final Property[] mSysSettings = new Property[] { - new Property(Settings.System.SHOW_TOUCHES, SHOW_TOUCHES_KEY), - new Property(Settings.System.POINTER_LOCATION, POINTER_LOCATION_KEY), - }; - - private final Property mGlobProp = - new Property(Settings.Global.DEVELOPMENT_FORCE_RTL, FORCE_RTL_LAYOUT_KEY); - - private final String[] mAnimScales = new String[] { - WINDOW_ANIMATION_SCALE_KEY, - TRANSITION_ANIMATION_SCALE_KEY, - ANIMATOR_DURATION_SCALE_KEY - }; - - /** - * True is the values of all the properties corresponds to the expected values. Updated when - * {@link #refreshState(Context)} is called. - */ - public boolean allMatch; - /** - * True is at least one property has a non-default expected value. Updated when - * {@link #refreshState(Context)} is called. Not that if all properties have default - * expected value, then active and non-active state will be the same. - */ - public boolean isSet; - - public void refreshState(Context context) { - Map values = - context.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE).getAll(); - allMatch = true; - // True if there is at least one non-default value. - isSet = false; - - for (Property prop : mSysProps) { - Object expected = values.get(prop.prefKey); - String actual = SystemProperties.get(prop.key); - allMatch &= prop.isDefault(expected) - ? prop.isDefault(actual) : expected.toString().equals(actual); - isSet |= !prop.isDefault(expected); - } - - ContentResolver cr = context.getContentResolver(); - for (Property prop : mSysSettings) { - boolean expectedTrue = !prop.isDefault(values.get(prop.prefKey)); - isSet |= expectedTrue; - allMatch &= expectedTrue == (Settings.System.getInt(cr, prop.key, 0) != 0); - } - - boolean expectedGlopPropTrue = !mGlobProp.isDefault(values.get(mGlobProp.prefKey)); - isSet |= expectedGlopPropTrue; - allMatch &= expectedGlopPropTrue == (Settings.Global.getInt(cr, mGlobProp.key, 0) != 0); - - IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - try { - for (int i = 0; i < mAnimScales.length; i++) { - Object expected = values.get(mAnimScales[i]); - float expectedFloat = expected == null - ? 1 : Float.parseFloat(expected.toString()); - isSet |= expectedFloat != 1; - allMatch &= expectedFloat == wm.getAnimationScale(i); - } - } catch (RemoteException e) { } - } - } - - private static class Property { - final String key; - final String prefKey; - - Property(String key, String prefKey) { - this.key = key; - this.prefKey = prefKey; - } - - boolean isDefault(Object value) { - if (value == null) { - return true; - } - String str = value.toString(); - return str.equals("") || str.equals("false"); - } - } -} diff --git a/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java b/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java index cc63026645e..5968d7a0896 100644 --- a/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java +++ b/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java @@ -16,16 +16,20 @@ package com.android.settings.qstile; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.os.Bundle; -import android.view.View; +import android.service.quicksettings.TileService; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.Preference; -import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.instrumentation.Instrumentable; -import com.android.settings.widget.SwitchBar; public class DevelopmentTileConfigActivity extends SettingsActivity { @@ -42,35 +46,38 @@ public class DevelopmentTileConfigActivity extends SettingsActivity { return (DevelopmentTileConfigFragment.class.getName().equals(fragmentName)); } - public static class DevelopmentTileConfigFragment extends SettingsPreferenceFragment implements - SharedPreferences.OnSharedPreferenceChangeListener { - - private DevelopmentModeTile.DevModeProperties mProps = - new DevelopmentModeTile.DevModeProperties(); - - private SwitchBar mSwitchBar; - private View mDisabledMessage; + public static class DevelopmentTileConfigFragment extends SettingsPreferenceFragment + implements Preference.OnPreferenceChangeListener { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - getPreferenceManager() - .setSharedPreferencesName(DevelopmentModeTile.SHARED_PREFERENCES_NAME); - addPreferencesFromResource(R.xml.development_tile_prefs); - } - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - mDisabledMessage = setPinnedHeaderView(R.layout.development_tile_config_header); - refreshHeader(); - } + Context context = getPrefContext(); + setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context)); + getPreferenceScreen().removeAll(); - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); - mSwitchBar.setEnabled(false); + Intent intent = new Intent(TileService.ACTION_QS_TILE) + .setPackage(context.getPackageName()); + PackageManager pm = getPackageManager(); + for (ResolveInfo info : + pm.queryIntentServices(intent, PackageManager.MATCH_DISABLED_COMPONENTS)) { + ServiceInfo sInfo = info.serviceInfo; + int enabledSetting = pm.getComponentEnabledSetting( + new ComponentName(sInfo.packageName, sInfo.name)); + boolean checked = enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED + || ((enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) + && sInfo.enabled); + + SwitchPreference preference = new SwitchPreference(context); + preference.setTitle(sInfo.loadLabel(pm)); + preference.setIcon(sInfo.icon); + preference.setKey(sInfo.name); + preference.setChecked(checked); + preference.setPersistent(false); + preference.setOnPreferenceChangeListener(this); + getPreferenceScreen().addPreference(preference); + } } @Override @@ -79,37 +86,14 @@ public class DevelopmentTileConfigActivity extends SettingsActivity { } @Override - public void onResume() { - super.onResume(); - refreshHeader(); - getPreferenceManager().getSharedPreferences() - .registerOnSharedPreferenceChangeListener(this); - } - - @Override - public void onPause() { - super.onPause(); - getPreferenceManager().getSharedPreferences() - .unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - refreshHeader(); - } - - private void refreshHeader() { - if (mSwitchBar != null && mDisabledMessage != null) { - mProps.refreshState(getActivity()); - if (mProps.isSet) { - mSwitchBar.show(); - mDisabledMessage.setVisibility(View.GONE); - } else { - mSwitchBar.hide(); - mDisabledMessage.setVisibility(View.VISIBLE); - } - mSwitchBar.setChecked(mProps.allMatch); - } + public boolean onPreferenceChange(Preference preference, Object newValue) { + ComponentName cn = new ComponentName( + getPrefContext().getPackageName(), preference.getKey()); + getPackageManager().setComponentEnabledSetting(cn, (Boolean) newValue + ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + return true; } } -} +} \ No newline at end of file diff --git a/src/com/android/settings/qstile/DevelopmentTiles.java b/src/com/android/settings/qstile/DevelopmentTiles.java new file mode 100644 index 00000000000..635e9f06e1c --- /dev/null +++ b/src/com/android/settings/qstile/DevelopmentTiles.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 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.qstile; + +import android.os.RemoteException; +import android.os.SystemProperties; +import android.provider.Settings; +import android.service.quicksettings.Tile; +import android.service.quicksettings.TileService; +import android.view.IWindowManager; +import android.view.ThreadedRenderer; +import android.view.View; +import android.view.WindowManagerGlobal; + +import com.android.internal.app.LocalePicker; +import com.android.settings.DevelopmentSettings; + +public abstract class DevelopmentTiles extends TileService { + + protected abstract boolean isEnabled(); + + protected abstract void setIsEnabled(boolean isEnabled); + + @Override + public void onStartListening() { + super.onStartListening(); + refresh(); + } + + public void refresh() { + getQsTile().setState(isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); + getQsTile().updateTile(); + } + + @Override + public void onClick() { + setIsEnabled(getQsTile().getState() == Tile.STATE_INACTIVE); + new DevelopmentSettings.SystemPropPoker().execute(); // Settings app magic + refresh(); + } + + /** + * Tile to control the "Show layout bounds" developer setting + */ + public static class ShowLayout extends DevelopmentTiles { + + @Override + protected boolean isEnabled() { + return SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false); + } + + @Override + protected void setIsEnabled(boolean isEnabled) { + SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY, isEnabled ? "true" : "false"); + } + } + + /** + * Tile to control the "GPU profiling" developer setting + */ + public static class GPUProfiling extends DevelopmentTiles { + + @Override + protected boolean isEnabled() { + final String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY); + return value.equals("visual_bars"); + } + + @Override + protected void setIsEnabled(boolean isEnabled) { + SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY, isEnabled ? "visual_bars" : ""); + } + } + + /** + * Tile to control the "Force RTL" developer setting + */ + public static class ForceRTL extends DevelopmentTiles { + + @Override + protected boolean isEnabled() { + return Settings.Global.getInt( + getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0; + } + + @Override + protected void setIsEnabled(boolean isEnabled) { + Settings.Global.putInt( + getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? 1 : 0); + SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? "1" : "0"); + LocalePicker.updateLocales(getResources().getConfiguration().getLocales()); + } + } + + /** + * Tile to control the "Animation speed" developer setting + */ + public static class AnimationSpeed extends DevelopmentTiles { + + @Override + protected boolean isEnabled() { + IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + try { + return wm.getAnimationScale(0) != 1; + } catch (RemoteException e) { } + return false; + } + + @Override + protected void setIsEnabled(boolean isEnabled) { + IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + float scale = isEnabled ? 10 : 1; + try { + wm.setAnimationScale(0, scale); + wm.setAnimationScale(1, scale); + wm.setAnimationScale(2, scale); + } catch (RemoteException e) { } + } + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/qstile/DevelopmentModeTileTest.java b/tests/robotests/src/com/android/settings/qstile/DevelopmentModeTileTest.java deleted file mode 100644 index a30bd47ca2f..00000000000 --- a/tests/robotests/src/com/android/settings/qstile/DevelopmentModeTileTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.android.settings.qstile; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Intent; -import android.service.quicksettings.Tile; - -import com.android.settings.SettingsRobolectricTestRunner; -import com.android.settings.TestConfig; -import com.android.settings.testutils.shadow.ShadowTileService; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.Robolectric; -import org.robolectric.annotation.Config; -import org.robolectric.internal.ShadowExtractor; -import org.robolectric.util.ReflectionHelpers; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, - shadows = ShadowTileService.class) -public class DevelopmentModeTileTest { - - @Mock private Tile mTile; - @Mock private DevelopmentModeTile.DevModeProperties mProps; - - private DevelopmentModeTile mDevelopmentModeTile; - private ShadowTileService mShadowTileService; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mDevelopmentModeTile = Robolectric.buildService(DevelopmentModeTile.class).get(); - - ReflectionHelpers.setField(mDevelopmentModeTile, "mProps", mProps); - mShadowTileService = (ShadowTileService) ShadowExtractor.extract(mDevelopmentModeTile); - mShadowTileService.setTile(mTile); - } - - @Test - public void refresh() { - verifyRefreshState(false, true, Tile.STATE_UNAVAILABLE); - verifyRefreshState(false, false, Tile.STATE_UNAVAILABLE); - verifyRefreshState(true, false, Tile.STATE_INACTIVE); - verifyRefreshState(true, true, Tile.STATE_ACTIVE); - } - - @Test - public void onClick_startSetting() { - when(mTile.getState()).thenReturn(Tile.STATE_UNAVAILABLE); - mDevelopmentModeTile.onClick(); - - Intent intent = mShadowTileService.getNextStartedActivity(); - assertEquals(DevelopmentTileConfigActivity.class.getName(), - intent.getComponent().getClassName()); - } - - private void verifyRefreshState(boolean isSet, boolean allMatch, int expectedState) { - reset(mProps, mTile); - - mProps.isSet = isSet; - mProps.allMatch = allMatch; - mDevelopmentModeTile.refresh(); - - verify(mProps).refreshState(eq(mDevelopmentModeTile)); - verify(mTile).setState(eq(expectedState)); - } -}