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

Commit 68419b1a authored by Fabian Leutenegger's avatar Fabian Leutenegger Committed by Sahil Sonar
Browse files

base: Add minimal support for Richtap vibrations



This implementation of Richtap is highly inspired by Nothings but stripped down to its essentials to match our needs.

If your device supports Richtap vibrations set "config_usesRichtapVibration" to true and enjoy!

Co-Authored-By: default avatarChris Crump <chriscrawford893@gmail.com>
Co-Authored-By: default avatarJake Weinstein <jake@aospa.co>
Co-Authored-By: default avatarUP5468-GE-ES44AC <2509942930@qq.com>
Co-Authored-By: default avatarAnay Wadhera <anay@aospa.co>

Change-Id: I4f8b5deb7b303a3adf388335aa1ee8b1e048af24
parent 25548043
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 Paranoid Android
 *
 * 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 android.os;

import android.content.res.Resources;
import android.os.VibrationEffect;
import android.util.Slog;

import com.android.internal.R;

/** @hide */
public class RichTapVibrationEffect {

    private static final String TAG = "RichTapVibrationEffect";

    public static boolean isSupported() {
        return Resources.getSystem().getBoolean(R.bool.config_usesRichtapVibration);
    }

    public static int[] getInnerEffect(int id) {
        switch (id) {
            case VibrationEffect.EFFECT_CLICK:
                return new int[]{1, 4097, 0, 100, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_DOUBLE_CLICK:
                return new int[]{1, 4097, 0, 100, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4097, 70, 100, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_TICK:
                return new int[]{1, 4097, 0, 100, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_THUD:
                return new int[]{1, 4097, 0, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_POP:
                return new int[]{1, 4097, 0, 100, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_HEAVY_CLICK:
                return new int[]{1, 4097, 0, 100, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            case VibrationEffect.EFFECT_TEXTURE_TICK:
                return new int[]{1, 4097, 0, 50, 33, 29, 0, 0, 0, 12, 59, 0, 22, 75, -21, 29, 0, 0, 4097, 30, 100, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            default:
                Slog.d(TAG, "Exception encountered!", new IllegalStateException("Unexpected effect id: " + id));
                return null;
        }
    }

    public static int getInnerEffectStrength(int strength) {
        switch (strength) {
            case VibrationEffect.EFFECT_STRENGTH_LIGHT:
                return 150;
            case VibrationEffect.EFFECT_STRENGTH_MEDIUM:
                return 200;
            case VibrationEffect.EFFECT_STRENGTH_STRONG:
                return 250;
            default:
                Slog.e(TAG, "Wrong Effect Strength!!");
                return 0;
        }
    }
}
+4 −0
Original line number Diff line number Diff line
<resources>
    <!-- Whether to use Richtap vibration -->
    <bool name="config_usesRichtapVibration">false</bool>
</resources>
+4 −0
Original line number Diff line number Diff line
<resources>
    <!-- Whether to use Richtap vibration -->
    <java-symbol type="bool" name="config_usesRichtapVibration" />
</resources>
+1 −0
Original line number Diff line number Diff line
@@ -256,6 +256,7 @@ java_library_static {
        "net_flags_lib",
        "stats_flags_lib",
        "core_os_flags_lib",
        "vendor.aac.hardware.richtap.vibrator",
    ],
    javac_shard_size: 50,
    javacflags: [
+132 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 Paranoid Android
 *
 * 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.hardware.vibrator.IVibrator;
import android.os.Binder;
import android.os.IBinder;
import android.os.ServiceManager;
import android.util.Slog;

import vendor.aac.hardware.richtap.vibrator.IRichtapCallback;
import vendor.aac.hardware.richtap.vibrator.IRichtapVibrator;

public class RichTapVibratorService {

    private static final String TAG = "RichTapVibratorService";
    private static final String VIBRATOR_DESCRIPTOR = IVibrator.DESCRIPTOR + "/default";

    private IRichtapCallback mCallback;
    private volatile IRichtapVibrator sRichtapVibratorService = null;

    private IRichtapVibrator getRichtapService() {
        synchronized (RichTapVibratorService.class) {
            if (sRichtapVibratorService == null) {
                Slog.d(TAG, "vibratorDescriptor:" + VIBRATOR_DESCRIPTOR);
                IVibrator vibratorHalService = IVibrator.Stub.asInterface(ServiceManager.getService(VIBRATOR_DESCRIPTOR));
                if (vibratorHalService == null) {
                    Slog.d(TAG, "can not get hal service");
                    return null;
                }
                Slog.d(TAG, "vibratorHalService:" + vibratorHalService);
                try {
                    Slog.d(TAG, "Capabilities:" + vibratorHalService.getCapabilities());
                } catch (Exception e) {
                    Slog.d(TAG, "getCapabilities failed", e);
                }
                try {
                    IBinder binder = vibratorHalService.asBinder().getExtension();
                    if (binder != null) {
                        sRichtapVibratorService = IRichtapVibrator.Stub.asInterface(Binder.allowBlocking(binder));
                        binder.linkToDeath(new VibHalDeathRecipient(this), 0);
                    } else {
                        sRichtapVibratorService = null;
                        Slog.e(TAG, "getExtension == null");
                    }
                } catch (Exception e) {
                    Slog.e(TAG, "getExtension fail", e);
                }
            }
            return sRichtapVibratorService;
        }
    }

    public RichTapVibratorService() { }

    public RichTapVibratorService(IRichtapCallback callback) {
        mCallback = callback;
    }

    public void richTapVibratorOn(long millis) {
        try {
            IRichtapVibrator service = getRichtapService();
            if (service != null) {
                Slog.d(TAG, "aac richtap doVibratorOn");
                service.on((int) millis, mCallback);
            }
        } catch (Exception e) {
            Slog.e(TAG, "aac richtap doVibratorOn fail.", e);
        }
    }

    public void richTapVibratorSetAmplitude(int amplitude) {
        try {
            IRichtapVibrator service = getRichtapService();
            if (service != null) {
                Slog.d(TAG, "aac richtap doVibratorSetAmplitude");
                service.setAmplitude(amplitude, mCallback);
            }
        } catch (Exception e) {
            Slog.e(TAG, "aac richtap doVibratorSetAmplitude fail.", e);
        }
    }

    public void richTapVibratorOnRawPattern(int[] pattern, int amplitude, int freq) {
        try {
            IRichtapVibrator service = getRichtapService();
            if (service != null) {
                Slog.d(TAG, "aac richtap doVibratorOnRawPattern");
                service.performHe(1, 0, amplitude, freq, pattern, mCallback);
            }
        } catch (Exception e) {
            Slog.e(TAG, "aac richtap doVibratorOnRawPattern fail.", e);
        }
    }

    void resetHalServiceProxy() {
        sRichtapVibratorService = null;
    }

    public static final class VibHalDeathRecipient implements IBinder.DeathRecipient {
        RichTapVibratorService mRichTapService;

        VibHalDeathRecipient(RichTapVibratorService richtapService) {
            mRichTapService = richtapService;
        }

        @Override
        public void binderDied() {
            Slog.d(TAG, "vibrator hal died,should reset hal proxy!!");
            synchronized (VibHalDeathRecipient.class) {
                if (mRichTapService != null) {
                    Slog.d(TAG, "vibrator hal reset hal proxy");
                    mRichTapService.resetHalServiceProxy();
                }
            }
        }
    }
}
Loading