Loading packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +19 −5 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.service.quicksettings.TileService; import android.text.TextUtils; import android.util.ArraySet; Loading Loading @@ -69,7 +70,8 @@ public class TileQueryHelper { mSpecs.clear(); mFinished = false; // Enqueue jobs to fetch every system tile and then ever package tile. addStockTiles(host); addCurrentAndStockTiles(host); addPackageTiles(host); } Loading @@ -77,16 +79,28 @@ public class TileQueryHelper { return mFinished; } private void addStockTiles(QSTileHost host) { String possible = mContext.getString(R.string.quick_settings_tiles_stock); private void addCurrentAndStockTiles(QSTileHost host) { String stock = mContext.getString(R.string.quick_settings_tiles_stock); String current = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.QS_TILES); final ArrayList<String> possibleTiles = new ArrayList<>(); possibleTiles.addAll(Arrays.asList(possible.split(","))); if (Build.IS_DEBUGGABLE) { if (current != null) { // The setting QS_TILES is not populated immediately upon Factory Reset possibleTiles.addAll(Arrays.asList(current.split(","))); } String[] stockSplit = stock.split(","); for (String spec : stockSplit) { if (!current.contains(spec)) { possibleTiles.add(spec); } } if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) { possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC); } final ArrayList<QSTile> tilesToAdd = new ArrayList<>(); for (String spec : possibleTiles) { // Only add current and stock tiles that can be created from QSFactoryImpl final QSTile tile = host.createTile(spec); if (tile == null) { continue; Loading packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ public class QSFactoryImpl implements QSFactory { } // Broken tiles. Log.w(TAG, "Bad tile spec: " + tileSpec); Log.w(TAG, "No stock tile spec: " + tileSpec); return null; } Loading packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java +124 −4 Original line number Diff line number Diff line Loading @@ -14,41 +14,76 @@ package com.android.systemui.qs.customize; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.pm.PackageManager; import android.provider.Settings; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.text.TextUtils; import android.util.ArraySet; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.QSTileHost; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper public class TileQueryHelperTest extends SysuiTestCase { @Mock private TileQueryHelper.TileStateListener mListener; @Mock private QSTileHost mQSTileHost; private static final String CURRENT_TILES = "wifi,dnd,nfc"; private static final String ONLY_STOCK_TILES = "wifi,dnd"; private static final String WITH_OTHER_TILES = "wifi,dnd,other"; // Note no nfc in stock tiles private static final String STOCK_TILES = "wifi,dnd,cell,battery"; private static final String ALL_TILES = "wifi,dnd,nfc,cell,battery"; private static final Set<String> FACTORY_TILES = new ArraySet<>(); static { FACTORY_TILES.addAll(Arrays.asList( new String[]{"wifi", "bt", "cell", "dnd", "inversion", "airplane", "work", "rotation", "flashlight", "location", "cast", "hotspot", "user", "battery", "saver", "night", "nfc"})); } private TestableLooper mBGLooper; @Mock private TileQueryHelper.TileStateListener mListener; @Mock private QSTileHost mQSTileHost; @Mock private PackageManager mPackageManager; private QSTile.State mState; private TestableLooper mBGLooper; private TileQueryHelper mTileQueryHelper; @Before Loading @@ -56,6 +91,23 @@ public class TileQueryHelperTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mBGLooper = TestableLooper.get(this); mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper()); mContext.setMockPackageManager(mPackageManager); mState = new QSTile.State(); doAnswer(invocation -> { String spec = (String) invocation.getArguments()[0]; if (FACTORY_TILES.contains(spec)) { QSTile m = mock(QSTile.class); when(m.isAvailable()).thenReturn(true); when(m.getTileSpec()).thenReturn(spec); when(m.getState()).thenReturn(mState); return m; } else { return null; } } ).when(mQSTileHost).createTile(anyString()); mTileQueryHelper = new TileQueryHelper(mContext, mListener); } Loading Loading @@ -98,4 +150,72 @@ public class TileQueryHelperTest extends SysuiTestCase { assertTrue(mTileQueryHelper.isFinished()); } @Test public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, ONLY_STOCK_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } String tiles = TextUtils.join(",", specs); assertThat(tiles, is(equalTo(STOCK_TILES))); } @Test public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, CURRENT_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } String tiles = TextUtils.join(",", specs); assertThat(tiles, is(equalTo(ALL_TILES))); } @Test public void testQueryTiles_otherTileNotIncluded() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, WITH_OTHER_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } assertFalse(specs.contains("other")); } } Loading
packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +19 −5 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.service.quicksettings.TileService; import android.text.TextUtils; import android.util.ArraySet; Loading Loading @@ -69,7 +70,8 @@ public class TileQueryHelper { mSpecs.clear(); mFinished = false; // Enqueue jobs to fetch every system tile and then ever package tile. addStockTiles(host); addCurrentAndStockTiles(host); addPackageTiles(host); } Loading @@ -77,16 +79,28 @@ public class TileQueryHelper { return mFinished; } private void addStockTiles(QSTileHost host) { String possible = mContext.getString(R.string.quick_settings_tiles_stock); private void addCurrentAndStockTiles(QSTileHost host) { String stock = mContext.getString(R.string.quick_settings_tiles_stock); String current = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.QS_TILES); final ArrayList<String> possibleTiles = new ArrayList<>(); possibleTiles.addAll(Arrays.asList(possible.split(","))); if (Build.IS_DEBUGGABLE) { if (current != null) { // The setting QS_TILES is not populated immediately upon Factory Reset possibleTiles.addAll(Arrays.asList(current.split(","))); } String[] stockSplit = stock.split(","); for (String spec : stockSplit) { if (!current.contains(spec)) { possibleTiles.add(spec); } } if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) { possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC); } final ArrayList<QSTile> tilesToAdd = new ArrayList<>(); for (String spec : possibleTiles) { // Only add current and stock tiles that can be created from QSFactoryImpl final QSTile tile = host.createTile(spec); if (tile == null) { continue; Loading
packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ public class QSFactoryImpl implements QSFactory { } // Broken tiles. Log.w(TAG, "Bad tile spec: " + tileSpec); Log.w(TAG, "No stock tile spec: " + tileSpec); return null; } Loading
packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java +124 −4 Original line number Diff line number Diff line Loading @@ -14,41 +14,76 @@ package com.android.systemui.qs.customize; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.pm.PackageManager; import android.provider.Settings; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.text.TextUtils; import android.util.ArraySet; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.QSTileHost; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper public class TileQueryHelperTest extends SysuiTestCase { @Mock private TileQueryHelper.TileStateListener mListener; @Mock private QSTileHost mQSTileHost; private static final String CURRENT_TILES = "wifi,dnd,nfc"; private static final String ONLY_STOCK_TILES = "wifi,dnd"; private static final String WITH_OTHER_TILES = "wifi,dnd,other"; // Note no nfc in stock tiles private static final String STOCK_TILES = "wifi,dnd,cell,battery"; private static final String ALL_TILES = "wifi,dnd,nfc,cell,battery"; private static final Set<String> FACTORY_TILES = new ArraySet<>(); static { FACTORY_TILES.addAll(Arrays.asList( new String[]{"wifi", "bt", "cell", "dnd", "inversion", "airplane", "work", "rotation", "flashlight", "location", "cast", "hotspot", "user", "battery", "saver", "night", "nfc"})); } private TestableLooper mBGLooper; @Mock private TileQueryHelper.TileStateListener mListener; @Mock private QSTileHost mQSTileHost; @Mock private PackageManager mPackageManager; private QSTile.State mState; private TestableLooper mBGLooper; private TileQueryHelper mTileQueryHelper; @Before Loading @@ -56,6 +91,23 @@ public class TileQueryHelperTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mBGLooper = TestableLooper.get(this); mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper()); mContext.setMockPackageManager(mPackageManager); mState = new QSTile.State(); doAnswer(invocation -> { String spec = (String) invocation.getArguments()[0]; if (FACTORY_TILES.contains(spec)) { QSTile m = mock(QSTile.class); when(m.isAvailable()).thenReturn(true); when(m.getTileSpec()).thenReturn(spec); when(m.getState()).thenReturn(mState); return m; } else { return null; } } ).when(mQSTileHost).createTile(anyString()); mTileQueryHelper = new TileQueryHelper(mContext, mListener); } Loading Loading @@ -98,4 +150,72 @@ public class TileQueryHelperTest extends SysuiTestCase { assertTrue(mTileQueryHelper.isFinished()); } @Test public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, ONLY_STOCK_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } String tiles = TextUtils.join(",", specs); assertThat(tiles, is(equalTo(STOCK_TILES))); } @Test public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, CURRENT_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } String tiles = TextUtils.join(",", specs); assertThat(tiles, is(equalTo(ALL_TILES))); } @Test public void testQueryTiles_otherTileNotIncluded() { ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class); Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, WITH_OTHER_TILES); mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock, STOCK_TILES); mTileQueryHelper.queryTiles(mQSTileHost); mBGLooper.processAllMessages(); waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER)); verify(mListener, atLeastOnce()).onTilesChanged(captor.capture()); List<String> specs = new ArrayList<>(); for (TileQueryHelper.TileInfo t : captor.getValue()) { specs.add(t.spec); } assertFalse(specs.contains("other")); } }