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

Commit e58e8706 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[3FT] When the chosen app is uninstalled" into main

parents eebbf6d6 d2a34ce6
Loading
Loading
Loading
Loading
+63 −14
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.hardware.input.AppLaunchData.ComponentData;
import android.hardware.input.InputGestureData;
import android.hardware.input.InputManager;
import android.hardware.input.InputSettings;
import android.hardware.input.KeyGestureEvent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -80,24 +79,73 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceController extends Base

    @Nullable private PreferenceScreen mPreferenceScreen;

    private final LauncherApps.Callback mLauncherAppsCallback = new LauncherApps.Callback() {
        @Override
        public void onPackageRemoved(@Nullable String packageName, @Nullable UserHandle user) {
            if (packageName != null && isAppSelected(packageName)) {
                setGestureToDefault();
                repopulateApps();
            }
        }

        @Override
        public void onPackageAdded(@Nullable String packageName, @Nullable UserHandle user) {}

        @Override
        public void onPackageChanged(@Nullable String packageName, @Nullable UserHandle user) {}

        @Override
        public void onPackagesAvailable(
                @Nullable String[] packageNames, @Nullable UserHandle user, boolean replacing) {}

        @Override
        public void onPackagesUnavailable(
                @Nullable String[] packageNames, @Nullable UserHandle user, boolean replacing) {
            if (packageNames == null) {
                return;
            }
            for (String packageName : packageNames) {
                if (isAppSelected(packageName)) {
                    setGestureToDefault();
                    repopulateApps();
                }
            }
        }
    };

    public TouchpadThreeFingerTapAppSelectionPreferenceController(@NonNull Context context,
            @NonNull String key) {
        super(context, key);
        mLauncherApps = context.getSystemService(LauncherApps.class);
        mInputManager = context.getSystemService(InputManager.class);
        mContentResolver = context.getContentResolver();
        mLauncherApps.registerCallback(mLauncherAppsCallback);
    }

    @VisibleForTesting
    TouchpadThreeFingerTapAppSelectionPreferenceController(@NonNull Context context,
            @NonNull String key,
            LauncherApps launcherApps,
            InputManager inputManager,
            ContentObserver contentObserver) {
            @NonNull LauncherApps launcherApps,
            @NonNull InputManager inputManager,
            @NonNull ContentObserver contentObserver) {
        this(context, key);
        mLauncherApps = launcherApps;
        mInputManager = inputManager;
        mObserver = contentObserver;
        mLauncherApps.registerCallback(mLauncherAppsCallback);
    }

    private void setGestureToDefault() {
        mInputManager.removeAllCustomInputGestures(InputGestureData.Filter.TOUCHPAD);
        TouchpadThreeFingerTapUtils.setDefaultGestureType(mContentResolver);
    }

    private boolean isAppSelected(@NonNull String packageName) {
        if (TouchpadThreeFingerTapUtils.isGestureTypeLaunchApp(mContentResolver)) {
            ComponentName componentName = getSelectedAppComponent();
            return componentName != null && packageName.equals(componentName.getPackageName());
        }
        return false;
    }

    @Override
@@ -119,13 +167,15 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceController extends Base
    }

    private void updateAppListSelection() {
        int current = TouchpadThreeFingerTapUtils.getCurrentGestureType(mContentResolver);

        // When the current gesture state is not app launching, the key is set to null so that no
        // app Preference will be selected
        String matchingKey =
                current == KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION
                        ? parsePreferenceKey() : null;
        String matchingKey = null;
        if (TouchpadThreeFingerTapUtils.isGestureTypeLaunchApp(mContentResolver)) {
            ComponentName componentName = getSelectedAppComponent();
            if (componentName != null) {
                matchingKey = parsePreferenceKeyFromComponent(componentName);
            }
        }
        updateCheckStatus(matchingKey);
    }

