Loading services/art-wear-profile +2 −2 Original line number Diff line number Diff line Loading @@ -1255,8 +1255,8 @@ Lcom/android/server/utils/WatchedSparseIntArray; Lcom/android/server/utils/WatchedSparseSetArray; Lcom/android/server/utils/Watcher; Lcom/android/server/vibrator/HalVibrator$Callbacks; Lcom/android/server/vibrator/HalVibratorManager$Callbacks; Lcom/android/server/vibrator/VibratorController$NativeWrapper; Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks; Lcom/android/server/vibrator/VibratorManagerService; Lcom/android/server/wm/AbsAppSnapshotController; Lcom/android/server/wm/ActionChain$Tracker; Loading Loading @@ -19865,7 +19865,7 @@ PLcom/android/server/vibrator/VibratorManagerService$Lifecycle;->onStart()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;-><init>()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->cancelSynced()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->clearSessions()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->init(Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks;)V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->init(Lcom/android/server/vibrator/HalVibratorManager$Callbacks;)V PLcom/android/server/vibrator/VibratorManagerService$VendorVibrationSessionCallbacks;-><init>(Lcom/android/server/vibrator/VibratorManagerService;)V PLcom/android/server/vibrator/VibratorManagerService$VibrationCompleteListener;->onComplete(IJ)V PLcom/android/server/vibrator/VibratorManagerService$VibrationRecord;-><init>(Lcom/android/server/vibrator/VibrationSession$DebugInfo;)V services/core/java/com/android/server/vibrator/HalVibratorManager.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.NonNull; import android.util.IndentingPrintWriter; /** Handles interactions with a vibrator manager HAL. */ interface HalVibratorManager { /** Callbacks from the vibrator manager HAL. */ interface Callbacks { /** Callback triggered when synced vibration is complete. */ void onSyncedVibrationComplete(long vibrationId); /** Callback triggered when vibration session is complete. */ void onVibrationSessionComplete(long sessionId); } /** Initializes the HAL and set the callback instance for future interactions. */ void init(@NonNull Callbacks callbacks); /** Notifies the boot phase system ready. This might load some HAL static data. */ void onSystemReady(); /** Return the vibrator manager capabilities. */ long getCapabilities(); /** Return true if vibrator manager has required capability, false otherwise. */ default boolean hasCapability(long capability) { return (getCapabilities() & capability) == capability; } /** Return the IDs of the vibrators controlled by this manager. */ @NonNull int[] getVibratorIds(); /** Prepare vibrators for triggering vibrations in sync. */ boolean prepareSynced(@NonNull int[] vibratorIds); /** Trigger prepared synced vibration. */ boolean triggerSynced(long vibrationId); /** Cancel prepared synced vibration. */ boolean cancelSynced(); /** Start vibration session. */ boolean startSession(long sessionId, @NonNull int[] vibratorIds); /** End vibration session. */ boolean endSession(long sessionId, boolean shouldAbort); /** Writes information into dumpsys. */ void dump(IndentingPrintWriter pw); } services/core/java/com/android/server/vibrator/VibratorManagerService.java +141 −70 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.server.vibrator; import static android.os.Trace.TRACE_TAG_VIBRATOR; import static android.os.VibrationAttributes.USAGE_CLASS_ALARM; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import static android.os.VibrationAttributes.USAGE_UNKNOWN; import static android.os.VibrationAttributes.USAGE_CLASS_FEEDBACK; import static android.os.VibrationAttributes.USAGE_CLASS_MASK; import static android.os.VibrationAttributes.USAGE_UNKNOWN; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -160,10 +160,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private final Handler mHandler; private final VibrationThread mVibrationThread; private final AppOpsManager mAppOps; private final NativeWrapper mNativeWrapper; private final HalVibratorManager mVibratorManager; private final VibratorManagerRecords mVibratorManagerRecords; private final long mCapabilities; private final int[] mVibratorIds; private final SparseArray<HalVibrator> mVibrators; private final VibrationThreadCallbacks mVibrationThreadCallbacks = new VibrationThreadCallbacks(); Loading Loading @@ -234,7 +232,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } }; static native long nativeInit(VibratorManagerNativeCallbacks listener); // TODO(b/409002423): remove the native methods once remove_hidl_support flag removed static native long nativeInit(HalVibratorManager.Callbacks callback); static native long nativeGetFinalizer(); Loading Loading @@ -271,8 +270,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler); HalListener halListener = new HalListener(this); mNativeWrapper = injector.getNativeWrapper(); mNativeWrapper.init(halListener); mVibratorManager = injector.createHalVibratorManager(); mVibratorManager.init(halListener); int recentDumpSizeLimit = mContext.getResources().getInteger( com.android.internal.R.integer.config_recentVibrationsDumpSizeLimit); Loading @@ -295,35 +294,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationThread = new VibrationThread(mWakeLock, mVibrationThreadCallbacks); mVibrationThread.start(); // Load vibrator hardware info. The vibrator ids and manager capabilities are loaded only // once and assumed unchanged for the lifecycle of this service. Each individual vibrator // can still retry loading each individual vibrator hardware spec once more at systemReady. mCapabilities = mNativeWrapper.getCapabilities(); int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds == null) { mVibratorIds = new int[0]; mVibrators = new SparseArray<>(0); } else { // Keep original vibrator id order, which might be meaningful. mVibratorIds = vibratorIds; mVibrators = new SparseArray<>(mVibratorIds.length); int[] vibratorIds = mVibratorManager.getVibratorIds(); mVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = injector.createHalVibrator(vibratorId); vibrator.init(halListener); mVibrators.put(vibratorId, vibrator); } } // Load vibrator adapter, that depends on hardware info. mDeviceAdapter = new DeviceAdapter(mVibrationSettings, mVibrators); // Reset the hardware to a default state, in case this is a runtime restart instead of a // fresh boot. mNativeWrapper.cancelSynced(); if (Flags.vendorVibrationEffects()) { mNativeWrapper.clearSessions(); } IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); if (UserManagerInternal.shouldShowNotificationForBackgroundUserSounds()) { Loading @@ -344,6 +325,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.v(TAG, "Initializing VibratorManager service..."); Trace.traceBegin(TRACE_TAG_VIBRATOR, "systemReady"); try { mVibratorManager.onSystemReady(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).onSystemReady(); } Loading Loading @@ -375,12 +357,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public int[] getVibratorIds() { return Arrays.copyOf(mVibratorIds, mVibratorIds.length); int[] vibratorIds = mVibratorManager.getVibratorIds(); return Arrays.copyOf(vibratorIds, vibratorIds.length); } @Override // Binder call public int getCapabilities() { return (int) mCapabilities; return (int) mVibratorManager.getCapabilities(); } @Override // Binder call Loading Loading @@ -806,7 +789,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { CallerInfo ignoredBy = null; // Check if HAL has capability to start sessions. if ((mCapabilities & IVibratorManager.CAP_START_SESSIONS) == 0) { if (!mVibratorManager.hasCapability(IVibratorManager.CAP_START_SESSIONS)) { if (DEBUG) { Slog.d(TAG, "Missing capability to start sessions, ignoring request"); } Loading @@ -815,11 +798,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Check if vibrator IDs requested are available. if (ignoreStatus == null) { if (vibratorIds.length == 0 || vibratorIds.length != deviceAdapter.getAvailableVibratorIds().length) { int[] availableVibratorIds = deviceAdapter.getAvailableVibratorIds(); if (vibratorIds.length == 0 || vibratorIds.length != availableVibratorIds.length) { Slog.e(TAG, "Bad vibrator ids to start session, ignoring request." + " requested=" + Arrays.toString(vibratorIds) + " available=" + Arrays.toString(mVibratorIds)); + " available=" + Arrays.toString(availableVibratorIds)); ignoreStatus = Status.IGNORED_UNSUPPORTED; } } Loading Loading @@ -890,7 +873,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mCurrentSession = null; return Status.IGNORED_ERROR_TOKEN; } if (!mNativeWrapper.startSession(sessionId, session.getVibratorIds())) { if (!mVibratorManager.startSession(sessionId, session.getVibratorIds())) { Slog.e(TAG, "Error starting session " + sessionId + " on vibrators " + Arrays.toString(session.getVibratorIds())); session.unlinkToDeath(); Loading Loading @@ -949,6 +932,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationScaler.dump(pw); pw.println(); mVibratorManager.dump(pw); pw.println(); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { Loading Loading @@ -1741,10 +1727,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @VisibleForTesting static class Injector { NativeWrapper getNativeWrapper() { return new NativeWrapper(); } Handler createHandler(Looper looper) { return new Handler(looper); } Loading @@ -1758,6 +1740,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return new VibratorFrameworkStatsLogger(handler); } HalVibratorManager createHalVibratorManager() { return new NativeHalVibratorManager(new NativeWrapper()); } HalVibrator createHalVibrator(int vibratorId) { return new VibratorController(vibratorId); } Loading Loading @@ -1790,12 +1776,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean prepareSyncedVibration(long requiredCapabilities, int[] vibratorIds) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "prepareSyncedVibration"); try { if ((mCapabilities & requiredCapabilities) != requiredCapabilities) { // This sync step requires capabilities this device doesn't have, skipping // sync... if (!mVibratorManager.hasCapability(requiredCapabilities)) { // This sync step requires capabilities this device doesn't have, skipping... return false; } return mNativeWrapper.prepareSynced(vibratorIds); return mVibratorManager.prepareSynced(vibratorIds); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading @@ -1805,7 +1790,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean triggerSyncedVibration(long vibrationId) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "triggerSyncedVibration"); try { return mNativeWrapper.triggerSynced(vibrationId); return mVibratorManager.triggerSynced(vibrationId); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading @@ -1815,7 +1800,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public void cancelSyncedVibration() { Trace.traceBegin(TRACE_TAG_VIBRATOR, "cancelSyncedVibration"); try { mNativeWrapper.cancelSynced(); mVibratorManager.cancelSynced(); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -2039,7 +2024,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } Trace.traceBegin(TRACE_TAG_VIBRATOR, "endSession"); try { mNativeWrapper.endSession(sessionId, shouldAbort); mVibratorManager.endSession(sessionId, shouldAbort); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -2083,22 +2068,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } /** Listener for vibrator manager completion callbacks from native. */ @VisibleForTesting interface VibratorManagerNativeCallbacks { /** Callback triggered when synced vibration is complete. */ void onSyncedVibrationComplete(long vibrationId); /** Callback triggered when vibration session is complete. */ void onVibrationSessionComplete(long sessionId); } /** * Implementation of listeners to native vibrators with a weak reference to this service. */ private static final class HalListener implements HalVibrator.Callbacks, VibratorManagerNativeCallbacks { implements HalVibrator.Callbacks, HalVibratorManager.Callbacks { private WeakReference<VibratorManagerService> mServiceRef; HalListener(VibratorManagerService service) { Loading Loading @@ -2147,15 +2121,111 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } /** Controls the vibrator manager HAL. */ // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeHalVibratorManager implements HalVibratorManager { private final NativeWrapper mNativeWrapper; // Variables that are updated from synchronized blocks but can be read anytime // for a snippet of the current known vibrator manager info. private volatile long mCapabilities; private volatile int[] mVibratorIds = new int[0]; NativeHalVibratorManager(NativeWrapper nativeWrapper) { mNativeWrapper = nativeWrapper; } @Override public void init(@NonNull Callbacks callbacks) { mNativeWrapper.init(callbacks); // Load vibrator hardware info. The vibrator ids and manager capabilities are loaded // once and assumed unchanged for the lifecycle of this service. Each vibrator can still // retry loading each individual vibrator hardware spec once more at systemReady. mCapabilities = mNativeWrapper.getCapabilities(); // Keep original vibrator id order, which might be meaningful. int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds != null) { mVibratorIds = vibratorIds; } // Reset the hardware to a default state. // In case this is a runtime restart instead of a fresh boot. cancelSynced(); if (Flags.vendorVibrationEffects()) { mNativeWrapper.clearSessions(); } } @Override public void onSystemReady() { } @Override public long getCapabilities() { return mCapabilities; } @NonNull @Override public int[] getVibratorIds() { return mVibratorIds; } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return mNativeWrapper.prepareSynced(vibratorIds); } @Override public boolean triggerSynced(long vibrationId) { return mNativeWrapper.triggerSynced(vibrationId); } @Override public boolean cancelSynced() { mNativeWrapper.cancelSynced(); return hasCapability(IVibratorManager.CAP_SYNC); } @Override public boolean startSession(long sessionId, @NonNull int[] vibratorIds) { return mNativeWrapper.startSession(sessionId, vibratorIds); } @Override public boolean endSession(long sessionId, boolean shouldAbort) { mNativeWrapper.endSession(sessionId, shouldAbort); return hasCapability(IVibratorManager.CAP_START_SESSIONS); } @Override public void dump(IndentingPrintWriter pw) { pw.println("Native HAL VibratorManager:"); pw.increaseIndent(); pw.println("capabilitiesFlags = " + Long.toBinaryString(mCapabilities)); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.decreaseIndent(); } @Override public String toString() { return "NativeHalVibratorManager{" + "mCapabilities flags=" + Long.toBinaryString(mCapabilities) + ", mVibratorIds=" + Arrays.toString(mVibratorIds) + '}'; } } /** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */ @VisibleForTesting // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeWrapper { private long mNativeServicePtr = 0; /** Returns native pointer to newly created controller and connects with HAL service. */ public void init(VibratorManagerNativeCallbacks listener) { mNativeServicePtr = nativeInit(listener); public void init(HalVibratorManager.Callbacks callback) { mNativeServicePtr = nativeInit(callback); long finalizerPtr = nativeGetFinalizer(); if (finalizerPtr != 0) { Loading @@ -2177,7 +2247,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } /** Prepare vibrators for triggering vibrations in sync. */ public boolean prepareSynced(@NonNull int[] vibratorIds) { public boolean prepareSynced(int[] vibratorIds) { return nativePrepareSynced(mNativeServicePtr, vibratorIds); } Loading @@ -2192,7 +2262,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } /** Start vibration session. */ public boolean startSession(long sessionId, @NonNull int[] vibratorIds) { public boolean startSession(long sessionId, int[] vibratorIds) { return nativeStartSession(mNativeServicePtr, sessionId, vibratorIds); } Loading Loading @@ -2671,10 +2741,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private int runListVibrators() { try (PrintWriter pw = getOutPrintWriter();) { if (mVibratorIds.length == 0) { int[] vibratorIds = mVibratorManager.getVibratorIds(); if (vibratorIds.length == 0) { pw.println("No vibrator found"); } else { for (int id : mVibratorIds) { for (int id : vibratorIds) { pw.println(id); } } Loading services/core/jni/com_android_server_vibrator_VibratorManagerService.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -255,7 +255,7 @@ static void nativeClearSessions(JNIEnv* env, jclass /* clazz */, jlong servicePt } inline static constexpr auto sNativeInitMethodSignature = "(Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks;)J"; "(Lcom/android/server/vibrator/HalVibratorManager$Callbacks;)J"; static const JNINativeMethod method_table[] = { {"nativeInit", sNativeInitMethodSignature, (void*)nativeInit}, Loading @@ -272,8 +272,7 @@ static const JNINativeMethod method_table[] = { int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) { sJvm = jvm; auto listenerClassName = "com/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks"; auto listenerClassName = "com/android/server/vibrator/HalVibratorManager$Callbacks"; jclass listenerClass = FindClassOrDie(env, listenerClassName); sMethodIdOnSyncedVibrationComplete = GetMethodIDOrDie(env, listenerClass, "onSyncedVibrationComplete", "(J)V"); Loading services/proguard.flags +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaJackDetector { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaMidiDevice { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.HalVibrator$Callbacks { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorManagerService$VibratorManagerNativeCallbacks { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.HalVibratorManager$Callbacks { *; } -keepclasseswithmembers,allowoptimization,allowaccessmodification class com.android.server.** { *** *FromNative(...); } Loading Loading
services/art-wear-profile +2 −2 Original line number Diff line number Diff line Loading @@ -1255,8 +1255,8 @@ Lcom/android/server/utils/WatchedSparseIntArray; Lcom/android/server/utils/WatchedSparseSetArray; Lcom/android/server/utils/Watcher; Lcom/android/server/vibrator/HalVibrator$Callbacks; Lcom/android/server/vibrator/HalVibratorManager$Callbacks; Lcom/android/server/vibrator/VibratorController$NativeWrapper; Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks; Lcom/android/server/vibrator/VibratorManagerService; Lcom/android/server/wm/AbsAppSnapshotController; Lcom/android/server/wm/ActionChain$Tracker; Loading Loading @@ -19865,7 +19865,7 @@ PLcom/android/server/vibrator/VibratorManagerService$Lifecycle;->onStart()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;-><init>()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->cancelSynced()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->clearSessions()V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->init(Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks;)V PLcom/android/server/vibrator/VibratorManagerService$NativeWrapper;->init(Lcom/android/server/vibrator/HalVibratorManager$Callbacks;)V PLcom/android/server/vibrator/VibratorManagerService$VendorVibrationSessionCallbacks;-><init>(Lcom/android/server/vibrator/VibratorManagerService;)V PLcom/android/server/vibrator/VibratorManagerService$VibrationCompleteListener;->onComplete(IJ)V PLcom/android/server/vibrator/VibratorManagerService$VibrationRecord;-><init>(Lcom/android/server/vibrator/VibrationSession$DebugInfo;)V
services/core/java/com/android/server/vibrator/HalVibratorManager.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.NonNull; import android.util.IndentingPrintWriter; /** Handles interactions with a vibrator manager HAL. */ interface HalVibratorManager { /** Callbacks from the vibrator manager HAL. */ interface Callbacks { /** Callback triggered when synced vibration is complete. */ void onSyncedVibrationComplete(long vibrationId); /** Callback triggered when vibration session is complete. */ void onVibrationSessionComplete(long sessionId); } /** Initializes the HAL and set the callback instance for future interactions. */ void init(@NonNull Callbacks callbacks); /** Notifies the boot phase system ready. This might load some HAL static data. */ void onSystemReady(); /** Return the vibrator manager capabilities. */ long getCapabilities(); /** Return true if vibrator manager has required capability, false otherwise. */ default boolean hasCapability(long capability) { return (getCapabilities() & capability) == capability; } /** Return the IDs of the vibrators controlled by this manager. */ @NonNull int[] getVibratorIds(); /** Prepare vibrators for triggering vibrations in sync. */ boolean prepareSynced(@NonNull int[] vibratorIds); /** Trigger prepared synced vibration. */ boolean triggerSynced(long vibrationId); /** Cancel prepared synced vibration. */ boolean cancelSynced(); /** Start vibration session. */ boolean startSession(long sessionId, @NonNull int[] vibratorIds); /** End vibration session. */ boolean endSession(long sessionId, boolean shouldAbort); /** Writes information into dumpsys. */ void dump(IndentingPrintWriter pw); }
services/core/java/com/android/server/vibrator/VibratorManagerService.java +141 −70 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.server.vibrator; import static android.os.Trace.TRACE_TAG_VIBRATOR; import static android.os.VibrationAttributes.USAGE_CLASS_ALARM; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import static android.os.VibrationAttributes.USAGE_UNKNOWN; import static android.os.VibrationAttributes.USAGE_CLASS_FEEDBACK; import static android.os.VibrationAttributes.USAGE_CLASS_MASK; import static android.os.VibrationAttributes.USAGE_UNKNOWN; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -160,10 +160,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private final Handler mHandler; private final VibrationThread mVibrationThread; private final AppOpsManager mAppOps; private final NativeWrapper mNativeWrapper; private final HalVibratorManager mVibratorManager; private final VibratorManagerRecords mVibratorManagerRecords; private final long mCapabilities; private final int[] mVibratorIds; private final SparseArray<HalVibrator> mVibrators; private final VibrationThreadCallbacks mVibrationThreadCallbacks = new VibrationThreadCallbacks(); Loading Loading @@ -234,7 +232,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } }; static native long nativeInit(VibratorManagerNativeCallbacks listener); // TODO(b/409002423): remove the native methods once remove_hidl_support flag removed static native long nativeInit(HalVibratorManager.Callbacks callback); static native long nativeGetFinalizer(); Loading Loading @@ -271,8 +270,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler); HalListener halListener = new HalListener(this); mNativeWrapper = injector.getNativeWrapper(); mNativeWrapper.init(halListener); mVibratorManager = injector.createHalVibratorManager(); mVibratorManager.init(halListener); int recentDumpSizeLimit = mContext.getResources().getInteger( com.android.internal.R.integer.config_recentVibrationsDumpSizeLimit); Loading @@ -295,35 +294,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationThread = new VibrationThread(mWakeLock, mVibrationThreadCallbacks); mVibrationThread.start(); // Load vibrator hardware info. The vibrator ids and manager capabilities are loaded only // once and assumed unchanged for the lifecycle of this service. Each individual vibrator // can still retry loading each individual vibrator hardware spec once more at systemReady. mCapabilities = mNativeWrapper.getCapabilities(); int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds == null) { mVibratorIds = new int[0]; mVibrators = new SparseArray<>(0); } else { // Keep original vibrator id order, which might be meaningful. mVibratorIds = vibratorIds; mVibrators = new SparseArray<>(mVibratorIds.length); int[] vibratorIds = mVibratorManager.getVibratorIds(); mVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = injector.createHalVibrator(vibratorId); vibrator.init(halListener); mVibrators.put(vibratorId, vibrator); } } // Load vibrator adapter, that depends on hardware info. mDeviceAdapter = new DeviceAdapter(mVibrationSettings, mVibrators); // Reset the hardware to a default state, in case this is a runtime restart instead of a // fresh boot. mNativeWrapper.cancelSynced(); if (Flags.vendorVibrationEffects()) { mNativeWrapper.clearSessions(); } IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); if (UserManagerInternal.shouldShowNotificationForBackgroundUserSounds()) { Loading @@ -344,6 +325,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.v(TAG, "Initializing VibratorManager service..."); Trace.traceBegin(TRACE_TAG_VIBRATOR, "systemReady"); try { mVibratorManager.onSystemReady(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).onSystemReady(); } Loading Loading @@ -375,12 +357,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public int[] getVibratorIds() { return Arrays.copyOf(mVibratorIds, mVibratorIds.length); int[] vibratorIds = mVibratorManager.getVibratorIds(); return Arrays.copyOf(vibratorIds, vibratorIds.length); } @Override // Binder call public int getCapabilities() { return (int) mCapabilities; return (int) mVibratorManager.getCapabilities(); } @Override // Binder call Loading Loading @@ -806,7 +789,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { CallerInfo ignoredBy = null; // Check if HAL has capability to start sessions. if ((mCapabilities & IVibratorManager.CAP_START_SESSIONS) == 0) { if (!mVibratorManager.hasCapability(IVibratorManager.CAP_START_SESSIONS)) { if (DEBUG) { Slog.d(TAG, "Missing capability to start sessions, ignoring request"); } Loading @@ -815,11 +798,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Check if vibrator IDs requested are available. if (ignoreStatus == null) { if (vibratorIds.length == 0 || vibratorIds.length != deviceAdapter.getAvailableVibratorIds().length) { int[] availableVibratorIds = deviceAdapter.getAvailableVibratorIds(); if (vibratorIds.length == 0 || vibratorIds.length != availableVibratorIds.length) { Slog.e(TAG, "Bad vibrator ids to start session, ignoring request." + " requested=" + Arrays.toString(vibratorIds) + " available=" + Arrays.toString(mVibratorIds)); + " available=" + Arrays.toString(availableVibratorIds)); ignoreStatus = Status.IGNORED_UNSUPPORTED; } } Loading Loading @@ -890,7 +873,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mCurrentSession = null; return Status.IGNORED_ERROR_TOKEN; } if (!mNativeWrapper.startSession(sessionId, session.getVibratorIds())) { if (!mVibratorManager.startSession(sessionId, session.getVibratorIds())) { Slog.e(TAG, "Error starting session " + sessionId + " on vibrators " + Arrays.toString(session.getVibratorIds())); session.unlinkToDeath(); Loading Loading @@ -949,6 +932,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationScaler.dump(pw); pw.println(); mVibratorManager.dump(pw); pw.println(); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { Loading Loading @@ -1741,10 +1727,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @VisibleForTesting static class Injector { NativeWrapper getNativeWrapper() { return new NativeWrapper(); } Handler createHandler(Looper looper) { return new Handler(looper); } Loading @@ -1758,6 +1740,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return new VibratorFrameworkStatsLogger(handler); } HalVibratorManager createHalVibratorManager() { return new NativeHalVibratorManager(new NativeWrapper()); } HalVibrator createHalVibrator(int vibratorId) { return new VibratorController(vibratorId); } Loading Loading @@ -1790,12 +1776,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean prepareSyncedVibration(long requiredCapabilities, int[] vibratorIds) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "prepareSyncedVibration"); try { if ((mCapabilities & requiredCapabilities) != requiredCapabilities) { // This sync step requires capabilities this device doesn't have, skipping // sync... if (!mVibratorManager.hasCapability(requiredCapabilities)) { // This sync step requires capabilities this device doesn't have, skipping... return false; } return mNativeWrapper.prepareSynced(vibratorIds); return mVibratorManager.prepareSynced(vibratorIds); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading @@ -1805,7 +1790,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean triggerSyncedVibration(long vibrationId) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "triggerSyncedVibration"); try { return mNativeWrapper.triggerSynced(vibrationId); return mVibratorManager.triggerSynced(vibrationId); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading @@ -1815,7 +1800,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public void cancelSyncedVibration() { Trace.traceBegin(TRACE_TAG_VIBRATOR, "cancelSyncedVibration"); try { mNativeWrapper.cancelSynced(); mVibratorManager.cancelSynced(); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -2039,7 +2024,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } Trace.traceBegin(TRACE_TAG_VIBRATOR, "endSession"); try { mNativeWrapper.endSession(sessionId, shouldAbort); mVibratorManager.endSession(sessionId, shouldAbort); } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -2083,22 +2068,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } /** Listener for vibrator manager completion callbacks from native. */ @VisibleForTesting interface VibratorManagerNativeCallbacks { /** Callback triggered when synced vibration is complete. */ void onSyncedVibrationComplete(long vibrationId); /** Callback triggered when vibration session is complete. */ void onVibrationSessionComplete(long sessionId); } /** * Implementation of listeners to native vibrators with a weak reference to this service. */ private static final class HalListener implements HalVibrator.Callbacks, VibratorManagerNativeCallbacks { implements HalVibrator.Callbacks, HalVibratorManager.Callbacks { private WeakReference<VibratorManagerService> mServiceRef; HalListener(VibratorManagerService service) { Loading Loading @@ -2147,15 +2121,111 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } /** Controls the vibrator manager HAL. */ // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeHalVibratorManager implements HalVibratorManager { private final NativeWrapper mNativeWrapper; // Variables that are updated from synchronized blocks but can be read anytime // for a snippet of the current known vibrator manager info. private volatile long mCapabilities; private volatile int[] mVibratorIds = new int[0]; NativeHalVibratorManager(NativeWrapper nativeWrapper) { mNativeWrapper = nativeWrapper; } @Override public void init(@NonNull Callbacks callbacks) { mNativeWrapper.init(callbacks); // Load vibrator hardware info. The vibrator ids and manager capabilities are loaded // once and assumed unchanged for the lifecycle of this service. Each vibrator can still // retry loading each individual vibrator hardware spec once more at systemReady. mCapabilities = mNativeWrapper.getCapabilities(); // Keep original vibrator id order, which might be meaningful. int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds != null) { mVibratorIds = vibratorIds; } // Reset the hardware to a default state. // In case this is a runtime restart instead of a fresh boot. cancelSynced(); if (Flags.vendorVibrationEffects()) { mNativeWrapper.clearSessions(); } } @Override public void onSystemReady() { } @Override public long getCapabilities() { return mCapabilities; } @NonNull @Override public int[] getVibratorIds() { return mVibratorIds; } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return mNativeWrapper.prepareSynced(vibratorIds); } @Override public boolean triggerSynced(long vibrationId) { return mNativeWrapper.triggerSynced(vibrationId); } @Override public boolean cancelSynced() { mNativeWrapper.cancelSynced(); return hasCapability(IVibratorManager.CAP_SYNC); } @Override public boolean startSession(long sessionId, @NonNull int[] vibratorIds) { return mNativeWrapper.startSession(sessionId, vibratorIds); } @Override public boolean endSession(long sessionId, boolean shouldAbort) { mNativeWrapper.endSession(sessionId, shouldAbort); return hasCapability(IVibratorManager.CAP_START_SESSIONS); } @Override public void dump(IndentingPrintWriter pw) { pw.println("Native HAL VibratorManager:"); pw.increaseIndent(); pw.println("capabilitiesFlags = " + Long.toBinaryString(mCapabilities)); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.decreaseIndent(); } @Override public String toString() { return "NativeHalVibratorManager{" + "mCapabilities flags=" + Long.toBinaryString(mCapabilities) + ", mVibratorIds=" + Arrays.toString(mVibratorIds) + '}'; } } /** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */ @VisibleForTesting // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeWrapper { private long mNativeServicePtr = 0; /** Returns native pointer to newly created controller and connects with HAL service. */ public void init(VibratorManagerNativeCallbacks listener) { mNativeServicePtr = nativeInit(listener); public void init(HalVibratorManager.Callbacks callback) { mNativeServicePtr = nativeInit(callback); long finalizerPtr = nativeGetFinalizer(); if (finalizerPtr != 0) { Loading @@ -2177,7 +2247,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } /** Prepare vibrators for triggering vibrations in sync. */ public boolean prepareSynced(@NonNull int[] vibratorIds) { public boolean prepareSynced(int[] vibratorIds) { return nativePrepareSynced(mNativeServicePtr, vibratorIds); } Loading @@ -2192,7 +2262,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } /** Start vibration session. */ public boolean startSession(long sessionId, @NonNull int[] vibratorIds) { public boolean startSession(long sessionId, int[] vibratorIds) { return nativeStartSession(mNativeServicePtr, sessionId, vibratorIds); } Loading Loading @@ -2671,10 +2741,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private int runListVibrators() { try (PrintWriter pw = getOutPrintWriter();) { if (mVibratorIds.length == 0) { int[] vibratorIds = mVibratorManager.getVibratorIds(); if (vibratorIds.length == 0) { pw.println("No vibrator found"); } else { for (int id : mVibratorIds) { for (int id : vibratorIds) { pw.println(id); } } Loading
services/core/jni/com_android_server_vibrator_VibratorManagerService.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -255,7 +255,7 @@ static void nativeClearSessions(JNIEnv* env, jclass /* clazz */, jlong servicePt } inline static constexpr auto sNativeInitMethodSignature = "(Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks;)J"; "(Lcom/android/server/vibrator/HalVibratorManager$Callbacks;)J"; static const JNINativeMethod method_table[] = { {"nativeInit", sNativeInitMethodSignature, (void*)nativeInit}, Loading @@ -272,8 +272,7 @@ static const JNINativeMethod method_table[] = { int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) { sJvm = jvm; auto listenerClassName = "com/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks"; auto listenerClassName = "com/android/server/vibrator/HalVibratorManager$Callbacks"; jclass listenerClass = FindClassOrDie(env, listenerClassName); sMethodIdOnSyncedVibrationComplete = GetMethodIDOrDie(env, listenerClass, "onSyncedVibrationComplete", "(J)V"); Loading
services/proguard.flags +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaJackDetector { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaMidiDevice { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.HalVibrator$Callbacks { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorManagerService$VibratorManagerNativeCallbacks { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.HalVibratorManager$Callbacks { *; } -keepclasseswithmembers,allowoptimization,allowaccessmodification class com.android.server.** { *** *FromNative(...); } Loading