blob: 9e226f69362234a362b42c719753c0910503ce14 [file] [log] [blame]
/*
* 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.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.anyInt;
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.Manifest;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.text.TextUtils;
import android.util.ArraySet;
import androidx.test.filters.SmallTest;
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.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
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 {
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<>();
private static final String TEST_PKG = "test_pkg";
private static final String TEST_CLS = "test_cls";
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"}));
}
@Mock
private TileQueryHelper.TileStateListener mListener;
@Mock
private QSTileHost mQSTileHost;
@Mock
private PackageManager mPackageManager;
@Captor
private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
private QSTile.State mState;
private TestableLooper mBGLooper;
private TileQueryHelper mTileQueryHelper;
@Before
public void setup() {
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);
}
@Test
public void testIsFinished_falseBeforeQuerying() {
assertFalse(mTileQueryHelper.isFinished());
}
@Test
public void testIsFinished_trueAfterQuerying() {
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
assertTrue(mTileQueryHelper.isFinished());
}
@Test
public void testQueryTiles_callsListenerTwice() {
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
verify(mListener, times(2)).onTilesChanged(any());
}
@Test
public void testQueryTiles_isFinishedFalseOnListenerCalls_thenTrueAfterCompletion() {
doAnswer(invocation -> {
assertFalse(mTileQueryHelper.isFinished());
return null;
}).when(mListener).onTilesChanged(any());
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
assertTrue(mTileQueryHelper.isFinished());
}
@Test
public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() {
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(mCaptor.capture());
List<String> specs = new ArrayList<>();
for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
specs.add(t.spec);
}
String tiles = TextUtils.join(",", specs);
assertThat(tiles, is(equalTo(STOCK_TILES)));
}
@Test
public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() {
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(mCaptor.capture());
List<String> specs = new ArrayList<>();
for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
specs.add(t.spec);
}
String tiles = TextUtils.join(",", specs);
assertThat(tiles, is(equalTo(ALL_TILES)));
}
@Test
public void testQueryTiles_otherTileNotIncluded() {
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(mCaptor.capture());
List<String> specs = new ArrayList<>();
for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
specs.add(t.spec);
}
assertFalse(specs.contains("other"));
}
@Test
public void testThirdPartyTilesInactive() {
ResolveInfo resolveInfo = new ResolveInfo();
ServiceInfo serviceInfo = mock(ServiceInfo.class, Answers.RETURNS_MOCKS);
resolveInfo.serviceInfo = serviceInfo;
serviceInfo.packageName = TEST_PKG;
serviceInfo.name = TEST_CLS;
serviceInfo.icon = R.drawable.android;
serviceInfo.permission = Manifest.permission.BIND_QUICK_SETTINGS_TILE;
serviceInfo.applicationInfo = mock(ApplicationInfo.class, Answers.RETURNS_MOCKS);
serviceInfo.applicationInfo.icon = R.drawable.android;
List<ResolveInfo> list = new ArrayList<>();
list.add(resolveInfo);
when(mPackageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(list);
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, "");
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
"");
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
List<TileQueryHelper.TileInfo> tileInfos = mCaptor.getValue();
assertEquals(1, tileInfos.size());
assertEquals(Tile.STATE_INACTIVE, tileInfos.get(0).state.state);
}
@Test
public void testQueryTiles_nullSetting() {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
mTileQueryHelper.queryTiles(mQSTileHost);
}
}