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

Commit 13bc56e0 authored by David Padlipsky's avatar David Padlipsky
Browse files

Implement AppLaunchData persistance for input gestures

Adds support for persisting AppLaunchData for custom input gestures.

Test: atest InputTests:InputDataStoreTests
Bug: 365064144
Flag: com.android.hardware.input.enable_customizable_input_gestures
Change-Id: I1cfed974485077096ba5c3feac5b1b8ea07a8c47
parent b1e17a3f
Loading
Loading
Loading
Loading
+45 −10
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.input;

import android.hardware.input.AppLaunchData;
import android.hardware.input.InputGestureData;
import android.os.Environment;
import android.util.AtomicFile;
@@ -55,11 +56,16 @@ public final class InputDataStore {
    private static final String TAG_INPUT_GESTURE = "input_gesture";
    private static final String TAG_KEY_TRIGGER = "key_trigger";
    private static final String TAG_TOUCHPAD_TRIGGER = "touchpad_trigger";
    private static final String TAG_APP_LAUNCH_DATA = "app_launch_data";

    private static final String ATTR_KEY_TRIGGER_KEYCODE = "keycode";
    private static final String ATTR_KEY_TRIGGER_MODIFIER_STATE = "modifiers";
    private static final String ATTR_KEY_GESTURE_TYPE = "key_gesture_type";
    private static final String ATTR_TOUCHPAD_TRIGGER_GESTURE_TYPE = "touchpad_gesture_type";
    private static final String ATTR_APP_LAUNCH_DATA_CATEGORY = "category";
    private static final String ATTR_APP_LAUNCH_DATA_ROLE = "role";
    private static final String ATTR_APP_LAUNCH_DATA_PACKAGE_NAME = "package_name";
    private static final String ATTR_APP_LAUNCH_DATA_CLASS_NAME = "class_name";

    private final FileInjector mInputGestureFileInjector;

@@ -167,15 +173,31 @@ public final class InputDataStore {
                break;
            }

            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            final String tag = parser.getName();
            if (type == XmlPullParser.START_TAG && TAG_KEY_TRIGGER.equals(tag)) {
            if (TAG_KEY_TRIGGER.equals(tag)) {
                builder.setTrigger(InputGestureData.createKeyTrigger(
                        parser.getAttributeInt(null, ATTR_KEY_TRIGGER_KEYCODE),
                        parser.getAttributeInt(null, ATTR_KEY_TRIGGER_MODIFIER_STATE)));
            } else if (type == XmlPullParser.START_TAG && TAG_TOUCHPAD_TRIGGER.equals(tag)) {
                builder.setTrigger(
                        InputGestureData.createTouchpadTrigger(parser.getAttributeInt(null,
                                ATTR_TOUCHPAD_TRIGGER_GESTURE_TYPE)));
            } else if (TAG_TOUCHPAD_TRIGGER.equals(tag)) {
                builder.setTrigger(InputGestureData.createTouchpadTrigger(
                        parser.getAttributeInt(null, ATTR_TOUCHPAD_TRIGGER_GESTURE_TYPE)));
            } else if (TAG_APP_LAUNCH_DATA.equals(tag)) {
                final String roleValue = parser.getAttributeValue(null, ATTR_APP_LAUNCH_DATA_ROLE);
                final String categoryValue = parser.getAttributeValue(null,
                        ATTR_APP_LAUNCH_DATA_CATEGORY);
                final String classNameValue = parser.getAttributeValue(null,
                        ATTR_APP_LAUNCH_DATA_CLASS_NAME);
                final String packageNameValue = parser.getAttributeValue(null,
                        ATTR_APP_LAUNCH_DATA_PACKAGE_NAME);
                final AppLaunchData appLaunchData = AppLaunchData.createLaunchData(categoryValue,
                        roleValue, packageNameValue, classNameValue);
                if (appLaunchData != null) {
                    builder.setAppLaunchData(appLaunchData);
                }
            }
        }
        return builder.build();
@@ -237,11 +259,6 @@ public final class InputDataStore {

    private void writeInputGestureToXml(TypedXmlSerializer serializer,
            InputGestureData inputGestureData) throws IOException {
        // TODO(b/365064144): Implement storage of AppLaunch data.
        if (inputGestureData.getAction().appLaunchData() != null) {
            return;
        }

        serializer.startTag(null, TAG_INPUT_GESTURE);
        serializer.attributeInt(null, ATTR_KEY_GESTURE_TYPE,
                inputGestureData.getAction().keyGestureType());
@@ -260,6 +277,24 @@ public final class InputDataStore {
            serializer.endTag(null, TAG_TOUCHPAD_TRIGGER);
        }

        if (inputGestureData.getAction().appLaunchData() != null) {
            serializer.startTag(null, TAG_APP_LAUNCH_DATA);
            final AppLaunchData appLaunchData = inputGestureData.getAction().appLaunchData();
            if (appLaunchData instanceof AppLaunchData.RoleData roleData) {
                serializer.attribute(null, ATTR_APP_LAUNCH_DATA_ROLE, roleData.getRole());
            } else if (appLaunchData
                    instanceof AppLaunchData.CategoryData categoryData) {
                serializer.attribute(null, ATTR_APP_LAUNCH_DATA_CATEGORY,
                        categoryData.getCategory());
            } else if (appLaunchData instanceof AppLaunchData.ComponentData componentData) {
                serializer.attribute(null, ATTR_APP_LAUNCH_DATA_PACKAGE_NAME,
                        componentData.getPackageName());
                serializer.attribute(null, ATTR_APP_LAUNCH_DATA_CLASS_NAME,
                        componentData.getClassName());
            }
            serializer.endTag(null, TAG_APP_LAUNCH_DATA);
        }

        serializer.endTag(null, TAG_INPUT_GESTURE);
    }

+62 −2
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.server.input

import android.app.role.RoleManager
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.hardware.input.AppLaunchData
import android.hardware.input.InputGestureData
import android.hardware.input.KeyGestureEvent
import android.platform.test.annotations.Presubmit
@@ -149,7 +152,54 @@ class InputDataStoreTests {
    }

    @Test
    fun saveToDiskCombineGestures() {
    fun saveToDiskAppLaunchGestures() {
        val inputGestures = listOf(
            InputGestureData.Builder()
                .setTrigger(
                    InputGestureData.createTouchpadTrigger(
                        InputGestureData.TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP
                    )
                )
                .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
                .setAppLaunchData(AppLaunchData.createLaunchDataForRole(RoleManager.ROLE_BROWSER))
                .build(),
            InputGestureData.Builder()
                .setTrigger(
                    InputGestureData.createKeyTrigger(
                        KeyEvent.KEYCODE_2,
                        KeyEvent.META_META_ON
                    )
                )
                .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
                .setAppLaunchData(AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CONTACTS))
                .build(),
            InputGestureData.Builder()
                .setTrigger(
                    InputGestureData.createKeyTrigger(
                        KeyEvent.KEYCODE_1,
                        KeyEvent.META_META_ON
                    )
                )
                .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
                .setAppLaunchData(
                    AppLaunchData.createLaunchDataForComponent(
                        "com.test",
                        "com.test.BookmarkTest"
                    )
                )
                .build()
        )

        inputDataStore.saveInputGestures(USER_ID, inputGestures)
        assertEquals(
            inputGestures,
            inputDataStore.loadInputGestures(USER_ID),
            getPrintableXml(inputGestures)
        )
    }

    @Test
    fun saveToDiskCombinedGestures() {
        val inputGestures = listOf(
            InputGestureData.Builder()
                .setTrigger(
@@ -176,7 +226,17 @@ class InputDataStoreTests {
                    )
                )
                .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_HOME)
                .build()
                .build(),
            InputGestureData.Builder()
                .setTrigger(
                    InputGestureData.createKeyTrigger(
                        KeyEvent.KEYCODE_9,
                        KeyEvent.META_META_ON
                    )
                )
                .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
                .setAppLaunchData(AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CONTACTS))
                .build(),
        )

        inputDataStore.saveInputGestures(USER_ID, inputGestures)
+6 −10
Original line number Diff line number Diff line
@@ -1460,11 +1460,6 @@ class KeyGestureControllerTests {
    @Test
    @Parameters(method = "customInputGesturesTestArguments")
    fun testCustomKeyGesturesSavedAndLoadedByController(test: TestData) {
        // TODO(b/365064144): Implement storage of AppLaunch data.
        if (test.expectedAppLaunchData != null) {
            return
        }

        val userId = 10
        setupKeyGestureController()
        val builder = InputGestureData.Builder()
@@ -1475,6 +1470,9 @@ class KeyGestureControllerTests {
                    test.expectedModifierState
                )
            )
        if (test.expectedAppLaunchData != null) {
            builder.setAppLaunchData(test.expectedAppLaunchData)
        }
        val inputGestureData = builder.build()

        keyGestureController.setCurrentUserId(userId)
@@ -1579,16 +1577,14 @@ class KeyGestureControllerTests {
    @Test
    @Parameters(method = "customTouchpadGesturesTestArguments")
    fun testCustomTouchpadGesturesSavedAndLoadedByController(test: TouchpadTestData) {
        // TODO(b/365064144): Implement storage of AppLaunch data.
        if (test.expectedAppLaunchData != null) {
            return
        }

        val userId = 10
        setupKeyGestureController()
        val builder = InputGestureData.Builder()
            .setKeyGestureType(test.expectedKeyGestureType)
            .setTrigger(InputGestureData.createTouchpadTrigger(test.touchpadGestureType))
        if (test.expectedAppLaunchData != null) {
            builder.setAppLaunchData(test.expectedAppLaunchData)
        }
        val inputGestureData = builder.build()
        keyGestureController.setCurrentUserId(userId)
        testLooper.dispatchAll()