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

Commit 14ec4f08 authored by Riley Jones's avatar Riley Jones Committed by Android (Google) Code Review
Browse files

Merge "DragToEdit Dynaimc Title" into main

parents 950d9e9f 43420f16
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
  -->

<resources>
    <string name="accessibility_shortcut_description_pref" translatable="false">shortcut_description</string>
    <string name="accessibility_shortcut_volume_keys_pref" translatable="false">shortcut_volume_keys_pref</string>
    <string name="accessibility_shortcut_gesture_pref" translatable="false">shortcut_gesture_pref</string>
    <string name="accessibility_shortcut_nav_button_pref" translatable="false">shortcut_nav_button_pref</string>
+4 −0
Original line number Diff line number Diff line
@@ -5112,6 +5112,10 @@
    <string name="accessibility_shortcut_type_hardware">Hold volume keys</string>
    <!-- Summary for accessibility shortcut preference for magnification triple tap shortcut type. [CHAR LIMIT=NONE] -->
    <string name="accessibility_shortcut_type_triple_tap">Triple tap screen</string>
    <!-- Generic title for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
    <string name="accessibility_shortcut_edit_screen_title">Edit accessibility shortcuts</string>
    <!-- Prompt for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
    <string name="accessibility_shortcut_edit_screen_prompt">Chose your shortcut for %1$s</string>
    <!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
    <string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
+55 −51
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto">

    <PreferenceCategory
        android:key="@string/accessibility_shortcut_description_pref">

        <com.android.settings.accessibility.shortcuts.ShortcutOptionPreference
            android:key="@string/accessibility_shortcut_fab_pref"
            android:persistent="false"
@@ -75,5 +78,6 @@
            settings:allowDividerAbove="false"
            settings:allowDividerBelow="false"
            settings:controller="com.android.settings.accessibility.shortcuts.TripleTapShortcutOptionController" />
    </PreferenceCategory>

</PreferenceScreen>
 No newline at end of file
+89 −1
Original line number Diff line number Diff line
@@ -27,16 +27,21 @@ import static com.android.internal.accessibility.AccessibilityShortcutController
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE;

import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.icu.text.ListFormatter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -48,9 +53,12 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.recyclerview.widget.RecyclerView;

import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.accessibility.dialog.AccessibilityTargetHelper;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.accessibility.AccessibilitySetupWizardUtils;
import com.android.settings.accessibility.Flags;
import com.android.settings.accessibility.PreferredShortcuts;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
@@ -60,7 +68,10 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifPreferenceLayout;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
@@ -171,6 +182,36 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
        registerSettingsObserver();
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        super.onCreatePreferences(savedInstanceState, rootKey);

        Activity activity = getActivity();

        if (!activity.getIntent().getAction().equals(
                Settings.ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS)
                || !Flags.editShortcutsInFullScreen()) {
            return;
        }

        // TODO(b/325664350): Implement shortcut type for "all shortcuts"
        List<AccessibilityTarget> accessibilityTargets =
                AccessibilityTargetHelper.getInstalledTargets(
                        activity.getBaseContext(), AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY);

        Pair<String, String> titles = getTitlesFromAccessibilityTargetList(
                mShortcutTargets,
                accessibilityTargets,
                activity.getResources()
        );

        activity.setTitle(titles.first);

        String categoryKey = activity.getResources().getString(
                R.string.accessibility_shortcut_description_pref);
        findPreference(categoryKey).setTitle(titles.second);
    }

    @NonNull
    @Override
    public RecyclerView onCreateRecyclerView(
@@ -275,7 +316,6 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
        }

        mShortcutTargets = Set.of(targets);
        // TODO(318748373): use 'targets' to populate title when no title is given
    }

    @Override
