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

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

Fixes NPE when trying to expand QSPanel with wrong name of tile

Fixes promise of StatusBarManager#expandSettingsPanel to document what
happens on invalid tile name.

Added test to verify correct behavior.

Change-Id: I057210eb47411cf2a7dfefdd4efe49b96fd33f69
Fixes: 111128728
Test: runtest && manual
parent e0ef793d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -208,10 +209,11 @@ public class StatusBarManager {
    }

    /**
     * Expand the settings panel and open a subPanel, pass null to just open the settings panel.
     * Expand the settings panel and open a subPanel. If the subpanel is null or does not have a
     * corresponding tile, the QS panel is simply expanded
     */
    @UnsupportedAppUsage
    public void expandSettingsPanel(String subPanel) {
    public void expandSettingsPanel(@Nullable String subPanel) {
        try {
            final IStatusBarService svc = getService();
            if (svc != null) {
+5 −1
Original line number Diff line number Diff line
@@ -199,8 +199,12 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne

    public void openDetails(String subPanel) {
        QSTile tile = getTile(subPanel);
        // If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
        // QSFactory will not be able to create a tile and getTile will return null
        if (tile != null) {
            showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
        }
    }

    private QSTile getTile(String subPanel) {
        for (int i = 0; i < mRecords.size(); i++) {
+1 −2
Original line number Diff line number Diff line
@@ -2156,7 +2156,7 @@ public class StatusBar extends SystemUI implements DemoMode,
    }

    @Override
    public void animateExpandSettingsPanel(String subPanel) {
    public void animateExpandSettingsPanel(@Nullable String subPanel) {
        if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
        if (!panelsEnabled()) {
            return;
@@ -2165,7 +2165,6 @@ public class StatusBar extends SystemUI implements DemoMode,
        // Settings are not available in setup
        if (!mUserSetup) return;


        if (subPanel != null) {
            mQSPanel.openDetails(subPanel);
        }
+58 −3
Original line number Diff line number Diff line
@@ -14,8 +14,12 @@

package com.android.systemui.qs;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -23,15 +27,21 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizer;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Collections;

@@ -41,19 +51,37 @@ import java.util.Collections;
public class QSPanelTest extends SysuiTestCase {

    private MetricsLogger mMetricsLogger;
    private TestableLooper mTestableLooper;
    private QSPanel mQsPanel;
    @Mock
    private QSTileHost mHost;
    @Mock
    private QSCustomizer mCustomizer;
    @Mock
    private QSTile dndTile;
    private ViewGroup mParentView;
    @Mock
    private QSDetail.Callback mCallback;

    @Before
    public void setup() throws Exception {
        TestableLooper.get(this).runWithLooper(() -> {
        MockitoAnnotations.initMocks(this);

        mTestableLooper = TestableLooper.get(this);
        mTestableLooper.runWithLooper(() -> {
            mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
            mQsPanel = new QSPanel(mContext, null);
            mHost = mock(QSTileHost.class);
            // Provides a parent with non-zero size for QSPanel
            mParentView = new FrameLayout(mContext);
            mParentView.addView(mQsPanel);

            when(dndTile.getTileSpec()).thenReturn("dnd");
            when(mHost.getTiles()).thenReturn(Collections.emptyList());
            mCustomizer = mock(QSCustomizer.class);
            when(mHost.createTileView(any(), anyBoolean())).thenReturn(mock(QSTileView.class));

            mQsPanel.setHost(mHost, mCustomizer);
            mQsPanel.addTile(dndTile, true);
            mQsPanel.setCallback(mCallback);
        });
    }

@@ -64,4 +92,31 @@ public class QSPanelTest extends SysuiTestCase {
        mQsPanel.setExpanded(false);
        verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
    }

    @Test
    public void testOpenDetailsWithExistingTile_NoException() {
        mTestableLooper.processAllMessages();
        mQsPanel.openDetails("dnd");
        mTestableLooper.processAllMessages();

        verify(mCallback).onShowingDetail(any(), anyInt(), anyInt());
    }

/*    @Test
    public void testOpenDetailsWithNullParameter_NoException() {
        mTestableLooper.processAllMessages();
        mQsPanel.openDetails(null);
        mTestableLooper.processAllMessages();

        verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
    }*/

    @Test
    public void testOpenDetailsWithNonExistingTile_NoException() {
        mTestableLooper.processAllMessages();
        mQsPanel.openDetails("invalid-name");
        mTestableLooper.processAllMessages();

        verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
    }
}