Loading core/java/android/os/VibratorInfo.java +1 −2 Original line number Diff line number Diff line Loading @@ -424,8 +424,7 @@ public class VibratorInfo implements Parcelable { * @return The duration in milliseconds estimated for the primitive, or zero if primitive not * supported. */ public int getPrimitiveDuration( @VibrationEffect.Composition.PrimitiveType int primitiveId) { public int getPrimitiveDuration(int primitiveId) { return mSupportedPrimitives.get(primitiveId); } Loading services/core/java/com/android/server/vibrator/HalVibratorManager.java +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.IndentingPrintWriter; /** Handles interactions with a vibrator manager HAL. */ Loading Loading @@ -48,6 +49,10 @@ interface HalVibratorManager { /** Return the IDs of the vibrators controlled by this manager. */ @NonNull int[] getVibratorIds(); /** Return the vibrator with given ID controlled by this manager. */ @Nullable HalVibrator getVibrator(int id); /** Prepare vibrators for triggering vibrations in sync. */ boolean prepareSynced(@NonNull int[] vibratorIds); Loading services/core/java/com/android/server/vibrator/VibratorManagerService.java +71 −40 Original line number Diff line number Diff line Loading @@ -162,7 +162,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private final AppOpsManager mAppOps; private final HalVibratorManager mVibratorManager; private final VibratorManagerRecords mVibratorManagerRecords; private final SparseArray<HalVibrator> mVibrators; private final VibrationThreadCallbacks mVibrationThreadCallbacks = new VibrationThreadCallbacks(); private final ExternalVibrationCallbacks mExternalVibrationCallbacks = Loading Loading @@ -297,15 +296,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationThread.start(); int[] vibratorIds = mVibratorManager.getVibratorIds(); mVibrators = new SparseArray<>(vibratorIds.length); SparseArray<HalVibrator> availableVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = injector.createHalVibrator(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { availableVibrators.put(vibratorId, vibrator); vibrator.init(halListener); mVibrators.put(vibratorId, vibrator); } } // Load vibrator adapter, that depends on hardware info. mDeviceAdapter = new DeviceAdapter(mVibrationSettings, mVibrators); mDeviceAdapter = new DeviceAdapter(mVibrationSettings, availableVibrators); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); Loading @@ -328,8 +329,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Trace.traceBegin(TRACE_TAG_VIBRATOR, "systemReady"); try { mVibratorManager.onSystemReady(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).onSystemReady(); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.onSystemReady(); } } synchronized (mLock) { Loading Loading @@ -371,7 +375,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call @Nullable public VibratorInfo getVibratorInfo(int vibratorId) { final HalVibrator vibrator = mVibrators.get(vibratorId); final HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null) { return null; } Loading Loading @@ -403,7 +407,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public boolean isVibrating(int vibratorId) { isVibrating_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); return vibrator != null && vibrator.isVibrating(); } Loading @@ -411,7 +415,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public boolean registerVibratorStateListener(int vibratorId, IVibratorStateListener listener) { registerVibratorStateListener_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null || listener == null) { return false; } Loading @@ -423,7 +427,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean unregisterVibratorStateListener(int vibratorId, IVibratorStateListener listener) { unregisterVibratorStateListener_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null || listener == null) { return false; } Loading Loading @@ -767,7 +771,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Create session with adapter that only uses the session vibrators. SparseArray<HalVibrator> sessionVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { sessionVibrators.put(vibratorId, vibrator); } Loading Loading @@ -937,14 +941,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibratorManager.dump(pw); pw.println(); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.println(); pw.println("CurrentVibration:"); pw.increaseIndent(); if (mCurrentSession != null) { Loading Loading @@ -986,8 +982,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mCurrentSession.getDebugInfo().dump(proto, VibratorManagerServiceDumpProto.CURRENT_VIBRATION); } for (int i = 0; i < mVibrators.size(); i++) { proto.write(VibratorManagerServiceDumpProto.VIBRATOR_IDS, mVibrators.keyAt(i)); for (int vibratorId : mVibratorManager.getVibratorIds()) { proto.write(VibratorManagerServiceDumpProto.VIBRATOR_IDS, vibratorId); } } mVibratorManagerRecords.dump(proto); Loading Loading @@ -1031,16 +1027,19 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } private void setExternalControl(boolean externalControl, VibrationStats vibrationStats) { for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).setExternalControl(externalControl); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.setExternalControl(externalControl); vibrationStats.reportSetExternalControl(); } } } @GuardedBy("mLock") private void updateAlwaysOnLocked(AlwaysOnVibration vib) { for (int i = 0; i < vib.effects.size(); i++) { HalVibrator vibrator = mVibrators.get(vib.effects.keyAt(i)); HalVibrator vibrator = mVibratorManager.getVibrator(vib.effects.keyAt(i)); PrebakedSegment effect = vib.effects.valueAt(i); if (vibrator == null) { continue; Loading Loading @@ -1642,7 +1641,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return null; } int vibratorId = effects.keyAt(i); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null && vibrator.getInfo().hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { result.put(vibratorId, prebaked); Loading Loading @@ -1711,16 +1710,23 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @GuardedBy("mLock") private void runOnAllVibratorsLocked(Consumer<HalVibrator> consumer) { for (int i = 0; i < mVibrators.size(); i++) { consumer.accept(mVibrators.valueAt(i)); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { consumer.accept(vibrator); } } } @GuardedBy("mLock") private <T> SparseArray<T> applyToAllVibratorsLocked(Function<HalVibrator, T> fn) { SparseArray<T> ret = new SparseArray<>(mVibrators.size()); for (int i = 0; i < mVibrators.size(); i++) { ret.put(mVibrators.keyAt(i), fn.apply(mVibrators.valueAt(i))); int[] vibratorIds = mVibratorManager.getVibratorIds(); SparseArray<T> ret = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { ret.put(vibratorId, fn.apply(vibrator)); } } return ret; } Loading Loading @@ -1750,10 +1756,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return new NativeHalVibratorManager(new NativeWrapper()); } HalVibrator createHalVibrator(int vibratorId) { return new VibratorController(vibratorId); } HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider( Resources resources, VibratorInfo vibratorInfo) { return new HapticFeedbackVibrationProvider(resources, vibratorInfo); Loading Loading @@ -2061,7 +2063,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Make sure all controllers in session are reset after session ended. // This will update the vibrator state to isVibrating = false for listeners. for (int vibratorId : session.getVibratorIds()) { mVibrators.get(vibratorId).off(); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.off(); } } finishAppOpModeLocked(mCurrentSession.getCallerInfo()); clearCurrentSessionLocked(); Loading Loading @@ -2131,6 +2136,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeHalVibratorManager implements HalVibratorManager { private final NativeWrapper mNativeWrapper; private final SparseArray<HalVibrator> mVibrators = new SparseArray<>(); // Variables that are updated from synchronized blocks but can be read anytime // for a snippet of the current known vibrator manager info. Loading @@ -2153,6 +2159,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds != null) { mVibratorIds = vibratorIds; for (int id : vibratorIds) { mVibrators.put(id, mNativeWrapper.createVibrator(id)); } } // Reset the hardware to a default state. Loading @@ -2178,6 +2187,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return mNativeWrapper.prepareSynced(vibratorIds); Loading Loading @@ -2209,9 +2224,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { 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.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading @@ -2229,6 +2253,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private long mNativeServicePtr = 0; /** Create the {@link HalVibrator} instance for given vibrator ID. */ public HalVibrator createVibrator(int vibratorId) { return new VibratorController(vibratorId); } /** Returns native pointer to newly created controller and connects with HAL service. */ public void init(HalVibratorManager.Callbacks callback) { mNativeServicePtr = nativeInit(callback); Loading Loading @@ -2641,8 +2670,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } private boolean hasExternalControlCapability() { for (int i = 0; i < mVibrators.size(); i++) { if (mVibrators.valueAt(i).getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null && vibrator.getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { return true; } } Loading services/core/java/com/android/server/vibrator/VintfHalVibratorManager.java +56 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.vibrator.IVibrationSession; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorCallback; Loading @@ -30,9 +32,7 @@ import android.os.vibrator.Flags; import android.util.IndentingPrintWriter; import android.util.LongSparseArray; import android.util.Slog; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.server.vibrator.VintfUtils.VintfSupplier; Loading @@ -42,6 +42,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.IntFunction; /** Implementations for {@link HalVibratorManager} backed by VINTF objects. */ class VintfHalVibratorManager { Loading @@ -50,17 +51,21 @@ class VintfHalVibratorManager { /** Create {@link HalVibratorManager} based on declared services on device. */ static HalVibratorManager createHalVibratorManager() { // TODO(b/422944962): Replace this with Vintf HalVibrator IntFunction<HalVibrator> vibratorFactory = VibratorController::new; if (ServiceManager.isDeclared(IVibratorManager.DESCRIPTOR + "/default")) { Slog.v(TAG, "Loading default IVibratorManager service."); return new DefaultHalVibratorManager(new DefaultVibratorManagerSupplier()); return new DefaultHalVibratorManager( new DefaultVibratorManagerSupplier(), vibratorFactory); } if (ServiceManager.isDeclared(IVibrator.DESCRIPTOR + "/default")) { Slog.v(TAG, "Loading default IVibrator service."); return new LegacyHalVibratorManager(new int[] { DEFAULT_VIBRATOR_ID }); return new LegacyHalVibratorManager(new int[] { DEFAULT_VIBRATOR_ID }, vibratorFactory); } Slog.v(TAG, "No default services declared for IVibratorManager or IVibrator." + " Vibrator manager service will proceed without vibrator hardware."); return new LegacyHalVibratorManager(new int[0]); return new LegacyHalVibratorManager(new int[0], vibratorFactory); } /** {@link VintfSupplier} for default {@link IVibratorManager} service. */ Loading @@ -87,14 +92,18 @@ class VintfHalVibratorManager { @GuardedBy("mLock") private final LongSparseArray<IVibrationSession> mOngoingSessions = new LongSparseArray<>(); private final VintfSupplier<IVibratorManager> mHalSupplier; private final IntFunction<HalVibrator> mVibratorFactory; private final SparseArray<HalVibrator> mVibrators = new SparseArray<>(); private Callbacks mCallbacks; private volatile long mCapabilities = 0; private volatile int[] mVibratorIds = new int[0]; DefaultHalVibratorManager(VintfSupplier<IVibratorManager> supplier) { DefaultHalVibratorManager(VintfSupplier<IVibratorManager> supplier, IntFunction<HalVibrator> vibratorFactory) { mHalSupplier = supplier; mVibratorFactory = vibratorFactory; } @Override Loading @@ -112,6 +121,9 @@ class VintfHalVibratorManager { e -> Slog.e(TAG, "Error getting vibrator ids", e)); mCapabilities = capabilities.orElse(0).longValue(); mVibratorIds = vibratorIds.orElseGet(() -> new int[0]); for (int id : mVibratorIds) { mVibrators.put(id, mVibratorFactory.apply(id)); } // Reset the hardware to a default state. // In case this is a runtime restart instead of a fresh boot. Loading @@ -136,6 +148,12 @@ class VintfHalVibratorManager { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { if (!hasCapability(IVibratorManager.CAP_SYNC)) { Loading Loading @@ -229,11 +247,20 @@ class VintfHalVibratorManager { public void dump(IndentingPrintWriter pw) { pw.println("Default Hal VibratorManager:"); pw.increaseIndent(); pw.println("capabilities = " + Arrays.toString(getCapabilitiesNames())); pw.println("capabilitiesFlags = " + Long.toBinaryString(mCapabilities)); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.println("ongoingSessionsCount = " + mOngoingSessions.size()); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading Loading @@ -365,9 +392,15 @@ class VintfHalVibratorManager { /** Legacy implementation for devices without a declared {@link IVibratorManager} service. */ static final class LegacyHalVibratorManager implements HalVibratorManager { private final int[] mVibratorIds; private final SparseArray<HalVibrator> mVibrators; LegacyHalVibratorManager(@NonNull int[] vibratorIds) { LegacyHalVibratorManager(@NonNull int[] vibratorIds, IntFunction<HalVibrator> vibratorFactory) { mVibratorIds = vibratorIds; mVibrators = new SparseArray<>(vibratorIds.length); for (int id : vibratorIds) { mVibrators.put(id, vibratorFactory.apply(id)); } } @Override Loading @@ -389,6 +422,12 @@ class VintfHalVibratorManager { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return false; Loading Loading @@ -418,8 +457,17 @@ class VintfHalVibratorManager { public void dump(IndentingPrintWriter pw) { pw.println("Legacy HAL VibratorManager:"); pw.increaseIndent(); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading services/tests/vibrator/src/com/android/server/vibrator/HalVibratorManagerTestCase.java +29 −3 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ public abstract class HalVibratorManagerTestCase { @Test @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS) public void init_initializesHalAndClearSyncedAndSessions() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_START_SESSIONS); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_START_SESSIONS); mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newVibratorManager(); manager.init(mHalCallbackMock); Loading @@ -87,7 +87,7 @@ public abstract class HalVibratorManagerTestCase { @Test public void hasCapability_checksAllFlagBits() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_START_SESSIONS); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_START_SESSIONS); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.hasCapability(IVibratorManager.CAP_SYNC)).isTrue(); Loading @@ -98,6 +98,32 @@ public abstract class HalVibratorManagerTestCase { assertThat(manager.hasCapability(IVibratorManager.CAP_TRIGGER_CALLBACK)).isFalse(); } @Test public void getVibrator_validVibratorId_returnsValidVibrators() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.getVibrator(1)).isNotNull(); assertThat(manager.getVibrator(1).getInfo().getId()).isEqualTo(1); assertThat(manager.getVibrator(2)).isNotNull(); assertThat(manager.getVibrator(2).getInfo().getId()).isEqualTo(2); } @Test public void getVibrator_beforeInit_returnsNull() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newVibratorManager(); assertThat(manager.getVibrator(1)).isNull(); assertThat(manager.getVibrator(2)).isNull(); } @Test public void getVibrator_badVibratorId_returnsNull() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.getVibrator(3)).isNull(); assertThat(manager.getVibrator(-1)).isNull(); } @Test public void prepareSynced_withCapabilityAndValidVibrators_returnsTrue() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC); Loading Loading @@ -170,7 +196,7 @@ public abstract class HalVibratorManagerTestCase { @Test public void triggerSynced_triggerCallback_returnsVibrationId() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_TRIGGER_CALLBACK); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_TRIGGER_CALLBACK); mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); Loading Loading
core/java/android/os/VibratorInfo.java +1 −2 Original line number Diff line number Diff line Loading @@ -424,8 +424,7 @@ public class VibratorInfo implements Parcelable { * @return The duration in milliseconds estimated for the primitive, or zero if primitive not * supported. */ public int getPrimitiveDuration( @VibrationEffect.Composition.PrimitiveType int primitiveId) { public int getPrimitiveDuration(int primitiveId) { return mSupportedPrimitives.get(primitiveId); } Loading
services/core/java/com/android/server/vibrator/HalVibratorManager.java +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.IndentingPrintWriter; /** Handles interactions with a vibrator manager HAL. */ Loading Loading @@ -48,6 +49,10 @@ interface HalVibratorManager { /** Return the IDs of the vibrators controlled by this manager. */ @NonNull int[] getVibratorIds(); /** Return the vibrator with given ID controlled by this manager. */ @Nullable HalVibrator getVibrator(int id); /** Prepare vibrators for triggering vibrations in sync. */ boolean prepareSynced(@NonNull int[] vibratorIds); Loading
services/core/java/com/android/server/vibrator/VibratorManagerService.java +71 −40 Original line number Diff line number Diff line Loading @@ -162,7 +162,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private final AppOpsManager mAppOps; private final HalVibratorManager mVibratorManager; private final VibratorManagerRecords mVibratorManagerRecords; private final SparseArray<HalVibrator> mVibrators; private final VibrationThreadCallbacks mVibrationThreadCallbacks = new VibrationThreadCallbacks(); private final ExternalVibrationCallbacks mExternalVibrationCallbacks = Loading Loading @@ -297,15 +296,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationThread.start(); int[] vibratorIds = mVibratorManager.getVibratorIds(); mVibrators = new SparseArray<>(vibratorIds.length); SparseArray<HalVibrator> availableVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = injector.createHalVibrator(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { availableVibrators.put(vibratorId, vibrator); vibrator.init(halListener); mVibrators.put(vibratorId, vibrator); } } // Load vibrator adapter, that depends on hardware info. mDeviceAdapter = new DeviceAdapter(mVibrationSettings, mVibrators); mDeviceAdapter = new DeviceAdapter(mVibrationSettings, availableVibrators); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); Loading @@ -328,8 +329,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Trace.traceBegin(TRACE_TAG_VIBRATOR, "systemReady"); try { mVibratorManager.onSystemReady(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).onSystemReady(); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.onSystemReady(); } } synchronized (mLock) { Loading Loading @@ -371,7 +375,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call @Nullable public VibratorInfo getVibratorInfo(int vibratorId) { final HalVibrator vibrator = mVibrators.get(vibratorId); final HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null) { return null; } Loading Loading @@ -403,7 +407,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public boolean isVibrating(int vibratorId) { isVibrating_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); return vibrator != null && vibrator.isVibrating(); } Loading @@ -411,7 +415,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public boolean registerVibratorStateListener(int vibratorId, IVibratorStateListener listener) { registerVibratorStateListener_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null || listener == null) { return false; } Loading @@ -423,7 +427,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public boolean unregisterVibratorStateListener(int vibratorId, IVibratorStateListener listener) { unregisterVibratorStateListener_enforcePermission(); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator == null || listener == null) { return false; } Loading Loading @@ -767,7 +771,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Create session with adapter that only uses the session vibrators. SparseArray<HalVibrator> sessionVibrators = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { sessionVibrators.put(vibratorId, vibrator); } Loading Loading @@ -937,14 +941,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibratorManager.dump(pw); pw.println(); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.println(); pw.println("CurrentVibration:"); pw.increaseIndent(); if (mCurrentSession != null) { Loading Loading @@ -986,8 +982,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mCurrentSession.getDebugInfo().dump(proto, VibratorManagerServiceDumpProto.CURRENT_VIBRATION); } for (int i = 0; i < mVibrators.size(); i++) { proto.write(VibratorManagerServiceDumpProto.VIBRATOR_IDS, mVibrators.keyAt(i)); for (int vibratorId : mVibratorManager.getVibratorIds()) { proto.write(VibratorManagerServiceDumpProto.VIBRATOR_IDS, vibratorId); } } mVibratorManagerRecords.dump(proto); Loading Loading @@ -1031,16 +1027,19 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } private void setExternalControl(boolean externalControl, VibrationStats vibrationStats) { for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).setExternalControl(externalControl); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.setExternalControl(externalControl); vibrationStats.reportSetExternalControl(); } } } @GuardedBy("mLock") private void updateAlwaysOnLocked(AlwaysOnVibration vib) { for (int i = 0; i < vib.effects.size(); i++) { HalVibrator vibrator = mVibrators.get(vib.effects.keyAt(i)); HalVibrator vibrator = mVibratorManager.getVibrator(vib.effects.keyAt(i)); PrebakedSegment effect = vib.effects.valueAt(i); if (vibrator == null) { continue; Loading Loading @@ -1642,7 +1641,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return null; } int vibratorId = effects.keyAt(i); HalVibrator vibrator = mVibrators.get(vibratorId); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null && vibrator.getInfo().hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { result.put(vibratorId, prebaked); Loading Loading @@ -1711,16 +1710,23 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @GuardedBy("mLock") private void runOnAllVibratorsLocked(Consumer<HalVibrator> consumer) { for (int i = 0; i < mVibrators.size(); i++) { consumer.accept(mVibrators.valueAt(i)); for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { consumer.accept(vibrator); } } } @GuardedBy("mLock") private <T> SparseArray<T> applyToAllVibratorsLocked(Function<HalVibrator, T> fn) { SparseArray<T> ret = new SparseArray<>(mVibrators.size()); for (int i = 0; i < mVibrators.size(); i++) { ret.put(mVibrators.keyAt(i), fn.apply(mVibrators.valueAt(i))); int[] vibratorIds = mVibratorManager.getVibratorIds(); SparseArray<T> ret = new SparseArray<>(vibratorIds.length); for (int vibratorId : vibratorIds) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { ret.put(vibratorId, fn.apply(vibrator)); } } return ret; } Loading Loading @@ -1750,10 +1756,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return new NativeHalVibratorManager(new NativeWrapper()); } HalVibrator createHalVibrator(int vibratorId) { return new VibratorController(vibratorId); } HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider( Resources resources, VibratorInfo vibratorInfo) { return new HapticFeedbackVibrationProvider(resources, vibratorInfo); Loading Loading @@ -2061,7 +2063,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Make sure all controllers in session are reset after session ended. // This will update the vibrator state to isVibrating = false for listeners. for (int vibratorId : session.getVibratorIds()) { mVibrators.get(vibratorId).off(); HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null) { vibrator.off(); } } finishAppOpModeLocked(mCurrentSession.getCallerInfo()); clearCurrentSessionLocked(); Loading Loading @@ -2131,6 +2136,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // TODO(b/409002423): remove this class once remove_hidl_support flag removed public static class NativeHalVibratorManager implements HalVibratorManager { private final NativeWrapper mNativeWrapper; private final SparseArray<HalVibrator> mVibrators = new SparseArray<>(); // Variables that are updated from synchronized blocks but can be read anytime // for a snippet of the current known vibrator manager info. Loading @@ -2153,6 +2159,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { int[] vibratorIds = mNativeWrapper.getVibratorIds(); if (vibratorIds != null) { mVibratorIds = vibratorIds; for (int id : vibratorIds) { mVibrators.put(id, mNativeWrapper.createVibrator(id)); } } // Reset the hardware to a default state. Loading @@ -2178,6 +2187,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return mNativeWrapper.prepareSynced(vibratorIds); Loading Loading @@ -2209,9 +2224,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { 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.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading @@ -2229,6 +2253,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private long mNativeServicePtr = 0; /** Create the {@link HalVibrator} instance for given vibrator ID. */ public HalVibrator createVibrator(int vibratorId) { return new VibratorController(vibratorId); } /** Returns native pointer to newly created controller and connects with HAL service. */ public void init(HalVibratorManager.Callbacks callback) { mNativeServicePtr = nativeInit(callback); Loading Loading @@ -2641,8 +2670,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } private boolean hasExternalControlCapability() { for (int i = 0; i < mVibrators.size(); i++) { if (mVibrators.valueAt(i).getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { for (int vibratorId : mVibratorManager.getVibratorIds()) { HalVibrator vibrator = mVibratorManager.getVibrator(vibratorId); if (vibrator != null && vibrator.getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { return true; } } Loading
services/core/java/com/android/server/vibrator/VintfHalVibratorManager.java +56 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.vibrator.IVibrationSession; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorCallback; Loading @@ -30,9 +32,7 @@ import android.os.vibrator.Flags; import android.util.IndentingPrintWriter; import android.util.LongSparseArray; import android.util.Slog; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.server.vibrator.VintfUtils.VintfSupplier; Loading @@ -42,6 +42,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.IntFunction; /** Implementations for {@link HalVibratorManager} backed by VINTF objects. */ class VintfHalVibratorManager { Loading @@ -50,17 +51,21 @@ class VintfHalVibratorManager { /** Create {@link HalVibratorManager} based on declared services on device. */ static HalVibratorManager createHalVibratorManager() { // TODO(b/422944962): Replace this with Vintf HalVibrator IntFunction<HalVibrator> vibratorFactory = VibratorController::new; if (ServiceManager.isDeclared(IVibratorManager.DESCRIPTOR + "/default")) { Slog.v(TAG, "Loading default IVibratorManager service."); return new DefaultHalVibratorManager(new DefaultVibratorManagerSupplier()); return new DefaultHalVibratorManager( new DefaultVibratorManagerSupplier(), vibratorFactory); } if (ServiceManager.isDeclared(IVibrator.DESCRIPTOR + "/default")) { Slog.v(TAG, "Loading default IVibrator service."); return new LegacyHalVibratorManager(new int[] { DEFAULT_VIBRATOR_ID }); return new LegacyHalVibratorManager(new int[] { DEFAULT_VIBRATOR_ID }, vibratorFactory); } Slog.v(TAG, "No default services declared for IVibratorManager or IVibrator." + " Vibrator manager service will proceed without vibrator hardware."); return new LegacyHalVibratorManager(new int[0]); return new LegacyHalVibratorManager(new int[0], vibratorFactory); } /** {@link VintfSupplier} for default {@link IVibratorManager} service. */ Loading @@ -87,14 +92,18 @@ class VintfHalVibratorManager { @GuardedBy("mLock") private final LongSparseArray<IVibrationSession> mOngoingSessions = new LongSparseArray<>(); private final VintfSupplier<IVibratorManager> mHalSupplier; private final IntFunction<HalVibrator> mVibratorFactory; private final SparseArray<HalVibrator> mVibrators = new SparseArray<>(); private Callbacks mCallbacks; private volatile long mCapabilities = 0; private volatile int[] mVibratorIds = new int[0]; DefaultHalVibratorManager(VintfSupplier<IVibratorManager> supplier) { DefaultHalVibratorManager(VintfSupplier<IVibratorManager> supplier, IntFunction<HalVibrator> vibratorFactory) { mHalSupplier = supplier; mVibratorFactory = vibratorFactory; } @Override Loading @@ -112,6 +121,9 @@ class VintfHalVibratorManager { e -> Slog.e(TAG, "Error getting vibrator ids", e)); mCapabilities = capabilities.orElse(0).longValue(); mVibratorIds = vibratorIds.orElseGet(() -> new int[0]); for (int id : mVibratorIds) { mVibrators.put(id, mVibratorFactory.apply(id)); } // Reset the hardware to a default state. // In case this is a runtime restart instead of a fresh boot. Loading @@ -136,6 +148,12 @@ class VintfHalVibratorManager { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { if (!hasCapability(IVibratorManager.CAP_SYNC)) { Loading Loading @@ -229,11 +247,20 @@ class VintfHalVibratorManager { public void dump(IndentingPrintWriter pw) { pw.println("Default Hal VibratorManager:"); pw.increaseIndent(); pw.println("capabilities = " + Arrays.toString(getCapabilitiesNames())); pw.println("capabilitiesFlags = " + Long.toBinaryString(mCapabilities)); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.println("ongoingSessionsCount = " + mOngoingSessions.size()); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading Loading @@ -365,9 +392,15 @@ class VintfHalVibratorManager { /** Legacy implementation for devices without a declared {@link IVibratorManager} service. */ static final class LegacyHalVibratorManager implements HalVibratorManager { private final int[] mVibratorIds; private final SparseArray<HalVibrator> mVibrators; LegacyHalVibratorManager(@NonNull int[] vibratorIds) { LegacyHalVibratorManager(@NonNull int[] vibratorIds, IntFunction<HalVibrator> vibratorFactory) { mVibratorIds = vibratorIds; mVibrators = new SparseArray<>(vibratorIds.length); for (int id : vibratorIds) { mVibrators.put(id, vibratorFactory.apply(id)); } } @Override Loading @@ -389,6 +422,12 @@ class VintfHalVibratorManager { return mVibratorIds; } @Nullable @Override public HalVibrator getVibrator(int id) { return mVibrators.get(id); } @Override public boolean prepareSynced(@NonNull int[] vibratorIds) { return false; Loading Loading @@ -418,8 +457,17 @@ class VintfHalVibratorManager { public void dump(IndentingPrintWriter pw) { pw.println("Legacy HAL VibratorManager:"); pw.increaseIndent(); pw.println("vibratorIds = " + Arrays.toString(mVibratorIds)); pw.println("Vibrators:"); pw.increaseIndent(); for (int i = 0; i < mVibrators.size(); i++) { mVibrators.valueAt(i).dump(pw); } pw.decreaseIndent(); pw.decreaseIndent(); pw.println(); } @Override Loading
services/tests/vibrator/src/com/android/server/vibrator/HalVibratorManagerTestCase.java +29 −3 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ public abstract class HalVibratorManagerTestCase { @Test @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS) public void init_initializesHalAndClearSyncedAndSessions() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_START_SESSIONS); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_START_SESSIONS); mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newVibratorManager(); manager.init(mHalCallbackMock); Loading @@ -87,7 +87,7 @@ public abstract class HalVibratorManagerTestCase { @Test public void hasCapability_checksAllFlagBits() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_START_SESSIONS); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_START_SESSIONS); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.hasCapability(IVibratorManager.CAP_SYNC)).isTrue(); Loading @@ -98,6 +98,32 @@ public abstract class HalVibratorManagerTestCase { assertThat(manager.hasCapability(IVibratorManager.CAP_TRIGGER_CALLBACK)).isFalse(); } @Test public void getVibrator_validVibratorId_returnsValidVibrators() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.getVibrator(1)).isNotNull(); assertThat(manager.getVibrator(1).getInfo().getId()).isEqualTo(1); assertThat(manager.getVibrator(2)).isNotNull(); assertThat(manager.getVibrator(2).getInfo().getId()).isEqualTo(2); } @Test public void getVibrator_beforeInit_returnsNull() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newVibratorManager(); assertThat(manager.getVibrator(1)).isNull(); assertThat(manager.getVibrator(2)).isNull(); } @Test public void getVibrator_badVibratorId_returnsNull() { mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); assertThat(manager.getVibrator(3)).isNull(); assertThat(manager.getVibrator(-1)).isNull(); } @Test public void prepareSynced_withCapabilityAndValidVibrators_returnsTrue() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC); Loading Loading @@ -170,7 +196,7 @@ public abstract class HalVibratorManagerTestCase { @Test public void triggerSynced_triggerCallback_returnsVibrationId() { mHelper.setCapabilities(IVibratorManager.CAP_SYNC | IVibratorManager.CAP_TRIGGER_CALLBACK); mHelper.setCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_TRIGGER_CALLBACK); mHelper.setVibratorIds(new int[] {1, 2}); HalVibratorManager manager = newInitializedVibratorManager(); Loading