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

Commit 890d8d5a authored by Brian Isganitis's avatar Brian Isganitis
Browse files

Give each preference screen its own activity and toolbar title

This change is in preparation for each preference screen having its own collapsible toolbar with its specific title.

Test: Subsettings open with activity transition and title changes
Bug: 187732263
Change-Id: Iac44d688539195ddb6c2aca0a96d737ce7727071
parent a07c2efd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -45,9 +45,14 @@ android_robolectric_test {
    java_resources: [":launcher3-robolectric-resources"],
    static_libs: [
        "truth-prebuilt",
        "androidx.test.espresso.contrib",
        "androidx.test.espresso.core",
        "androidx.test.espresso.intents",
        "androidx.test.ext.junit",
        "androidx.test.runner",
        "androidx.test.rules",
        "mockito-robolectric-prebuilt",
        "SystemUISharedLib",
    ],
    robolectric_prebuilt_version: "4.5.1",
    instrumentation_for: "Launcher3",
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.launcher3.settings;

import static androidx.preference.PreferenceFragmentCompat.ARG_PREFERENCE_ROOT;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.matcher.BundleMatchers.hasEntry;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT;
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARGS;

import static com.google.common.truth.Truth.assertThat;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.preference.PreferenceFragmentCompat;
import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.espresso.intent.Intents;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.launcher3.R;
import com.android.systemui.shared.plugins.PluginPrefs;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class SettingsActivityTest {

    private Context mApplicationContext;

    @Before
    public void setUp() {
        mApplicationContext = ApplicationProvider.getApplicationContext();
        Intents.init();
    }

    @After
    public void tearDown() {
        Intents.release();
    }

    @Test
    public void testSettings_aboutTap_launchesActivity() {
        ActivityScenario.launch(SettingsActivity.class);
        onView(withId(R.id.recycler_view)).perform(
                actionOnItem(hasDescendant(withText("About")), click()));

        intended(allOf(
                hasComponent(SettingsActivity.class.getName()),
                hasExtra(
                        equalTo(EXTRA_FRAGMENT_ARGS),
                        hasEntry(ARG_PREFERENCE_ROOT, "about_screen"))));
    }

    @Test
    public void testSettings_developerOptionsTap_launchesActivityWithFragment() {
        PluginPrefs.setHasPlugins(mApplicationContext);
        ActivityScenario.launch(SettingsActivity.class);
        onView(withId(R.id.recycler_view)).perform(
                actionOnItem(hasDescendant(withText("Developer Options")), click()));

        intended(allOf(
                hasComponent(SettingsActivity.class.getName()),
                hasExtra(EXTRA_FRAGMENT, DeveloperOptionsFragment.class.getName())));
    }

    @Test
    public void testSettings_aboutScreenIntent() {
        Bundle fragmentArgs = new Bundle();
        fragmentArgs.putString(ARG_PREFERENCE_ROOT, "about_screen");

        Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
                .putExtra(EXTRA_FRAGMENT_ARGS, fragmentArgs);
        ActivityScenario.launch(intent);

        onView(withText("About")).check(matches(isDisplayed()));
        onView(withText("Version")).check(matches(isDisplayed()));
    }

    @Test
    public void testSettings_developerOptionsFragmentIntent() {
        Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
                .putExtra(EXTRA_FRAGMENT, DeveloperOptionsFragment.class.getName());
        ActivityScenario.launch(intent);

        onView(withText("Developer Options")).check(matches(isDisplayed()));
        onView(withId(R.id.filter_box)).check(matches(isDisplayed()));
    }

    @Test
    public void testSettings_intentWithUnknownFragment() {
        String fragmentClass = PreferenceFragmentCompat.class.getName();
        Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
                .putExtra(EXTRA_FRAGMENT, fragmentClass);

        try {
            ActivityScenario.launch(intent);
            Assert.fail("Should have thrown an IllegalArgumentException.");
        } catch (IllegalArgumentException e) {
            assertThat(e.getMessage()).contains(fragmentClass);
        }
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -104,6 +104,10 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
        initFlags();
        loadPluginPrefs();
        maybeAddSandboxCategory();

        if (getActivity() != null) {
            getActivity().setTitle("Developer Options");
        }
    }

    private void filterPreferences(String query, PreferenceGroup pg) {
+56 −10
Original line number Diff line number Diff line
@@ -20,11 +20,13 @@ import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTIO

import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -46,6 +48,9 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;

import java.util.Collections;
import java.util.List;

/**
 * Settings activity for Launcher. Currently implements the following setting: Allow rotation
 */
@@ -53,6 +58,10 @@ public class SettingsActivity extends FragmentActivity
        implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback,
        SharedPreferences.OnSharedPreferenceChangeListener{

    /** List of fragments that can be hosted by this activity. */
    private static final List<String> VALID_PREFERENCE_FRAGMENTS = Collections.singletonList(
            DeveloperOptionsFragment.class.getName());

    private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
    private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";

@@ -63,20 +72,30 @@ public class SettingsActivity extends FragmentActivity
    private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
    public static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";

    @VisibleForTesting
    static final String EXTRA_FRAGMENT = ":settings:fragment";
    @VisibleForTesting
    static final String EXTRA_FRAGMENT_ARGS = ":settings:fragment_args";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            Bundle args = new Bundle();
            String prefKey = getIntent().getStringExtra(EXTRA_FRAGMENT_ARG_KEY);
            Intent intent = getIntent();
            Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
            if (args == null) {
                args = new Bundle();
            }

            String prefKey = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY);
            if (!TextUtils.isEmpty(prefKey)) {
                args.putString(EXTRA_FRAGMENT_ARG_KEY, prefKey);
            }

            final FragmentManager fm = getSupportFragmentManager();
            final Fragment f = fm.getFragmentFactory().instantiate(getClassLoader(),
                    getString(R.string.settings_fragment_name));
                    getPreferenceFragment());
            f.setArguments(args);
            // Display the fragment as the main content.
            fm.beginTransaction().replace(android.R.id.content, f).commit();
@@ -84,22 +103,45 @@ public class SettingsActivity extends FragmentActivity
        Utilities.getPrefs(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
    }

    /**
     * Obtains the preference fragment to instantiate in this activity.
     *
     * @return the preference fragment class
     * @throws IllegalArgumentException if the fragment is unknown to this activity
     */
    private String getPreferenceFragment() {
        String preferenceFragment = getIntent().getStringExtra(EXTRA_FRAGMENT);
        String defaultFragment = getString(R.string.settings_fragment_name);

        if (TextUtils.isEmpty(preferenceFragment)) {
            return defaultFragment;
        } else if (!preferenceFragment.equals(defaultFragment)
                && !VALID_PREFERENCE_FRAGMENTS.contains(preferenceFragment)) {
            throw new IllegalArgumentException(
                    "Invalid fragment for this activity: " + preferenceFragment);
        } else {
            return preferenceFragment;
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { }

    private boolean startFragment(String fragment, Bundle args, String key) {
    private boolean startPreference(String fragment, Bundle args, String key) {
        if (Utilities.ATLEAST_P && getSupportFragmentManager().isStateSaved()) {
            // Sometimes onClick can come after onPause because of being posted on the handler.
            // Skip starting new fragments in that case.
            // Skip starting new preferences in that case.
            return false;
        }
        final FragmentManager fm = getSupportFragmentManager();
        final Fragment f = fm.getFragmentFactory().instantiate(getClassLoader(), fragment);
        f.setArguments(args);
        if (f instanceof DialogFragment) {
            ((DialogFragment) f).show(getSupportFragmentManager(), key);
            f.setArguments(args);
            ((DialogFragment) f).show(fm, key);
        } else {
            fm.beginTransaction().replace(android.R.id.content, f).addToBackStack(key).commit();
            startActivity(new Intent(this, SettingsActivity.class)
                    .putExtra(EXTRA_FRAGMENT, fragment)
                    .putExtra(EXTRA_FRAGMENT_ARGS, args));
        }
        return true;
    }
@@ -107,14 +149,14 @@ public class SettingsActivity extends FragmentActivity
    @Override
    public boolean onPreferenceStartFragment(
            PreferenceFragmentCompat preferenceFragment, Preference pref) {
        return startFragment(pref.getFragment(), pref.getExtras(), pref.getKey());
        return startPreference(pref.getFragment(), pref.getExtras(), pref.getKey());
    }

    @Override
    public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
        Bundle args = new Bundle();
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.getKey());
        return startFragment(getString(R.string.settings_fragment_name), args, pref.getKey());
        return startPreference(getString(R.string.settings_fragment_name), args, pref.getKey());
    }

    /**
@@ -148,6 +190,10 @@ public class SettingsActivity extends FragmentActivity
                    screen.removePreference(preference);
                }
            }

            if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
                getActivity().setTitle(getPreferenceScreen().getTitle());
            }
        }

        @Override