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

Commit 3ba665d3 authored by Lais Andrade's avatar Lais Andrade
Browse files

Integrate new HALVibrator to service

Integrate the new DefaultHalVibrator implementation to the
VibratorManagerService and tests.

Bug: 422944962
Flag: android.os.vibrator.remove_hidl_support
Test: FrameworksVibratorServicesTests
Change-Id: I14a432d1364ac1c08465d3f1d97fe0f4eb5713c8
parent b0c2b375
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -318,7 +318,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {

        HalListener halListener = new HalListener(this);
        mVibratorManager = Flags.removeHidlSupport()
                ? injector.createHalVibratorManager()
                ? injector.createHalVibratorManager(mHandler)
                : injector.createNativeHalVibratorManager();
        mVibratorManager.init(halListener, halListener);

@@ -1786,8 +1786,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            return new VibratorFrameworkStatsLogger(handler);
        }

        HalVibratorManager createHalVibratorManager() {
            return VintfHalVibratorManager.createHalVibratorManager(new NativeHandler());
        HalVibratorManager createHalVibratorManager(Handler handler) {
            return VintfHalVibratorManager.createHalVibratorManager(handler, new NativeHandler());
        }

        HalVibratorManager createNativeHalVibratorManager() {
+58 −0
Original line number Diff line number Diff line
@@ -27,15 +27,18 @@ import android.hardware.vibrator.CompositeEffect;
import android.hardware.vibrator.CompositePwleV2;
import android.hardware.vibrator.FrequencyAccelerationMapEntry;
import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.IVibratorManager;
import android.hardware.vibrator.PrimitivePwle;
import android.hardware.vibrator.PwleV2Primitive;
import android.hardware.vibrator.VendorEffect;
import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IVibratorStateListener;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.os.VibrationEffect;
import android.os.VibratorInfo;
@@ -57,6 +60,61 @@ import java.util.function.Supplier;

/** Implementations for {@link HalVibrator} backed by VINTF objects. */
class VintfHalVibrator {
    private static final String TAG = "VintfHalVibrator";

    /** {@link VintfSupplier} for {@link IVibrator} service managed by {@link IVibratorManager}. */
    static final class ManagedVibratorSupplier extends VintfSupplier<IVibrator> {
        private final int mVibratorId;
        private final VintfSupplier<IVibratorManager> mManagerSupplier;

        ManagedVibratorSupplier(int vibratorId, VintfSupplier<IVibratorManager> managerSupplier) {
            mVibratorId = vibratorId;
            mManagerSupplier = managerSupplier;
        }

        @Nullable
        @Override
        IBinder connectToService() {
            try {
                IVibratorManager manager = mManagerSupplier.get();
                if (manager == null) {
                    Slog.e(TAG, "Error getting manager to load vibrator " + mVibratorId);
                    return null;
                }
                IVibrator vibrator = manager.getVibrator(mVibratorId);
                if (vibrator == null) {
                    Slog.e(TAG, "Null vibrator returned by manager for id " + mVibratorId);
                    return null;
                }
                return vibrator.asBinder();
            } catch (RemoteException e) {
                Slog.e(TAG, "Error getting vibrator " + mVibratorId + " from manager", e);
            }
            return null;
        }

        @NonNull
        @Override
        IVibrator castService(@NonNull IBinder binder) {
            return IVibrator.Stub.asInterface(binder);
        }
    }

    /** {@link VintfSupplier} for default {@link IVibrator} service. */
    static final class DefaultVibratorSupplier extends VintfSupplier<IVibrator> {
        @Nullable
        @Override
        IBinder connectToService() {
            return Binder.allowBlocking(ServiceManager.waitForDeclaredService(
                    IVibrator.DESCRIPTOR + "/default"));
        }

        @NonNull
        @Override
        IVibrator castService(@NonNull IBinder binder) {
            return IVibrator.Stub.asInterface(binder);
        }
    }

    /** Default implementation for devices with {@link IVibrator} available. */
    static final class DefaultHalVibrator implements HalVibrator {
+42 −26
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.IVibratorManager;
import android.os.Binder;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -33,6 +34,9 @@ import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.server.vibrator.VintfHalVibrator.DefaultHalVibrator;
import com.android.server.vibrator.VintfHalVibrator.DefaultVibratorSupplier;
import com.android.server.vibrator.VintfHalVibrator.ManagedVibratorSupplier;
import com.android.server.vibrator.VintfUtils.VintfSupplier;

import java.util.ArrayList;
@@ -44,25 +48,30 @@ import java.util.function.IntFunction;
/** Implementations for {@link HalVibratorManager} backed by VINTF objects. */
class VintfHalVibratorManager {
    private static final String TAG = "VintfHalVibratorManager";
    private static final int DEFAULT_VIBRATOR_ID = 0;
    static final int DEFAULT_VIBRATOR_ID = 0;

    /** Create {@link HalVibratorManager} based on declared services on device. */
    static HalVibratorManager createHalVibratorManager(HalNativeHandler nativeHandler) {
        // TODO(b/422944962): Replace this with Vintf HalVibrator
        IntFunction<HalVibrator> vibratorFactory = VibratorController::new;

    static HalVibratorManager createHalVibratorManager(
            Handler handler, HalNativeHandler nativeHandler) {
        if (ServiceManager.isDeclared(IVibratorManager.DESCRIPTOR + "/default")) {
            Slog.v(TAG, "Loading default IVibratorManager service.");
            return new DefaultHalVibratorManager(new DefaultVibratorManagerSupplier(),
                    nativeHandler, vibratorFactory);
            VintfSupplier<IVibratorManager> managerSupplier = new DefaultVibratorManagerSupplier();
            IntFunction<HalVibrator> vibratorFactory =
                    vibratorId -> new DefaultHalVibrator(vibratorId,
                            new ManagedVibratorSupplier(vibratorId, managerSupplier), handler,
                            nativeHandler);
            return new DefaultHalVibratorManager(managerSupplier, nativeHandler, vibratorFactory);
        }
        if (ServiceManager.isDeclared(IVibrator.DESCRIPTOR + "/default")) {
            Slog.v(TAG, "Loading default IVibrator service.");
            return new LegacyHalVibratorManager(new int[] { DEFAULT_VIBRATOR_ID }, vibratorFactory);
            return new LegacyHalVibratorManager(
                    new DefaultHalVibrator(DEFAULT_VIBRATOR_ID, new DefaultVibratorSupplier(),
                            handler, nativeHandler),
                    nativeHandler);
        }
        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], vibratorFactory);
        return new LegacyHalVibratorManager();
    }

    /** {@link VintfSupplier} for default {@link IVibratorManager} service. */
@@ -382,28 +391,35 @@ 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;
        @Nullable
        private final HalVibrator mDefaultVibrator;
        @Nullable
        private final HalNativeHandler mNativeHandler;

        LegacyHalVibratorManager(@NonNull int[] vibratorIds,
                IntFunction<HalVibrator> vibratorFactory) {
            mVibratorIds = vibratorIds;
            mVibrators = new SparseArray<>(vibratorIds.length);
            for (int id : vibratorIds) {
                mVibrators.put(id, vibratorFactory.apply(id));
        LegacyHalVibratorManager() {
            this(null, null);
        }

        LegacyHalVibratorManager(HalVibrator defaultVibrator, HalNativeHandler nativeHandler) {
            mVibratorIds = defaultVibrator == null ? new int[0] : new int[] { DEFAULT_VIBRATOR_ID };
            mDefaultVibrator = defaultVibrator;
            mNativeHandler = nativeHandler;
        }

        @Override
        public void init(@NonNull Callbacks cb, @NonNull HalVibrator.Callbacks vibratorCb) {
            for (int i = 0; i < mVibrators.size(); i++) {
                mVibrators.valueAt(i).init(vibratorCb);
            if (mNativeHandler != null) {
                mNativeHandler.init(cb, vibratorCb);
            }
            if (mDefaultVibrator != null) {
                mDefaultVibrator.init(vibratorCb);
            }
        }

        @Override
        public void onSystemReady() {
            for (int i = 0; i < mVibrators.size(); i++) {
                mVibrators.valueAt(i).onSystemReady();
            if (mDefaultVibrator != null) {
                mDefaultVibrator.onSystemReady();
            }
        }

@@ -421,7 +437,7 @@ class VintfHalVibratorManager {
        @Nullable
        @Override
        public HalVibrator getVibrator(int id) {
            return mVibrators.get(id);
            return (id == DEFAULT_VIBRATOR_ID) ? mDefaultVibrator : null;
        }

        @Override
@@ -456,11 +472,11 @@ class VintfHalVibratorManager {

            pw.println("vibratorIds = " + Arrays.toString(mVibratorIds));
            pw.println("Vibrators:");
            if (mDefaultVibrator != null) {
                pw.increaseIndent();
            for (int i = 0; i < mVibrators.size(); i++) {
                mVibrators.valueAt(i).dump(pw);
            }
                mDefaultVibrator.dump(pw);
                pw.decreaseIndent();
            }

            pw.decreaseIndent();
            pw.println();
+59 −22
Original line number Diff line number Diff line
@@ -174,6 +174,29 @@ public:
        return mVibratorHalProviders[vibratorId]->getHal();
    }

    void processManagerStatus(ndk::ScopedAStatus& status, const char* logLabel) {
        if (!status.isOk()) {
            ALOGE("%s: %s", logLabel, status.getDescription().c_str());
            if (status.getExceptionCode() == EX_TRANSACTION_FAILED) {
                ALOGE("%s: Resetting vibrator manager provider", logLabel);
                mManagerHalProvider->clear();
            }
        }
    }

    void processVibratorStatus(int32_t vibratorId, ndk::ScopedAStatus& status,
                               const char* logLabel) {
        if (!status.isOk()) {
            ALOGE("%s: %s", logLabel, status.getDescription().c_str());
            if (status.getExceptionCode() == EX_TRANSACTION_FAILED) {
                ALOGE("%s: Resetting vibrator %d provider", logLabel, vibratorId);
                if (mVibratorHalProviders[vibratorId]) {
                    mVibratorHalProviders[vibratorId]->clear();
                }
            }
        }
    }

    // TODO(b/409002423): remove functions below once remove_hidl_support flag removed
    vibrator::ManagerHalController* hal() const { return mHal.get(); }

@@ -255,20 +278,11 @@ vibrator::ManagerHalController* android_server_vibrator_VibratorManagerService_g
    return gManager;
}

static jboolean resultFromStatus(ndk::ScopedAStatus status, const char* logLabel) {
    if (status.isOk()) {
        return JNI_TRUE;
    }
    ALOGE("%s: %s", logLabel, status.getMessage());
    return JNI_FALSE;
}

static jint resultFromStatus(ndk::ScopedAStatus status, int32_t successValue,
jint vibrationResultFromStatus(ndk::ScopedAStatus& status, int32_t successValue,
                               const char* logLabel) {
    if (status.isOk()) {
        return static_cast<jint>(successValue);
    }
    ALOGE("%s: %s", logLabel, status.getMessage());
    if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION ||
        status.getStatus() == STATUS_UNKNOWN_TRANSACTION) {
        // STATUS_UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this
@@ -337,6 +351,19 @@ static jlong nativeNewInit(JNIEnv* env, jclass /* clazz */, jobject managerCallb
    ALOGD("%s", __func__);
    auto service = std::make_unique<NativeVibratorManagerService>(env, managerCallbacks,
                                                                  vibratorCallbacks);
    auto managerHal = loadManagerHal(service.get(), __func__);
    if (managerHal) {
        // Pre-load all vibrator HALs.
        std::vector<int32_t> vibratorIds;
        if (managerHal->getVibratorIds(&vibratorIds).isOk()) {
            for (auto vibratorId : vibratorIds) {
                loadVibratorHal(service.get(), vibratorId, __func__);
            }
        }
    } else {
        // No vibrator manager, pre-load default vibrator with ID = 0.
        loadVibratorHal(service.get(), 0, __func__);
    }
    return reinterpret_cast<jlong>(service.release());
}

@@ -356,7 +383,9 @@ static jboolean nativeTriggerSyncedWithCallback(JNIEnv* env, jclass /* clazz */,
    auto callback = ndk::SharedRefBase::make<VibratorCallback>(sJvm, service->managerCallbacks(),
                                                               sMethodIdOnSyncedVibrationComplete,
                                                               vibrationId);
    return resultFromStatus(hal->triggerSynced(callback), __func__);
    auto status = hal->triggerSynced(callback);
    service->processManagerStatus(status, __func__);
    return status.isOk() ? JNI_TRUE : JNI_FALSE;
}

static jobject nativeStartSessionWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr,
@@ -376,10 +405,7 @@ static jobject nativeStartSessionWithCallback(JNIEnv* env, jclass /* clazz */, j
    std::vector<int32_t> ids(size);
    env->GetIntArrayRegion(vibratorIds, 0, size, reinterpret_cast<jint*>(ids.data()));
    auto status = hal->startSession(ids, config, callback, &session);
    if (!status.isOk()) {
        ALOGE("%s: %s", __func__, status.getMessage());
        return nullptr;
    }
    service->processManagerStatus(status, __func__);
    return AIBinder_toJavaBinder(env, session->asBinder().get());
}

@@ -395,7 +421,9 @@ static jint nativeVibratorOnWithCallback(JNIEnv* env, jclass /* clazz */, jlong
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    int32_t millis = static_cast<int32_t>(durationMs);
    return resultFromStatus(hal->on(millis, callback), millis, __func__);
    auto status = hal->on(millis, callback);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, millis, __func__);
}

static jint nativeVibratorPerformVendorEffectWithCallback(JNIEnv* env, jclass /* clazz */,
@@ -411,7 +439,9 @@ static jint nativeVibratorPerformVendorEffectWithCallback(JNIEnv* env, jclass /*
    auto effect = fromJavaParcel<VendorEffect>(env, vendorEffect);
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    return resultFromStatus(hal->performVendorEffect(effect, callback), INT32_MAX, __func__);
    auto status = hal->performVendorEffect(effect, callback);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, INT32_MAX, __func__);
}

static jint nativeVibratorPerformEffectWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr,
@@ -430,7 +460,8 @@ static jint nativeVibratorPerformEffectWithCallback(JNIEnv* env, jclass /* clazz
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    auto status = hal->perform(effect, strength, callback, &durationMs);
    return resultFromStatus(std::move(status), durationMs, __func__);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, durationMs, __func__);
}

static jint nativeVibratorComposeEffectWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr,
@@ -445,7 +476,9 @@ static jint nativeVibratorComposeEffectWithCallback(JNIEnv* env, jclass /* clazz
    auto effects = vectorFromJavaParcel<CompositeEffect>(env, compositeEffects);
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    return resultFromStatus(hal->compose(effects, callback), INT32_MAX, __func__);
    auto status = hal->compose(effects, callback);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, INT32_MAX, __func__);
}

static jint nativeVibratorComposePwleEffectWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr,
@@ -460,7 +493,9 @@ static jint nativeVibratorComposePwleEffectWithCallback(JNIEnv* env, jclass /* c
    auto effects = vectorFromJavaParcel<PrimitivePwle>(env, pwles);
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    return resultFromStatus(hal->composePwle(effects, callback), INT32_MAX, __func__);
    auto status = hal->composePwle(effects, callback);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, INT32_MAX, __func__);
}

static jint nativeVibratorComposePwleV2EffectWithCallback(JNIEnv* env, jclass /* clazz */,
@@ -476,7 +511,9 @@ static jint nativeVibratorComposePwleV2EffectWithCallback(JNIEnv* env, jclass /*
    auto compositePwleV2 = fromJavaParcel<CompositePwleV2>(env, composite);
    auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(),
                                                                vibratorId, vibrationId, stepId);
    return resultFromStatus(hal->composePwleV2(compositePwleV2, callback), INT32_MAX, __func__);
    auto status = hal->composePwleV2(compositePwleV2, callback);
    service->processVibratorStatus(static_cast<int32_t>(vibratorId), status, __func__);
    return vibrationResultFromStatus(status, INT32_MAX, __func__);
}

// TODO(b/409002423): remove functions below once remove_hidl_support flag removed
+20 −1
Original line number Diff line number Diff line
@@ -103,11 +103,30 @@ public:
        if (status.isOk()) {
            mIsDeathRecipientLinked = true;
        } else {
            ALOGE("%s: Error linking to HAL binder death: %s", __func__, status.getMessage());
            ALOGE("%s: Error linking to HAL binder death: %s", __func__,
                  status.getDescription().c_str());
        }
        return mHal;
    }

    void clear() {
        std::lock_guard<std::mutex> lock(mMutex);
        if (mHal == nullptr) {
            return;
        }
        ALOGW("%s: clearing HAL client", __func__);
        auto binder = mHal->asBinder().get();
        if (binder && mIsDeathRecipientLinked) {
            auto status = ndk::ScopedAStatus::fromStatus(
                    AIBinder_unlinkToDeath(binder, mDeathRecipient.get(), this));
            if (!status.isOk()) {
                ALOGE("%s: Error unlinking to HAL binder death: %s", __func__,
                      status.getDescription().c_str());
            }
        }
        mHal = nullptr;
    }

    static void onBinderDied(void* cookie) {
        HalProvider* provider = reinterpret_cast<HalProvider*>(cookie);
        if (provider) {
Loading