Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +11 −147 Original line number Diff line number Diff line Loading @@ -208,7 +208,6 @@ import com.android.internal.policy.LogDecelerateInterpolator; import com.android.internal.policy.PhoneWindow; import com.android.internal.policy.TransitionAnimation; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockPatternUtils; import com.android.server.AccessibilityManagerInternal; Loading @@ -228,6 +227,7 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.vibrator.HapticFeedbackVibrationProvider; import com.android.server.vr.VrManagerInternal; import com.android.server.wallpaper.WallpaperManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; Loading Loading @@ -371,12 +371,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final String TALKBACK_LABEL = "TalkBack"; private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800; private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION); private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); /** * Keyguard stuff Loading Loading @@ -450,6 +444,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { PackageManager mPackageManager; SideFpsEventHandler mSideFpsEventHandler; LockPatternUtils mLockPatternUtils; private HapticFeedbackVibrationProvider mHapticFeedbackVibrationProvider; private boolean mHasFeatureAuto; private boolean mHasFeatureWatch; private boolean mHasFeatureLeanback; Loading @@ -458,9 +453,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Assigned on main thread, accessed on UI thread volatile VrManagerInternal mVrManagerInternal; // Vibrator pattern for haptic feedback during boot when safe mode is enabled. long[] mSafeModeEnabledVibePattern; /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ boolean mEnableShiftMenuBugReports = false; Loading Loading @@ -558,7 +550,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mPowerVolUpBehavior; boolean mStylusButtonsEnabled = true; boolean mHasSoftInput = false; boolean mHapticTextHandleEnabled; boolean mUseTvRouting; boolean mAllowStartActivityForLongPressOnPowerDuringSetup; MetricsLogger mLogger; Loading Loading @@ -2251,9 +2242,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup); mHapticTextHandleEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; mHandleVolumeKeysInWM = mContext.getResources().getBoolean( Loading Loading @@ -2294,8 +2282,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext.registerReceiver(mMultiuserReceiver, filter); mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeEnabledVibePattern); mHapticFeedbackVibrationProvider = new HapticFeedbackVibrationProvider(mContext.getResources(), mVibrator); mGlobalKeyManager = new GlobalKeyManager(mContext); Loading Loading @@ -5499,10 +5487,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } static long[] getLongIntArray(Resources r, int resid) { return ArrayUtils.convertToLongArray(r.getIntArray(resid)); } private void bindKeyguard() { synchronized (mLock) { if (mKeyguardBound) { Loading Loading @@ -5989,138 +5973,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!mVibrator.hasVibrator()) { return false; } VibrationEffect effect = getVibrationEffect(effectId); VibrationEffect effect = mHapticFeedbackVibrationProvider.getVibrationForHapticFeedback(effectId); if (effect == null) { return false; } VibrationAttributes attrs = getVibrationAttributes(effectId); if (always) { attrs = new VibrationAttributes.Builder(attrs) .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF) .build(); } VibrationAttributes attrs = mHapticFeedbackVibrationProvider.getVibrationAttributesForHapticFeedback( effectId, /* bypassVibrationIntensitySetting= */ always); mVibrator.vibrate(uid, packageName, effect, reason, attrs); return true; } private VibrationEffect getVibrationEffect(int effectId) { long[] pattern; switch (effectId) { case HapticFeedbackConstants.CONTEXT_CLICK: case HapticFeedbackConstants.GESTURE_END: case HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SEGMENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { return null; } // fallthrough case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.SEGMENT_FREQUENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS case HapticFeedbackConstants.VIRTUAL_KEY: case HapticFeedbackConstants.EDGE_RELEASE: case HapticFeedbackConstants.CALENDAR_DATE: case HapticFeedbackConstants.CONFIRM: case HapticFeedbackConstants.GESTURE_START: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.LONG_PRESS: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.DRAG_START: case HapticFeedbackConstants.EDGE_SQUEEZE: return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.REJECT: return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); case HapticFeedbackConstants.SAFE_MODE_ENABLED: pattern = mSafeModeEnabledVibePattern; break; case HapticFeedbackConstants.ASSISTANT_BUTTON: if (mVibrator.areAllPrimitivesSupported( VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, VibrationEffect.Composition.PRIMITIVE_TICK)) { // quiet ramp, short pause, then sharp tick return VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50) .compose(); } // fallback for devices without composition support return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.GESTURE_THRESHOLD_DEACTIVATE: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.4f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.TOGGLE_ON: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TOGGLE_OFF: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_LOW_TICK, 0.2f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.NO_HAPTICS: default: return null; } if (pattern.length == 0) { // No vibration return null; } else if (pattern.length == 1) { // One-shot vibration return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE); } else { // Pattern vibration return VibrationEffect.createWaveform(pattern, -1); } } private VibrationEffect getScaledPrimitiveOrElseEffect(int primitiveId, float scale, int elseEffectId) { if (mVibrator.areAllPrimitivesSupported(primitiveId)) { return VibrationEffect.startComposition() .addPrimitive(primitiveId, scale) .compose(); } else { return VibrationEffect.get(elseEffectId); } } private VibrationAttributes getVibrationAttributes(int effectId) { switch (effectId) { case HapticFeedbackConstants.EDGE_SQUEEZE: case HapticFeedbackConstants.EDGE_RELEASE: return PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES; case HapticFeedbackConstants.ASSISTANT_BUTTON: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; default: return TOUCH_VIBRATION_ATTRIBUTES; } } @Override public void keepScreenOnStartedLw() { Loading Loading @@ -6258,8 +6122,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup="); pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup); pw.print(prefix); pw.print("mHasSoftInput="); pw.print(mHasSoftInput); pw.print(" mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed); pw.print(" mIncallPowerBehavior="); Loading @@ -6284,6 +6147,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); mHapticFeedbackVibrationProvider.dump(prefix, pw); mGlobalKeyManager.dump(prefix, pw); mKeyCombinationManager.dump(prefix, pw); mSingleKeyGestureDetector.dump(prefix, pw); Loading services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java 0 → 100644 +194 −0 Original line number Diff line number Diff line /* * Copyright 2023 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. */ package com.android.server.vibrator; import android.annotation.Nullable; import android.content.res.Resources; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; import android.view.HapticFeedbackConstants; import java.io.PrintWriter; /** * Provides the {@link VibrationEffect} and {@link VibrationAttributes} for haptic feedback. * * @hide */ public final class HapticFeedbackVibrationProvider { private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION); private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); private final Vibrator mVibrator; private final boolean mHapticTextHandleEnabled; // Vibrator effect for haptic feedback during boot when safe mode is enabled. private final VibrationEffect mSafeModeEnabledVibrationEffect; /** @hide */ public HapticFeedbackVibrationProvider(Resources res, Vibrator vibrator) { mVibrator = vibrator; mHapticTextHandleEnabled = res.getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); mSafeModeEnabledVibrationEffect = VibrationSettings.createEffectFromResource( res, com.android.internal.R.array.config_safeModeEnabledVibePattern); } /** * Provides the {@link VibrationEffect} for a given haptic feedback effect ID (provided in * {@link HapticFeedbackConstants}). * * @param effectId the haptic feedback effect ID whose respective vibration we want to get. * @return a {@link VibrationEffect} for the given haptic feedback effect ID, or {@code null} if * the provided effect ID is not supported. */ @Nullable public VibrationEffect getVibrationForHapticFeedback(int effectId) { switch (effectId) { case HapticFeedbackConstants.CONTEXT_CLICK: case HapticFeedbackConstants.GESTURE_END: case HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SEGMENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { return null; } // fallthrough case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.SEGMENT_FREQUENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS case HapticFeedbackConstants.VIRTUAL_KEY: case HapticFeedbackConstants.EDGE_RELEASE: case HapticFeedbackConstants.CALENDAR_DATE: case HapticFeedbackConstants.CONFIRM: case HapticFeedbackConstants.GESTURE_START: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.LONG_PRESS: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.DRAG_START: case HapticFeedbackConstants.EDGE_SQUEEZE: return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.REJECT: return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); case HapticFeedbackConstants.SAFE_MODE_ENABLED: return mSafeModeEnabledVibrationEffect; case HapticFeedbackConstants.ASSISTANT_BUTTON: if (mVibrator.areAllPrimitivesSupported( VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, VibrationEffect.Composition.PRIMITIVE_TICK)) { // quiet ramp, short pause, then sharp tick return VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50) .compose(); } // fallback for devices without composition support return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.GESTURE_THRESHOLD_DEACTIVATE: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.4f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.TOGGLE_ON: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TOGGLE_OFF: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_LOW_TICK, 0.2f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.NO_HAPTICS: default: return null; } } /** * Provides the {@link VibrationAttributes} that should be used for a haptic feedback. * * @param effectId the haptic feedback effect ID whose respective vibration attributes we want * to get. * @param bypassVibrationIntensitySetting {@code true} if the returned attribute should bypass * vibration intensity settings. {@code false} otherwise. * @return the {@link VibrationAttributes} that should be used for the provided haptic feedback. */ public VibrationAttributes getVibrationAttributesForHapticFeedback( int effectId, boolean bypassVibrationIntensitySetting) { VibrationAttributes attrs; switch (effectId) { case HapticFeedbackConstants.EDGE_SQUEEZE: case HapticFeedbackConstants.EDGE_RELEASE: attrs = PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES; break; case HapticFeedbackConstants.ASSISTANT_BUTTON: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: attrs = HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; break; default: attrs = TOUCH_VIBRATION_ATTRIBUTES; } if (bypassVibrationIntensitySetting) { attrs = new VibrationAttributes.Builder(attrs) .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF) .build(); } return attrs; } /** Dumps relevant state. */ public void dump(String prefix, PrintWriter pw) { pw.print("mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled); } private VibrationEffect getScaledPrimitiveOrElseEffect( int primitiveId, float scale, int elseEffectId) { if (mVibrator.areAllPrimitivesSupported(primitiveId)) { return VibrationEffect.startComposition() .addPrimitive(primitiveId, scale) .compose(); } else { return VibrationEffect.get(elseEffectId); } } } services/core/java/com/android/server/vibrator/VibrationSettings.java +17 −1 Original line number Diff line number Diff line Loading @@ -698,7 +698,23 @@ final class VibrationSettings { @Nullable private VibrationEffect createEffectFromResource(int resId) { long[] timings = getLongIntArray(mContext.getResources(), resId); return createEffectFromResource(mContext.getResources(), resId); } /** * Provides a {@link VibrationEffect} from a timings-array provided as an int-array resource.. * * <p>If the timings array is {@code null} or empty, it returns {@code null}. * * <p>If the timings array has a size of one, it returns a one-shot vibration with duration that * is equal to the single value in the array. * * <p>If the timings array has more than one values, it returns a non-repeating wave-form * vibration with off-on timings as per the provided timings array. */ @Nullable static VibrationEffect createEffectFromResource(Resources res, int resId) { long[] timings = getLongIntArray(res, resId); return createEffectFromTimings(timings); } Loading Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +11 −147 Original line number Diff line number Diff line Loading @@ -208,7 +208,6 @@ import com.android.internal.policy.LogDecelerateInterpolator; import com.android.internal.policy.PhoneWindow; import com.android.internal.policy.TransitionAnimation; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockPatternUtils; import com.android.server.AccessibilityManagerInternal; Loading @@ -228,6 +227,7 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.vibrator.HapticFeedbackVibrationProvider; import com.android.server.vr.VrManagerInternal; import com.android.server.wallpaper.WallpaperManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; Loading Loading @@ -371,12 +371,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final String TALKBACK_LABEL = "TalkBack"; private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800; private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION); private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); /** * Keyguard stuff Loading Loading @@ -450,6 +444,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { PackageManager mPackageManager; SideFpsEventHandler mSideFpsEventHandler; LockPatternUtils mLockPatternUtils; private HapticFeedbackVibrationProvider mHapticFeedbackVibrationProvider; private boolean mHasFeatureAuto; private boolean mHasFeatureWatch; private boolean mHasFeatureLeanback; Loading @@ -458,9 +453,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Assigned on main thread, accessed on UI thread volatile VrManagerInternal mVrManagerInternal; // Vibrator pattern for haptic feedback during boot when safe mode is enabled. long[] mSafeModeEnabledVibePattern; /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ boolean mEnableShiftMenuBugReports = false; Loading Loading @@ -558,7 +550,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mPowerVolUpBehavior; boolean mStylusButtonsEnabled = true; boolean mHasSoftInput = false; boolean mHapticTextHandleEnabled; boolean mUseTvRouting; boolean mAllowStartActivityForLongPressOnPowerDuringSetup; MetricsLogger mLogger; Loading Loading @@ -2251,9 +2242,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup); mHapticTextHandleEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; mHandleVolumeKeysInWM = mContext.getResources().getBoolean( Loading Loading @@ -2294,8 +2282,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext.registerReceiver(mMultiuserReceiver, filter); mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeEnabledVibePattern); mHapticFeedbackVibrationProvider = new HapticFeedbackVibrationProvider(mContext.getResources(), mVibrator); mGlobalKeyManager = new GlobalKeyManager(mContext); Loading Loading @@ -5499,10 +5487,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } static long[] getLongIntArray(Resources r, int resid) { return ArrayUtils.convertToLongArray(r.getIntArray(resid)); } private void bindKeyguard() { synchronized (mLock) { if (mKeyguardBound) { Loading Loading @@ -5989,138 +5973,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!mVibrator.hasVibrator()) { return false; } VibrationEffect effect = getVibrationEffect(effectId); VibrationEffect effect = mHapticFeedbackVibrationProvider.getVibrationForHapticFeedback(effectId); if (effect == null) { return false; } VibrationAttributes attrs = getVibrationAttributes(effectId); if (always) { attrs = new VibrationAttributes.Builder(attrs) .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF) .build(); } VibrationAttributes attrs = mHapticFeedbackVibrationProvider.getVibrationAttributesForHapticFeedback( effectId, /* bypassVibrationIntensitySetting= */ always); mVibrator.vibrate(uid, packageName, effect, reason, attrs); return true; } private VibrationEffect getVibrationEffect(int effectId) { long[] pattern; switch (effectId) { case HapticFeedbackConstants.CONTEXT_CLICK: case HapticFeedbackConstants.GESTURE_END: case HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SEGMENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { return null; } // fallthrough case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.SEGMENT_FREQUENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS case HapticFeedbackConstants.VIRTUAL_KEY: case HapticFeedbackConstants.EDGE_RELEASE: case HapticFeedbackConstants.CALENDAR_DATE: case HapticFeedbackConstants.CONFIRM: case HapticFeedbackConstants.GESTURE_START: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.LONG_PRESS: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.DRAG_START: case HapticFeedbackConstants.EDGE_SQUEEZE: return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.REJECT: return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); case HapticFeedbackConstants.SAFE_MODE_ENABLED: pattern = mSafeModeEnabledVibePattern; break; case HapticFeedbackConstants.ASSISTANT_BUTTON: if (mVibrator.areAllPrimitivesSupported( VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, VibrationEffect.Composition.PRIMITIVE_TICK)) { // quiet ramp, short pause, then sharp tick return VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50) .compose(); } // fallback for devices without composition support return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.GESTURE_THRESHOLD_DEACTIVATE: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.4f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.TOGGLE_ON: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TOGGLE_OFF: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_LOW_TICK, 0.2f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.NO_HAPTICS: default: return null; } if (pattern.length == 0) { // No vibration return null; } else if (pattern.length == 1) { // One-shot vibration return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE); } else { // Pattern vibration return VibrationEffect.createWaveform(pattern, -1); } } private VibrationEffect getScaledPrimitiveOrElseEffect(int primitiveId, float scale, int elseEffectId) { if (mVibrator.areAllPrimitivesSupported(primitiveId)) { return VibrationEffect.startComposition() .addPrimitive(primitiveId, scale) .compose(); } else { return VibrationEffect.get(elseEffectId); } } private VibrationAttributes getVibrationAttributes(int effectId) { switch (effectId) { case HapticFeedbackConstants.EDGE_SQUEEZE: case HapticFeedbackConstants.EDGE_RELEASE: return PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES; case HapticFeedbackConstants.ASSISTANT_BUTTON: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; default: return TOUCH_VIBRATION_ATTRIBUTES; } } @Override public void keepScreenOnStartedLw() { Loading Loading @@ -6258,8 +6122,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup="); pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup); pw.print(prefix); pw.print("mHasSoftInput="); pw.print(mHasSoftInput); pw.print(" mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed); pw.print(" mIncallPowerBehavior="); Loading @@ -6284,6 +6147,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); mHapticFeedbackVibrationProvider.dump(prefix, pw); mGlobalKeyManager.dump(prefix, pw); mKeyCombinationManager.dump(prefix, pw); mSingleKeyGestureDetector.dump(prefix, pw); Loading
services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java 0 → 100644 +194 −0 Original line number Diff line number Diff line /* * Copyright 2023 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. */ package com.android.server.vibrator; import android.annotation.Nullable; import android.content.res.Resources; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; import android.view.HapticFeedbackConstants; import java.io.PrintWriter; /** * Provides the {@link VibrationEffect} and {@link VibrationAttributes} for haptic feedback. * * @hide */ public final class HapticFeedbackVibrationProvider { private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION); private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); private final Vibrator mVibrator; private final boolean mHapticTextHandleEnabled; // Vibrator effect for haptic feedback during boot when safe mode is enabled. private final VibrationEffect mSafeModeEnabledVibrationEffect; /** @hide */ public HapticFeedbackVibrationProvider(Resources res, Vibrator vibrator) { mVibrator = vibrator; mHapticTextHandleEnabled = res.getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); mSafeModeEnabledVibrationEffect = VibrationSettings.createEffectFromResource( res, com.android.internal.R.array.config_safeModeEnabledVibePattern); } /** * Provides the {@link VibrationEffect} for a given haptic feedback effect ID (provided in * {@link HapticFeedbackConstants}). * * @param effectId the haptic feedback effect ID whose respective vibration we want to get. * @return a {@link VibrationEffect} for the given haptic feedback effect ID, or {@code null} if * the provided effect ID is not supported. */ @Nullable public VibrationEffect getVibrationForHapticFeedback(int effectId) { switch (effectId) { case HapticFeedbackConstants.CONTEXT_CLICK: case HapticFeedbackConstants.GESTURE_END: case HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SEGMENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { return null; } // fallthrough case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.SEGMENT_FREQUENT_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS case HapticFeedbackConstants.VIRTUAL_KEY: case HapticFeedbackConstants.EDGE_RELEASE: case HapticFeedbackConstants.CALENDAR_DATE: case HapticFeedbackConstants.CONFIRM: case HapticFeedbackConstants.GESTURE_START: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.LONG_PRESS: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.DRAG_START: case HapticFeedbackConstants.EDGE_SQUEEZE: return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.REJECT: return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); case HapticFeedbackConstants.SAFE_MODE_ENABLED: return mSafeModeEnabledVibrationEffect; case HapticFeedbackConstants.ASSISTANT_BUTTON: if (mVibrator.areAllPrimitivesSupported( VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, VibrationEffect.Composition.PRIMITIVE_TICK)) { // quiet ramp, short pause, then sharp tick return VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50) .compose(); } // fallback for devices without composition support return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); case HapticFeedbackConstants.GESTURE_THRESHOLD_DEACTIVATE: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.4f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.TOGGLE_ON: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TOGGLE_OFF: return getScaledPrimitiveOrElseEffect( VibrationEffect.Composition.PRIMITIVE_LOW_TICK, 0.2f, VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.NO_HAPTICS: default: return null; } } /** * Provides the {@link VibrationAttributes} that should be used for a haptic feedback. * * @param effectId the haptic feedback effect ID whose respective vibration attributes we want * to get. * @param bypassVibrationIntensitySetting {@code true} if the returned attribute should bypass * vibration intensity settings. {@code false} otherwise. * @return the {@link VibrationAttributes} that should be used for the provided haptic feedback. */ public VibrationAttributes getVibrationAttributesForHapticFeedback( int effectId, boolean bypassVibrationIntensitySetting) { VibrationAttributes attrs; switch (effectId) { case HapticFeedbackConstants.EDGE_SQUEEZE: case HapticFeedbackConstants.EDGE_RELEASE: attrs = PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES; break; case HapticFeedbackConstants.ASSISTANT_BUTTON: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: attrs = HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; break; default: attrs = TOUCH_VIBRATION_ATTRIBUTES; } if (bypassVibrationIntensitySetting) { attrs = new VibrationAttributes.Builder(attrs) .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF) .build(); } return attrs; } /** Dumps relevant state. */ public void dump(String prefix, PrintWriter pw) { pw.print("mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled); } private VibrationEffect getScaledPrimitiveOrElseEffect( int primitiveId, float scale, int elseEffectId) { if (mVibrator.areAllPrimitivesSupported(primitiveId)) { return VibrationEffect.startComposition() .addPrimitive(primitiveId, scale) .compose(); } else { return VibrationEffect.get(elseEffectId); } } }
services/core/java/com/android/server/vibrator/VibrationSettings.java +17 −1 Original line number Diff line number Diff line Loading @@ -698,7 +698,23 @@ final class VibrationSettings { @Nullable private VibrationEffect createEffectFromResource(int resId) { long[] timings = getLongIntArray(mContext.getResources(), resId); return createEffectFromResource(mContext.getResources(), resId); } /** * Provides a {@link VibrationEffect} from a timings-array provided as an int-array resource.. * * <p>If the timings array is {@code null} or empty, it returns {@code null}. * * <p>If the timings array has a size of one, it returns a one-shot vibration with duration that * is equal to the single value in the array. * * <p>If the timings array has more than one values, it returns a non-repeating wave-form * vibration with off-on timings as per the provided timings array. */ @Nullable static VibrationEffect createEffectFromResource(Resources res, int resId) { long[] timings = getLongIntArray(res, resId); return createEffectFromTimings(timings); } Loading