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

Commit 580acc26 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Introduce getter for managed IVibrator" into main

parents b9eba49b d293e382
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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);
    }

+5 −0
Original line number Diff line number Diff line
@@ -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. */
@@ -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);

+71 −40
Original line number Diff line number Diff line
@@ -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 =
@@ -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);
@@ -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) {
@@ -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;
        }
@@ -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();
    }

@@ -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;
        }
@@ -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;
        }
@@ -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);
            }
@@ -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) {
@@ -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);
@@ -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;
@@ -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);
@@ -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;
    }
@@ -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);
@@ -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();
@@ -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.
@@ -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.
@@ -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);
@@ -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
@@ -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);
@@ -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;
                }
            }
+56 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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 {
@@ -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. */
@@ -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
@@ -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.
@@ -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)) {
@@ -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
@@ -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
@@ -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;
@@ -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
+29 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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();
@@ -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);
@@ -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