Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8ffbd32 authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

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
parent 680d2625
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
{
  "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"
        }
      ]
    }
  ]
}
 No newline at end of file
+19 −1
Original line number Diff line number Diff line
@@ -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() {
        if (mInitialDefaultIconFetched.get()) {
            return mDefaultIcon != null;
        } else {
            return true;
        }
    }

    public int getUser() {
+1 −1
Original line number Diff line number Diff line
@@ -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<>();
+2 −2
Original line number Diff line number Diff line
@@ -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
            );
        }

+16 −0
Original line number Diff line number Diff line
@@ -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)
    }
}
 No newline at end of file