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

Commit cb69baf8 authored by Doris Ling's avatar Doris Ling
Browse files

Fix crash when switching to fragment with null name.

Check for null fragment name before trying to launch the fragment.

Change-Id: Ibee6f7a1f27f7bc7d556a600c7e43fd30c2f1d6c
Fix: 35203478
Test: make RunSettingsRoboTests
parent 3ee0f4f5
Loading
Loading
Loading
Loading
+30 −65
Original line number Diff line number Diff line
@@ -236,7 +236,6 @@ public class SettingsActivity extends SettingsDrawerActivity
    private DashboardFeatureProvider mDashboardFeatureProvider;
    private Intent mResultIntentData;
    private ComponentName mCurrentSuggestion;
    private final StringBuffer mDebugData = new StringBuffer();

    @VisibleForTesting
    String mSearchQuery;
@@ -433,34 +432,7 @@ public class SettingsActivity extends SettingsDrawerActivity
            mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);

        } else {
            if (!mIsShowingDashboard) {
                if (initialFragmentName == null) {
                    logFragmentData(intent, className, isSubSettings);
                }
                mDisplaySearch = false;
                // UP will be shown only if it is a sub settings
                if (mIsShortcut) {
                    mDisplayHomeAsUpEnabled = isSubSettings;
                } else if (isSubSettings) {
                    mDisplayHomeAsUpEnabled = true;
                } else {
                    mDisplayHomeAsUpEnabled = false;
                }
                setTitleFromIntent(intent);

                Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
                switchToFragment(initialFragmentName, initialArguments, true, false,
                        mInitialTitleResId, mInitialTitle, false);
            } else {
                // No UP affordance if we are displaying the main Dashboard
                mDisplayHomeAsUpEnabled = false;
                // Show Search affordance
                mDisplaySearch = true;
                mInitialTitleResId = R.string.dashboard_title;

                switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
                            mInitialTitleResId, mInitialTitle, false);
            }
            launchSettingFragment(initialFragmentName, isSubSettings, intent);
        }

        mActionBar = getActionBar();
@@ -532,6 +504,35 @@ public class SettingsActivity extends SettingsDrawerActivity
        }
    }

    @VisibleForTesting
    void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
        if (!mIsShowingDashboard && initialFragmentName != null) {
            mDisplaySearch = false;
            // UP will be shown only if it is a sub settings
            if (mIsShortcut) {
                mDisplayHomeAsUpEnabled = isSubSettings;
            } else if (isSubSettings) {
                mDisplayHomeAsUpEnabled = true;
            } else {
                mDisplayHomeAsUpEnabled = false;
            }
            setTitleFromIntent(intent);

            Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
            switchToFragment(initialFragmentName, initialArguments, true, false,
                mInitialTitleResId, mInitialTitle, false);
        } else {
            // No UP affordance if we are displaying the main Dashboard
            mDisplayHomeAsUpEnabled = false;
            // Show Search affordance
            mDisplaySearch = true;
            mInitialTitleResId = R.string.dashboard_title;

            switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
                mInitialTitleResId, mInitialTitle, false);
        }
    }

    public void setDisplaySearchMenu(boolean displaySearch) {
        if (displaySearch != mDisplaySearch) {
            mDisplaySearch = displaySearch;
@@ -693,7 +694,6 @@ public class SettingsActivity extends SettingsDrawerActivity
        String startingFragment = getStartingFragmentClass(superIntent);
        // This is called from super.onCreate, isMultiPane() is not yet reliable
        // Do not use onIsHidingHeaders either, which relies itself on this method
        log("getIntent() startingFragment", startingFragment);
        if (startingFragment != null) {
            Intent modIntent = new Intent(superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
@@ -715,11 +715,9 @@ public class SettingsActivity extends SettingsDrawerActivity
     * returns the class name to load as a fragment.
     */
    private String getStartingFragmentClass(Intent intent) {
        log("getStartingFragmentClass() mFragmentClass", mFragmentClass);
        if (mFragmentClass != null) return mFragmentClass;

        String intentClass = intent.getComponent().getClassName();
        log("getStartingFragmentClass() intentClass", intentClass);
        if (intentClass.equals(getClass().getName())) return null;

        if ("com.android.settings.ManageApplications".equals(intentClass)
@@ -1125,37 +1123,4 @@ public class SettingsActivity extends SettingsDrawerActivity
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void logFragmentData(Intent intent, String className, boolean isSubSettings) {
        if (intent != null) {
            logBundleData(intent.getExtras(), "Intent extra");
            logBundleData(intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS), "Fragment args");
        } else {
            log("Intent data", "NULL");
        }
        log("Fragment", mFragmentClass);
        log("Shortcut", mIsShortcut);
        log("Class Name", className);
        log("Show dashboard", mIsShowingDashboard);
        log("Sub setting", isSubSettings);
        log("Title", mInitialTitle);
        Log.d(LOG_TAG, mDebugData.toString());
        mDebugData.delete(0, mDebugData.length());
    }

    private void logBundleData(Bundle data, String name) {
        if (data != null) {
            final Set<String> keys = data.keySet();
            mDebugData.append(name).append(": ");
            for (String key : keys) {
                log(key, data.get(key));
            }
        } else {
            log(name, "NULL");
        }
    }

    private void log(String key, Object data) {
        mDebugData.append(key).append("=").append(data).append(", ");
    }
}
+41 −0
Original line number Diff line number Diff line
@@ -16,18 +16,47 @@

package com.android.settings;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import com.android.settings.testutils.FakeFeatureFactory;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SettingsActivityTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Context mContext;
    @Mock
    private FragmentManager mFragmentManager;

    private SettingsActivity mActivity;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        FakeFeatureFactory.setupForTest(mContext);
        final FakeFeatureFactory factory =
            (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
    }

    @Test
    public void testQueryTextChange_shouldUpdate() {
        final String testQuery = "abc";
@@ -42,4 +71,16 @@ public class SettingsActivityTest {

        assertThat(mActivity.mSearchQuery).isEqualTo(testQuery);
    }

    @Test
    public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash()
            throws ClassNotFoundException {
        mActivity = spy(new SettingsActivity());
        when(mActivity.getFragmentManager()).thenReturn(mFragmentManager);
        when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));

        doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();

        mActivity.launchSettingFragment(null, true, mock(Intent.class));
    }
}