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

Commit 7c329321 authored by Yeabkal Wubshit's avatar Yeabkal Wubshit Committed by Chen Bai
Browse files

haptic: move haptic feedback vibration customization to xml resource

This makes it simpler for OEMs to set up their haptic feedback vibration
mapping, as it avoids the need to specify a file path and correctly
copying a customization XML to that path.

Flag: android.os.vibrator.load_haptic_feedback_vibration_customization_from_resources
Bug: 295142743
Test: manual
Test: atest HapticFeedbackCustomizationTest
Change-Id: I165e4f5d5707dde9b28b7a6d30ed60b57cbb3297
parent 1bb06ef3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -88,3 +88,14 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "haptics"
    name: "load_haptic_feedback_vibration_customization_from_resources"
    description: "Load haptic feedback vibrations customization from resources."
    is_fixed_read_only: true
    bug: "295142743"
    metadata {
        purpose: PURPOSE_FEATURE
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -5462,7 +5462,9 @@
  <java-symbol type="bool" name="config_enable_a11y_fullscreen_magnification_overscroll_handler" />
  <java-symbol type="dimen" name="accessibility_fullscreen_magnification_gesture_edge_slop" />

  <!-- For HapticFeedbackConstants configurability defined at HapticFeedbackCustomization -->
  <java-symbol type="string" name="config_hapticFeedbackCustomizationFile" />
  <java-symbol type="xml" name="haptic_feedback_customization" />

  <!-- For ActivityManager PSS profiling configurability -->
  <java-symbol type="bool" name="config_am_disablePssProfiling" />
+18 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2024 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.
  -->

<haptic-feedback-constants/>
+53 −18
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.vibrator;

import android.annotation.Nullable;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.VibrationEffect;
import android.os.VibratorInfo;
import android.os.vibrator.Flags;
@@ -28,6 +29,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;

import com.android.internal.util.XmlUtils;
import com.android.internal.vibrator.persistence.XmlParserException;
import com.android.internal.vibrator.persistence.XmlReader;
import com.android.internal.vibrator.persistence.XmlValidator;
@@ -39,6 +41,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * Class that loads custom {@link VibrationEffect} to be performed for each
@@ -127,27 +130,19 @@ final class HapticFeedbackCustomization {
            Slog.d(TAG, "Haptic feedback customization feature is not enabled.");
            return null;
        }
        String customizationFile =
                res.getString(
                        com.android.internal.R.string.config_hapticFeedbackCustomizationFile);
        if (TextUtils.isEmpty(customizationFile)) {
            Slog.d(TAG, "Customization file not configured.");
            return null;
        }

        FileReader fileReader;
        try {
            fileReader = new FileReader(customizationFile);
        } catch (FileNotFoundException e) {
            Slog.d(TAG, "Specified customization file not found.");
        // Old loading path that reads customization from file at dir defined by config.
        TypedXmlPullParser parser = readCustomizationFile(res);
        if (parser == null) {
            // When old loading path doesn't succeed, try loading customization from resources.
            parser = readCustomizationResources(res);
        }
        if (parser == null) {
            Slog.d(TAG, "No loadable haptic feedback customization.");
            return null;
        }

        TypedXmlPullParser parser = Xml.newFastPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
        parser.setInput(fileReader);

        XmlReader.readDocumentStartTag(parser, TAG_CONSTANTS);
        XmlUtils.beginDocument(parser, TAG_CONSTANTS);
        XmlValidator.checkTagHasNoUnexpectedAttributes(parser);
        int rootDepth = parser.getDepth();

@@ -191,6 +186,46 @@ final class HapticFeedbackCustomization {
        return mapping;
    }

    // TODO(b/356412421): deprecate old path related files.
    private static TypedXmlPullParser readCustomizationFile(Resources res)
            throws XmlPullParserException {
        String customizationFile = res.getString(
                com.android.internal.R.string.config_hapticFeedbackCustomizationFile);
        if (TextUtils.isEmpty(customizationFile)) {
            return null;
        }

        final Reader customizationReader;
        try {
            customizationReader = new FileReader(customizationFile);
        } catch (FileNotFoundException e) {
            Slog.e(TAG, "Specified customization file not found.", e);
            return null;
        }

        final TypedXmlPullParser parser;
        parser = Xml.newFastPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
        parser.setInput(customizationReader);
        Slog.d(TAG, "Successfully opened customization file.");
        return parser;
    }

    private static TypedXmlPullParser readCustomizationResources(Resources res) {
        if (!Flags.loadHapticFeedbackVibrationCustomizationFromResources()) {
            return null;
        }
        final XmlResourceParser resParser;
        try {
            resParser = res.getXml(com.android.internal.R.xml.haptic_feedback_customization);
        } catch (Resources.NotFoundException e) {
            Slog.e(TAG, "Haptic customization resource not found.", e);
            return null;
        }
        Slog.d(TAG, "Successfully opened customization resource.");
        return XmlUtils.makeTyped(resParser);
    }

    /**
     * Represents an error while parsing a haptic feedback customization XML.
     */
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ android_test {
        "frameworks-base-testutils",
        "frameworks-services-vibrator-testutils",
        "junit",
        "junit-params",
        "mockito-target-inline-minus-junit4",
        "platform-test-annotations",
        "service-permission.stubs.system_server",
Loading