Android system adds dynamic control of USB TP touch direction and touch wake-up

Implementation steps

  • In order to realize the wake-up and rotation functions of the USB touch screen (TP), I modified three modules of the Android system: inputflinger, surfaceflinger and Settings.
  • Inputflinger is a service responsible for processing input events. It receives raw input events from hardware devices and converts them into events that the Android system can understand, such as touch, etc.
  • Surfaceflinger is a service responsible for managing display output. It receives graphics buffers from applications and system services, synthesizes them into final display frames, and then sends them to the hardware device.
  • Settings application, which provides a user interface that allows users to modify various system settings, etc.

  • I modified the TouchInputMapper class in inputflinger. This class is responsible for mapping raw touch events to the logical coordinate system. I added two system properties: persist.sys.usbtpwake.enable and persist.sys.usbtp.rotation, which are used to control whether USB TP can wake the device and the direction of USB TP respectively. I adjust the touch event processing logic based on the values ​​of these two properties so that USB TP can work normally in different directions and wake up the device when the device is sleeping.

  • I modified the SurfaceFlinger class in surfaceflinger, which is the class responsible for managing the display layer. I added a system property: persist.sys.usbtp.rotation to control the USB TP direction. I adjust the rotation angle of the display layer based on the value of this attribute so that the USB TP can be consistent with the display screen (this area can also be shielded and not changed, use my previous link: Android system adds dynamic control of screen orientation, forcing APP horizontal and vertical screen orientation properties.

  • I added two preferences in Settings: USB TP wake-up and USB TP direction, corresponding to the two system properties persist.sys.usbtpwake.enable and persist.sys.usbtp.rotation respectively. I created two preference controllers: UsbTPWakePreferenceController and UsbTPRotatePreferenceController, which are used to monitor and update the values ​​of these two preferences respectively. Added interface elements for these two preferences to display_settings.xml so they can be seen and controlled in the Settings app.

Modify example

surfaceflinger module

  • SurfaceFlinger.cppYou need to modify the function in the file of the surfaceflinger module processDisplayHotplugEventsLocked():

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

+++ b/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2482,6 +2482,27 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {
    
    
             continue;
         }
 
+        
+        char rotationvalue[PROPERTY_VALUE_MAX] = "";;
+        property_get("persist.sys.usbtp.rotation", rotationvalue, "-1");
+        int rotation = atoi(rotationvalue);
+        ALOGI("Primary Display Orientation is set to rotation %2d.", rotation);
+        switch (rotation) {
    
    
+           case 0:
+                internalDisplayOrientation = ui::ROTATION_0;
+                break;
+            case 1:
+                internalDisplayOrientation = ui::ROTATION_90;
+                break;
+            case 2:
+                internalDisplayOrientation = ui::ROTATION_180;
+                break;
+            case 3:
+                internalDisplayOrientation = ui::ROTATION_270;
+                break;
+            default:
+                break;
+       }
         const DisplayId displayId = info->id;
  • The purpose of this code is to read the orientation value of the USB touch screen from the system properties and set the orientation of the internal display device based on this value.

inputflinger module

  • We need to TouchInputMapper.cppmodify the following three functions in the file of the inputflinger module: configureParameters(), configureSurface()and isPointInsideSurface():

frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp

+++ b/frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -481,7 +481,17 @@ void TouchInputMapper::configureParameters() {
    
    
     // Initial downs on external touch devices should wake the device.
     // Normally we don't do this for internal touch screens to prevent them from waking
     // up in your pocket but you can enable it using the input device configuration.
-    mParameters.wake = getDeviceContext().isExternal();
+    char wakevalue[PROPERTY_VALUE_MAX] = "";
+    property_get("persist.sys.usbtpwake.enable", wakevalue, "false");
+    
+    if (strcmp(wakevalue, "true") == 0) {
    
    
+        mParameters.wake = true;   
+    }else{
    
    
+        mParameters.wake = getDeviceContext().isExternal();
+    }
+
+    
+    
     getDeviceContext().getConfiguration().tryGetProperty(String8("touch.wake"), mParameters.wake);
 }
 
@@ -651,14 +661,21 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
    
    
     }
 
     // Get associated display dimensions.
