Postpone available check for CustomTile
In the case of custom tiles, we don't know if they are available until after initialization. Because it runs async to tile creation, the check in QSTileHost may fail and destroy the tile prematurely. Instead, postpone it until after we've tried to retrieve the service icon. Also, add TileService CTS tests to com.android.systemui.qs TEST_MAPPING. Test: atest SystemUITests Test: atest CtsAppTestCases Fixes: 197970498 Change-Id: Id8d4090cfbfaa144b71d78ffd74da8fc1b9e6c6e
This commit is contained in:
21
packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING
Normal file
21
packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "CtsAppTestCases",
|
||||
"options": [
|
||||
{
|
||||
"include-filter": "android.app.cts.TileServiceTest"
|
||||
},
|
||||
{
|
||||
"include-filter": "android.app.cts.BooleanTileServiceTest"
|
||||
},
|
||||
{
|
||||
"exclude-annotation": "org.junit.Ignore"
|
||||
},
|
||||
{
|
||||
"exclude-annotation": "androidx.test.filters.FlakyTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -63,6 +63,7 @@ import com.android.systemui.qs.logging.QSLogger;
|
||||
import com.android.systemui.qs.tileimpl.QSTileImpl;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -98,6 +99,8 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
|
||||
|
||||
private final TileServiceKey mKey;
|
||||
|
||||
private final AtomicBoolean mInitialDefaultIconFetched = new AtomicBoolean(false);
|
||||
|
||||
private CustomTile(
|
||||
QSHost host,
|
||||
Looper backgroundLooper,
|
||||
@@ -128,6 +131,12 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
|
||||
@Override
|
||||
protected void handleInitialize() {
|
||||
updateDefaultTileAndIcon();
|
||||
if (mInitialDefaultIconFetched.compareAndSet(false, true)) {
|
||||
if (mDefaultIcon == null) {
|
||||
mQSLogger.logTileDestroyed(getTileSpec(),
|
||||
"Custom tile default icon not available");
|
||||
}
|
||||
}
|
||||
if (mServiceManager.isToggleableTile()) {
|
||||
// Replace states with BooleanState
|
||||
resetStates();
|
||||
@@ -213,9 +222,18 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
|
||||
mHandler.post(this::updateDefaultTileAndIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom tile is considered available if there is a default icon (obtained from PM).
|
||||
*
|
||||
* It will return {@code true} before initialization, so tiles are not destroyed prematurely.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mDefaultIcon != null;
|
||||
if (mInitialDefaultIconFetched.get()) {
|
||||
return mDefaultIcon != null;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUser() {
|
||||
|
||||
@@ -105,7 +105,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
protected final ActivityStarter mActivityStarter;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final FalsingManager mFalsingManager;
|
||||
private final QSLogger mQSLogger;
|
||||
protected final QSLogger mQSLogger;
|
||||
private volatile int mReadyState;
|
||||
|
||||
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
|
||||
|
||||
@@ -20,8 +20,8 @@ package com.android.systemui.qs;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -424,7 +424,7 @@ public class QSTileHostTest extends SysuiTestCase {
|
||||
mock(MetricsLogger.class),
|
||||
mock(StatusBarStateController.class),
|
||||
mock(ActivityStarter.class),
|
||||
mQSLogger
|
||||
QSTileHostTest.this.mQSLogger
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -270,4 +270,20 @@ class CustomTileTest : SysuiTestCase() {
|
||||
verify(customTileStatePersister)
|
||||
.persistState(TileServiceKey(componentName, customTile.user), t)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAvailableBeforeInitialization() {
|
||||
`when`(packageManager.getApplicationInfo(anyString(), anyInt()))
|
||||
.thenThrow(PackageManager.NameNotFoundException())
|
||||
val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
|
||||
assertTrue(tile.isAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNotAvailableAfterInitializationWithoutIcon() {
|
||||
val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
|
||||
tile.initialize()
|
||||
testableLooper.processAllMessages()
|
||||
assertFalse(tile.isAvailable)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user