@@ -356,4 +396,52 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
        // A11y Nav Button
        refreshPreferenceController(NavButtonShortcutOptionController.class);
    }

    /**
     * Generates a title & subtitle pair describing the features whose shortcuts are being edited.
     *
     * @param shortcutTargets string list of component names corresponding to
     *                        the relevant shortcut targets.
     * @param accessibilityTargets list of accessibility targets
     *                             to try and find corresponding labels in.
     * @return pair of strings to be used as page title and subtitle.
     * If there is only one shortcut label, It is displayed in the title and the subtitle is null.
     * Otherwise, the title is a generic prompt and the subtitle lists all shortcut labels.
     */
    @VisibleForTesting
    static Pair<String, String> getTitlesFromAccessibilityTargetList(
            Set<String> shortcutTargets,
            List<AccessibilityTarget> accessibilityTargets,
            Resources resources) {
        ArrayList<CharSequence> featureLabels = new ArrayList<>();

        Map<String, CharSequence> accessibilityTargetLabels = new ArrayMap<>();
        accessibilityTargets.forEach((target) -> accessibilityTargetLabels.put(
                target.getId(), target.getLabel()));

        for (String target: shortcutTargets) {
            if (accessibilityTargetLabels.containsKey(target)) {
                featureLabels.add(accessibilityTargetLabels.get(target));
            } else {
                throw new IllegalStateException("Shortcut target does not have a label: " + target);
            }
        }

        if (featureLabels.size() == 1) {
            return new Pair<>(
                    resources.getString(
                            R.string.accessibility_shortcut_title, featureLabels.get(0)),
                    null
            );
        } else if (featureLabels.size() == 0) {
            throw new IllegalStateException("Found no labels for any shortcut targets.");
        } else {
            return new Pair<>(
                    resources.getString(R.string.accessibility_shortcut_edit_screen_title),
                    resources.getString(
                            R.string.accessibility_shortcut_edit_screen_prompt,
                            ListFormatter.getInstance().format(featureLabels))
            );
        }
    }
}
+72 −0
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@ import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_P
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SETUP_FLOW;
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

import android.content.ComponentName;
@@ -35,7 +38,9 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.util.Pair;
import android.view.accessibility.AccessibilityManager;

import androidx.fragment.app.FragmentActivity;
@@ -46,6 +51,7 @@ import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;

import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -60,6 +66,7 @@ import com.google.android.setupcompat.util.WizardManagerHelper;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@@ -89,6 +96,9 @@ public class EditShortcutsPreferenceFragmentTest {
    private static final String TARGET = MAGNIFICATION_CONTROLLER_NAME;
    private static final Set<String> TARGETS = Set.of(TARGET);

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    private final Context mContext = ApplicationProvider.getApplicationContext();
    private FragmentActivity mActivity;
    private FragmentScenario<EditShortcutsPreferenceFragment> mFragmentScenario;
@@ -414,6 +424,60 @@ public class EditShortcutsPreferenceFragmentTest {

    }

    @Test
    public void findTitles_withSingleTarget_hasNullSubtitle() {
        final String fake_label = "FAKE";
        List<AccessibilityTarget> accessibilityTargets = List.of(
                generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label));

        Pair<String, String> titles = EditShortcutsPreferenceFragment
                .getTitlesFromAccessibilityTargetList(
                        Set.of(TARGET_FAKE_COMPONENT.flattenToString()),
                        accessibilityTargets, mActivity.getResources()
                );

        assertThat(titles.first).isNotNull();
        assertThat(titles.first).contains(fake_label);
        assertThat(titles.second).isNull();
    }

    @Test
    public void findTitles_withMoreTargets_hasSubtitle() {
        final String fake_label = "FAKE";
        final String magnification_label = "MAGNIFICATION";
        List<AccessibilityTarget> accessibilityTargets = List.of(
                generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label),
                generateAccessibilityTargetMock(MAGNIFICATION_COMPONENT_NAME, magnification_label));

        Pair<String, String> titles = EditShortcutsPreferenceFragment
                .getTitlesFromAccessibilityTargetList(
                        Set.of(TARGET_FAKE_COMPONENT.flattenToString(),
                                MAGNIFICATION_COMPONENT_NAME.flattenToString()),
                        accessibilityTargets, mActivity.getResources()
                );

        assertThat(titles.first).isNotNull();
        assertThat(titles.second).isNotNull();
        assertThat(titles.second).contains(fake_label);
        assertThat(titles.second).contains(magnification_label);
    }

    @Test
    public void findTitles_targetMissing_labelNotInTitles() {
        final String fake_label = "FAKE";
        List<AccessibilityTarget> accessibilityTargets = List.of(
                generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label));

        assertThrows(IllegalStateException.class,
                () -> EditShortcutsPreferenceFragment
                        .getTitlesFromAccessibilityTargetList(
                                Set.of(MAGNIFICATION_COMPONENT_NAME.flattenToString()),
                                accessibilityTargets, mActivity.getResources()
                        ));
    }



    private void assertLaunchSubSettingWithCurrentTargetComponents(
            String componentName, boolean isInSuw) {
        Intent intent = shadowOf(mActivity.getApplication()).getNextStartedActivity();
@@ -480,4 +544,12 @@ public class EditShortcutsPreferenceFragmentTest {
        intent.putExtra(EXTRA_IS_DEFERRED_SETUP, isInSuw);
        return intent;
    }

    private AccessibilityTarget generateAccessibilityTargetMock(
            ComponentName componentName, String label) {
        AccessibilityTarget target = mock(AccessibilityTarget.class);
        when(target.getComponentName()).thenReturn(componentName);
        when(target.getLabel()).thenReturn(label);
        return target;
    }
}