-    std::optional<DisplayViewport> newViewport = findViewport();
-    if (!newViewport) {
    
    
-        ALOGI("Touch device '%s' could not query the properties of its associated "
-              "display.  The device will be inoperable until the display size "
-              "becomes available.",
-              getDeviceName().c_str());
-        mDeviceMode = DEVICE_MODE_DISABLED;
-        return;
+    char wakevalue[PROPERTY_VALUE_MAX] = "";
+    property_get("persist.sys.usbtpwake.enable", wakevalue, "false");
+    
+    std::optional<DisplayViewport> newViewport;
+    
+    if (strcmp(wakevalue, "true") == 0) {
    
    
+        newViewport = findViewport();
+        if (!newViewport) {
    
    
+            ALOGI("Touch device '%s' could not query the properties of its associated "
+                  "display.  The device will be inoperable until the display size "
+                  "becomes available.",
+                  getDeviceName().c_str());
+            mDeviceMode = DEVICE_MODE_DISABLED;
+            return;
+        }
     }
 

+++ b/frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -22,6 +22,7 @@
 #include "CursorScrollAccumulator.h"
 #include "TouchButtonAccumulator.h"
 #include "TouchCursorInputMapperCommon.h"
+#include <cutils/properties.h>
 
 namespace android {
    
    
 
@@ -664,6 +665,10 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
    
    
     int32_t rawWidth = mRawPointerAxes.getRawWidth();
     int32_t rawHeight = mRawPointerAxes.getRawHeight();
 
+    char rotationvalue[PROPERTY_VALUE_MAX] = "";;
+    property_get("persist.sys.usbtp.rotation", rotationvalue, "0");
+    int rotation = atoi(rotationvalue);
+
     bool viewportChanged = mViewport != *newViewport;
     if (viewportChanged) {
    
    
         mViewport = *newViewport;
@@ -674,7 +679,32 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
    
    
             int32_t naturalPhysicalWidth, naturalPhysicalHeight;
             int32_t naturalPhysicalLeft, naturalPhysicalTop;
             int32_t naturalDeviceWidth, naturalDeviceHeight;
-            switch (mViewport.orientation) {
    
    
+                       int currentrotation = DISPLAY_ORIENTATION_0;
+            switch (rotation) {
    
    
+                case 0:
+                    currentrotation = DISPLAY_ORIENTATION_0;
+                    break;
+                case 90:
+                    currentrotation = DISPLAY_ORIENTATION_90;
+                    break;
+                case 180:
+                    currentrotation = DISPLAY_ORIENTATION_180;
+                    break;
+                case 270:
+                    currentrotation = DISPLAY_ORIENTATION_270;
+                    break;
+                default:
+                    break;
+            }
+
+           if(currentrotation == DISPLAY_ORIENTATION_0 && mViewport.orientation != currentrotation){
    
    
+                   rotation = mViewport.orientation;
+                   currentrotation = mViewport.orientation;
+           }
+           
+           // switch (mViewport.orientation) {
    
    
+           switch (currentrotation) {
    
    
+
                 case DISPLAY_ORIENTATION_90:
                     naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
                     naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
@@ -752,6 +782,24 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
    
    
         }
     }
 
+    ALOGI("Primary Display Orientation is set to rotation %2d.", rotation);
+    switch (rotation) {
    
    
+       case 0:
+               mSurfaceOrientation = DISPLAY_ORIENTATION_0;
+               break;
+       case 1:
+               mSurfaceOrientation = DISPLAY_ORIENTATION_90;
+               break;
+       case 2:
+               mSurfaceOrientation = DISPLAY_ORIENTATION_180;
+               break;
+       case 3:
+               mSurfaceOrientation = DISPLAY_ORIENTATION_270;
+               break;
+       default:
+               break;
+    }
+
     // If moving between pointer modes, need to reset some state.
     bool deviceModeChanged = mDeviceMode != oldDeviceMode;
     if (deviceModeChanged) {
    
    
@@ -3653,13 +3701,14 @@ void TouchInputMapper::rotateAndScale(float& x, float& y) {
    
    
 }
 
 bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
    
    
-    const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale;
-    const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale;
+    //const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale;
+    //const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale;
+       //modify fix dual tp with sync display,second tp funtion is error
+       return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue 
+       //&& scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+       && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
+       //&& scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
 
-    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
-            xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight &&
-            y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
-            yScaled >= mSurfaceTop && yScaled <= mSurfaceBottom;
 }

Settings module

packages/apps/Settings/res/values-zh-rCN/arrays.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    
    <string-array name="usbtp_totate_entries">
        <item>0度</item>
        <item>90度</item>
        <item>180度</item>
        <item>270度</item>
    </string-array>
    
    <!-- Do not translate. -->
    <string-array name="usbtp_rotate_values" translatable="false">
        <item>0</item>
        <item>1</item>
        <item>2</item>
        <item>3</item>
    </string-array>
  <string-array name="timezone_filters">
    <item msgid="6657355508154731088">"美洲"</item>
    <item msgid="728005479339643412">"欧洲"</item>
  • A string array usbtp_totate_entries is defined to display the USB TP direction options. It has four elements: 0 degrees, 90 degrees, 180 degrees and 270 degrees.
  • A string array usbtp_rotate_values ​​is defined to store the value of the USB TP direction. It has four elements: 0, 1, 2 and 3, which correspond to 0 degrees, 90 degrees, 180 degrees and 270 degrees respectively.
  • To create a list of preferences, they must be the same length and the positions of each element must correspond.

packages/apps/Settings/res/values-zh-rCN/strings.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string name="usbtp_rotate_summary"> <xliff:g id="usbtprotate_description">%1$s</xliff:g> </string>
    <string name="ctrl_usbtp_wake" >"USB TP唤醒"</string>
    <string name="ctrl_usbtp_rotate">"USB TP方向"</string>

    <string name="ctrl_forceapp_rotate" >"APP旋转"</string>
    <string name="ctrl_screen_rotate">"屏幕旋转"</string>
    <string name="ctrl_statusbar">状态栏</string>
  • Three string resources are defined that display the title and summary of USB TP related preferences.
  • usbtp_rotate_summary is a string with placeholders showing the current value of the USB TP direction. The placeholder %1$s will be replaced with the corresponding element in usbtp_totate_entries.
  • ctrl_usbtp_wake is a string that displays the title of the switch preference for USB TP wake.
  • ctrl_usbtp_rotate is a string used to display the title of the list preference for USB TP orientation.

packages/apps/Settings/res/values/arrays.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <string-array name="usbtp_rotate_entries">
        <item>0 Degrees</item>
        <item>90 Degrees</item>
        <item>180 Degrees</item>
        <item>270 Degrees</item>
    </string-array>
    
    <!-- Do not translate. -->
    <string-array name="usbtp_rotate_values" translatable="false">
        <item>0</item>
        <item>1</item>
        <item>2</item>
        <item>3</item>
    </string-array>
    <!-- Choices for timezone picker first level.
         These values will be used as search terms for TimeZone displayName
         strings. --> <skip />
  • This code is similar to the code above, but uses English to represent the USB TP direction option. This is to adapt to users in different language environments.

packages/apps/Settings/res/values/strings.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="usbtp_rotate_summary"> <xliff:g id="usbtprotate_description">%1$s</xliff:g> </string>
    <string name="ctrl_usbtp_wake" >"USB TP Wake"</string>
    <string name="ctrl_usbtp_rotate">"USB TP Rotate"</string>
  • Similar to the code above, except that the title and summary of the USB TP-related preferences are expressed in English.

packages/apps/Settings/res/xml/display_settings.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="@string/display_settings"
    settings:keywords="@string/keywords_display"
    settings:initialExpandedChildrenCount="5">
   <SwitchPreference
       android:key="ctrl_usbtpwake"
       android:title="@string/ctrl_usbtp_wake"/>
   <com.android.settings.display.UsbTPRotateListPreference 
        android:key="usbtp_rotate"
        android:title="@string/ctrl_usbtp_rotate"
        android:summary="@string/summary_placeholder"
        android:entries="@array/usbtp_rotate_entries"
        android:entryValues="@array/usbtp_rotate_values"/>
     <com.android.settingslib.RestrictedPreference
         android:key="brightness"
         android:title="@string/brightness"
  • Two preference elements have been added to the display settings interface: a switch preference and a list preference.
  • The key attribute of the switch preference is ctrl_usbtpwake, which corresponds to the preference key defined in the UsbTPWakePreferenceController class. Its title attribute is @string/ctrl_usbtp_wake, which references the string resource defined above. When the user clicks this

packages/apps/Settings/src/com/android/settings/display/UsbTPRotateListPreference.java

package com.android.settings.display;

import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;

import androidx.preference.Preference;

import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
import android.app.Dialog;
import java.util.ArrayList;
import android.view.View;
import androidx.appcompat.app.AlertDialog;

import android.util.AttributeSet;
import com.android.settings.R;
import com.android.settings.RestrictedListPreference;
import android.content.DialogInterface;

public class UsbTPRotateListPreference extends RestrictedListPreference {
    
    
    private EnforcedAdmin mAdmin;
    private final CharSequence[] mInitialEntries;
    private final CharSequence[] mInitialValues;

    public UsbTPRotateListPreference(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        mInitialEntries = getEntries();
        mInitialValues = getEntryValues();
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
                                          DialogInterface.OnClickListener listener) {
    
    
        super.onPrepareDialogBuilder(builder, listener);
        if (mAdmin != null) {
    
    
            builder.setView(R.layout.admin_disabled_other_options_footer);
        } else {
    
    
            builder.setView(null);
        }
    }


    @Override
    protected void onDialogCreated(Dialog dialog) {
    
    
        super.onDialogCreated(dialog);
        dialog.create();
        if (mAdmin != null) {
    
    
            View footerView = dialog.findViewById(R.id.admin_disabled_other_options);
            footerView.findViewById(R.id.admin_more_details_link).setOnClickListener(
                    new View.OnClickListener() {
    
    
                        @Override
                        public void onClick(View view) {
    
    
                           // getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
                                    getContext(), mAdmin);
                        }
                    });
        }
    }

    public void removeUnusableRotates(long maxRotate, EnforcedAdmin admin) {
    
    
        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        if (dpm == null) {
    
    
            return;
        }

        if (admin == null && mAdmin == null && !isDisabledByAdmin()) {
    
    
            return;
        }
        if (admin == null) {
    
    
            maxRotate = Long.MAX_VALUE;
        }

        ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
        ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
        for (int i = 0; i < mInitialValues.length; ++i) {
    
    
            long rotate = Long.parseLong(mInitialValues[i].toString());
            if (rotate <= maxRotate) {
    
    
                revisedEntries.add(mInitialEntries[i]);
                revisedValues.add(mInitialValues[i]);
            }
        }

        // If there are no possible options for the user, then set this preference as disabled
        // by admin, otherwise remove the padlock in case it was set earlier.
        if (revisedValues.size() == 0) {
    
    
            setDisabledByAdmin(admin);
            return;
        } else {
    
    
            setDisabledByAdmin(null);
        }

        if (revisedEntries.size() != getEntries().length) {
    
    
            final int userPreference = Integer.parseInt(getValue());
            setEntries(revisedEntries.toArray(new CharSequence[0]));
            setEntryValues(revisedValues.toArray(new CharSequence[0]));
            mAdmin = admin;
            if (userPreference <= maxRotate) {
    
    
                setValue(String.valueOf(userPreference));
            } else if (revisedValues.size() > 0
                    && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString())
                            == maxRotate) {
    
    
                // If the last one happens to be the same as the max rotate, select that
                setValue(String.valueOf(maxRotate));
            } else {
    
    
                // There will be no highlighted selection since nothing in the list matches
                // maxRotate. The user can still select anything less than maxRotate.
                // TODO: maybe append maxRotate to the list and mark selected.
            }
        }
    }
}

This file defines a list preference class for USB TP direction rotation. There is nothing much to say. After writing it several times, I found that it is all written in the same routine and fixed way.

packages/apps/Settings/src/com/android/settings/display/UsbTPRotatePreferenceController.java

package com.android.settings.display;

import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import com.android.settings.R;
import android.os.SystemProperties;
public class UsbTPRotatePreferenceController extends AbstractPreferenceController implements
        Preference.OnPreferenceChangeListener {
    
    

    private static final String TAG = "UsbTPRotatePrefContr";

    /** If there is no setting in the provider, use this. */
    public static final int FALLBACK_FORCE_APP_ROTATE_VALUE = 0;

    private final String mUsbTPRotateKey;

    public UsbTPRotatePreferenceController(Context context, String key) {
    
    
        super(context);
        mUsbTPRotateKey = key;
    }

    @Override
    public boolean isAvailable() {
    
    
        return true;
    }

    @Override
    public String getPreferenceKey() {
    
    
        return mUsbTPRotateKey;
    }

    @Override
    public void updateState(Preference preference) {
    
    
        final UsbTPRotateListPreference forceAppRotateListPreference = (UsbTPRotateListPreference) preference;
        long currentRotate = 0;
        currentRotate = SystemProperties.getInt("persist.sys.usbtp.rotation", 0);

        forceAppRotateListPreference.setValue(String.valueOf(currentRotate));

        updateRotatePreferenceDescription(forceAppRotateListPreference, currentRotate);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
    
    
        try {
    
    
            int value = Integer.parseInt((String) newValue);
            SystemProperties.set("persist.sys.usbtp.rotation", ""+value);
            updateRotatePreferenceDescription((UsbTPRotateListPreference) preference, value);
        } catch (NumberFormatException e) {
    
    
            Log.e(TAG, "could not persist force app rotate setting", e);
        }
        return true;
    }

    public static CharSequence getRotateDescription(
            long currentRotate, CharSequence[] entries, CharSequence[] values) {
    
    
        if (currentRotate < 0 || entries == null || values == null
                || values.length != entries.length) {
    
    
            return null;
        }

        for (int i = 0; i < values.length; i++) {
    
    
            long rotate = Long.parseLong(values[i].toString());
            if (currentRotate == rotate) {
    
    
                return entries[i];
            }
        }
        return null;
    }

    private void updateRotatePreferenceDescription(UsbTPRotateListPreference preference,
            long currentRotate) {
    
    
        final CharSequence[] entries = preference.getEntries();
        final CharSequence[] values = preference.getEntryValues();
        final String summary;

        if (preference.isDisabledByAdmin()) {
    
    
            summary = mContext.getString(com.android.settings.R.string.disabled_by_policy_title);
        } else {
    
    
            final CharSequence rotateDescription = getRotateDescription(
                    currentRotate, entries, values);
            summary = rotateDescription == null
                    ? ""
                    : mContext.getString(R.string.forceapp_rotate_summary, rotateDescription);
        }
        preference.setSummary(summary);
    }
}
  • Added an implementation of the UsbTPRotatePreferenceController class, which is a list preference controller used to control the direction of USB TP.
  • The getPreferenceKey method has been rewritten to return usbtp_rotate as the preference key.
  • The isAvailable method is overridden and returns true to indicate that this preference controller is always available.
  • The updateState method has been overridden to update the state of this preference element. It first gets the value of the system property persist.sys.usbtp.rotation, converts it to a long, and then sets it to the value of the list preference element. It then calls the updateRotatePreferenceDescription method, which updates the summary of the list preference element. This method will find the corresponding description in the entries and values ​​arrays based on the current direction value, and display it as a summary.
  • The onPreferenceChange method has been rewritten to respond to user operations. It takes the new value selected by the user, converts it to an integer, and sets it to the value of the system property persist.sys.usbtp.rotation. It calls the updateRotatePreferenceDescription method, which is used to update the list preference element display.

packages/apps/Settings/src/com/android/settings/display/UsbTPWakePreferenceController.java

package com.android.settings.display;

import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import android.os.SystemProperties;

public class UsbTPWakePreferenceController extends AbstractPreferenceController implements
        Preference.OnPreferenceChangeListener {
    
    

    private static final String TAG = "UsbTPWakeCtrl";
    private static final boolean DEBUG = true;
    private static final String KEY_USBTPWAKE = "ctrl_usbtpwake";
    private static final String SYS_PROP_USBTPWAKE_ENABLE = "persist.sys.usbtpwake.enable";

    public UsbTPWakePreferenceController(Context context) {
    
    
        super(context);
    }

    @Override
    public String getPreferenceKey() {
    
    
        return KEY_USBTPWAKE;
    }

    @Override
    public boolean isAvailable() {
    
    
        return true;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
    
    
        if (!isAvailable()) {
    
    
            setVisible(screen, KEY_USBTPWAKE, false);
            return;
        }

        final SwitchPreference mUsbTPWakePreference = screen.findPreference(KEY_USBTPWAKE);
        if (mUsbTPWakePreference != null) {
    
    
            String value = SystemProperties.get(SYS_PROP_USBTPWAKE_ENABLE, "false");
            mUsbTPWakePreference.setChecked(value.equals("true"));
            mUsbTPWakePreference.setOnPreferenceChangeListener(this);
        }
    }

    @Override
    public void updateState(Preference preference) {
    
    
        String value = SystemProperties.get(SYS_PROP_USBTPWAKE_ENABLE, "false");
        ((SwitchPreference) preference).setChecked(value.equals("true"));
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
    
    
        boolean value = (Boolean) newValue;
        if (DEBUG) {
    
    
            Log.d(TAG, "key value " + value);
        }
        SystemProperties.set(SYS_PROP_USBTPWAKE_ENABLE, ""+value);
        return true;
    }
}

packages/apps/Settings/src/com/android/settings/DisplaySettings.java

 import com.android.settings.display.ExPlanPreferenceController;
 import com.android.settings.display.ForceAppRotatePreferenceController;
 import com.android.settings.display.ScreenRotatePreferenceController;
+import com.android.settings.display.UsbTPWakePreferenceController;
+import com.android.settings.display.UsbTPRotatePreferenceController;

+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -102,6 +107,13 @@ public class DisplaySettings extends DashboardFragment {
    
    
         controllers.add(new ExPlanPreferenceController(context));
         controllers.add(new ForceAppRotatePreferenceController(context,"forceapp_rotate"));
         controllers.add(new ScreenRotatePreferenceController(context,"screen_rotate"));

+        
+        controllers.add(new UsbTPWakePreferenceController(context));
+        controllers.add(new UsbTPRotatePreferenceController(context,"usbtp_rotate"));

+
         return controllers;
     }
 

Test Results

  • To test whether my modifications worked, I connected a USB TP device to my device.

  • Enter the settings application, find the display settings interface, and control the two preference settings of USB TP wake-up and USB TP direction.

  • Trying to select different USB TP orientations, I found that when I select different orientations, the coordinate system of the USB TP will rotate accordingly and remain consistent with the display. Contents on the screen can be touched normally using USB TP in different orientations.
    Insert image description here

Conclusion

  • By modifying three modules of the Android system, I implemented the wake-up and rotation functions of USB TP, which improved customer and debugging convenience. Two preference elements have been added to the Settings module, allowing customers to see and modify USB TP-related functions in the settings application. I added two system properties in the inputflinger and surfaceflinger modules to allow the USB TP to work properly in different orientations and to wake up the device when it is sleeping.

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/132576404