@@ -145,15 +195,14 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceController extends Base
    }

    @Nullable
    private String parsePreferenceKey() {
    private ComponentName getSelectedAppComponent() {
        InputGestureData gestureData =
                mInputManager.getInputGesture(TouchpadThreeFingerTapUtils.TRIGGER);
        if (gestureData != null) {
            ComponentData componentData = (ComponentData) gestureData.getAction().appLaunchData();
            if (componentData != null) {
                ComponentName component = new ComponentName(
                return new ComponentName(
                        componentData.getPackageName(), componentData.getClassName());
                return parsePreferenceKeyFromComponent(component);
            }
        }
        return null;
@@ -178,10 +227,10 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceController extends Base
    public void displayPreference(@NonNull PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreferenceScreen = screen;
        populateApps();
        repopulateApps();
    }

    private void populateApps() {
    private void repopulateApps() {
        if (mPreferenceScreen == null) {
            return;
        }
+23 −1
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@ public final class TouchpadThreeFingerTapUtils {
    static final InputGestureData.Trigger TRIGGER =
            createTouchpadTrigger(TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP);

    // Note that KEY_GESTURE_TYPE_UNSPECIFIED is the "mouse mid click" action
    static final Integer DEFAULT_GESTURE_TYPE =
            KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED;

    private static final Map<String, Integer> PREF_KEY_TO_GESTURE_TYPE = Map.ofEntries(
            Map.entry("launch_gemini", KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT),
            Map.entry("go_home", KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
@@ -60,6 +64,15 @@ public final class TouchpadThreeFingerTapUtils {
                ActivityManager.getCurrentUser());
    }

    /**
     * Return if KEY_GESTURE_TYPE_LAUNCH_APPLICATION is the cuurent the gesture type
     * @param resolver ContentResolver
     */
    public static boolean isGestureTypeLaunchApp(@NonNull ContentResolver resolver) {
        return getCurrentGestureType(resolver)
                == KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION;
    }

    /**
     * @param prefKey Preference key for input_touchpad_three_finger_tap_action
     * @return the corresponding KeyGestureEvent of the given key, or KEY_GESTURE_TYPE_UNSPECIFIED
@@ -80,7 +93,16 @@ public final class TouchpadThreeFingerTapUtils {
    }

    /**
     * Set KEY_GESTURE_TYPE_LAUNCH_APPLICATION as the gesture type
     * Set KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED as the gesture type
     * @param resolver ContentResolver
     */
    public static void setDefaultGestureType(@NonNull ContentResolver resolver) {
        Settings.System.putIntForUser(
                resolver, TARGET_ACTION, DEFAULT_GESTURE_TYPE, ActivityManager.getCurrentUser());
    }

    /**
     * Set KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION as the gesture type
     * @param resolver ContentResolver
     */
    public static void setLaunchAppAsGestureType(@NonNull ContentResolver resolver) {
+41 −5
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceControllerTest {
    private final Context mContext = RuntimeEnvironment.application;
    private ContentResolver mContentResolver;
    private TouchpadThreeFingerTapAppSelectionPreferenceController mController;
    private InputGestureData mCustomInputGesture = null;
    private InputGestureData mCustomInputGesture;
    private LauncherApps.Callback mLauncherAppsCallback;

    @Before
    public void setup() {
@@ -185,7 +186,7 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceControllerTest {
    public void updateState_whenActionIsLaunchApp_correspondingAppChecked() {
        ArgumentCaptor<SelectorWithWidgetPreference> captor = capturePrefs();

        setupLaunchingApp(/* matchingIndex = */ 1);
        setupAppSelection(/* matchingIndex = */ 1);
        mController.updateState(mMockPreferenceScreen);

        List<SelectorWithWidgetPreference> prefs = captor.getAllValues();
@@ -212,8 +213,7 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceControllerTest {
        mController.onRadioButtonClicked(captor.getAllValues().get(clickingIndex));

        // Settings key is updated
        int gesture = TouchpadThreeFingerTapUtils.getCurrentGestureType(mContentResolver);
        assertThat(gesture).isEqualTo(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION);
        assertTrue(TouchpadThreeFingerTapUtils.isGestureTypeLaunchApp(mContentResolver));

        // InputManager gesture is updated
        assertThat(mCustomInputGesture).isNotNull();
@@ -229,6 +229,42 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceControllerTest {
        assertThat(prefs.get(1).isChecked()).isFalse();
    }

    @Test
    public void onPackageRemoved_isNotSelectedApp_doNothing() {
        ArgumentCaptor<LauncherApps.Callback> captor =
                ArgumentCaptor.forClass(LauncherApps.Callback.class);
        verify(mMockLauncherApps).registerCallback(captor.capture());
        mLauncherAppsCallback = captor.getValue();

        int selectedAppIndex = 0;
        setupAppSelection(/* matchingIndex = */ selectedAppIndex);
        mController.updateState(mMockPreferenceScreen);

        mLauncherAppsCallback.onPackageRemoved(
                TEST_PACKAGE_PREFIX + 1, UserHandle.CURRENT);

        assertTrue(TouchpadThreeFingerTapUtils.isGestureTypeLaunchApp(mContentResolver));
    }

    @Test
    public void onPackageRemoved_isSelectedApp_setToDefaultGesture() {
        ArgumentCaptor<LauncherApps.Callback> captor =
                ArgumentCaptor.forClass(LauncherApps.Callback.class);
        verify(mMockLauncherApps).registerCallback(captor.capture());
        mLauncherAppsCallback = captor.getValue();

        int selectedAppIndex = 0;
        setupAppSelection(/* matchingIndex = */ selectedAppIndex);
        mController.updateState(mMockPreferenceScreen);

        mLauncherAppsCallback.onPackageRemoved(
                TEST_PACKAGE_PREFIX + selectedAppIndex, UserHandle.CURRENT);

        // Settings key is updated
        int gesture = TouchpadThreeFingerTapUtils.getCurrentGestureType(mContentResolver);
        assertThat(gesture).isEqualTo(TouchpadThreeFingerTapUtils.DEFAULT_GESTURE_TYPE);
    }

    private ArgumentCaptor<SelectorWithWidgetPreference> capturePrefs() {
        ArgumentCaptor<SelectorWithWidgetPreference> captor =
                ArgumentCaptor.forClass(SelectorWithWidgetPreference.class);
@@ -242,7 +278,7 @@ public class TouchpadThreeFingerTapAppSelectionPreferenceControllerTest {
        return captor;
    }

    private void setupLaunchingApp(int matchingIndex) {
    private void setupAppSelection(int matchingIndex) {
        AppLaunchData appLaunchData = createLaunchDataForComponent(
                TEST_PACKAGE_PREFIX + matchingIndex, TEST_CLASS_PREFIX + matchingIndex);