Skip to content

Commit 922afea

Browse files
33bcaSirhc95xboxfanjUP5468-GE-ES44ACanayw2001
authored andcommitted
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! Change-Id: I2c501478d3f02235a8318ac0ee9e2d8b7e94ce2f Co-Authored-By: Chris Crump <chriscrawford893@gmail.com> Co-Authored-By: Jake Weinstein <jake@aospa.co> Co-Authored-By: UP5468-GE-ES44AC <2509942930@qq.com> Co-Authored-By: Anay Wadhera <anay@aospa.co> Signed-off-by: NRanjan-17 <nalinishranjan05@gmail.com>
1 parent 14daa47 commit 922afea

File tree

6 files changed

+238
-4
lines changed

6 files changed

+238
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (C) 2023 Paranoid Android
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package android.os;
18+
19+
import android.content.res.Resources;
20+
import android.os.VibrationEffect;
21+
import android.util.Slog;
22+
23+
import com.android.internal.R;
24+
25+
/** @hide */
26+
public class RichTapVibrationEffect {
27+
28+
private static final String TAG = "RichTapVibrationEffect";
29+
30+
public static boolean isSupported() {
31+
return Resources.getSystem().getBoolean(R.bool.config_usesRichtapVibration);
32+
}
33+
34+
public static int[] getInnerEffect(int id) {
35+
switch (id) {
36+
case VibrationEffect.EFFECT_CLICK:
37+
return new int[]{1, 4097, 0, 100, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
38+
case VibrationEffect.EFFECT_DOUBLE_CLICK:
39+
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};
40+
case VibrationEffect.EFFECT_TICK:
41+
return new int[]{1, 4097, 0, 100, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
42+
case VibrationEffect.EFFECT_THUD:
43+
return new int[]{1, 4097, 0, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
44+
case VibrationEffect.EFFECT_POP:
45+
return new int[]{1, 4097, 0, 100, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
46+
case VibrationEffect.EFFECT_HEAVY_CLICK:
47+
return new int[]{1, 4097, 0, 100, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
48+
case VibrationEffect.EFFECT_TEXTURE_TICK:
49+
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};
50+
default:
51+
Slog.d(TAG, "Exception encountered!", new IllegalStateException("Unexpected effect id: " + id));
52+
return null;
53+
}
54+
}
55+
56+
public static int getInnerEffectStrength(int strength) {
57+
switch (strength) {
58+
case VibrationEffect.EFFECT_STRENGTH_LIGHT:
59+
return 150;
60+
case VibrationEffect.EFFECT_STRENGTH_MEDIUM:
61+
return 200;
62+
case VibrationEffect.EFFECT_STRENGTH_STRONG:
63+
return 250;
64+
default:
65+
Slog.e(TAG, "Wrong Effect Strength!!");
66+
return 0;
67+
}
68+
}
69+
}

core/res/res/values/droidx_config.xml

+3
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,7 @@
163163
<!-- Device model (Build.MODEL) to spoof for netflix, if not empty -->
164164
<string name="config_netflixSpoofModel" translatable="false"></string>
165165

166+
<!-- Whether to use Richtap vibration -->
167+
<bool name="config_usesRichtapVibration">false</bool>
168+
166169
</resources>

core/res/res/values/droidx_symbols.xml

+3
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,7 @@
6161
<java-symbol type="string" name="config_stockFingerprint" />
6262
<java-symbol type="string" name="config_netflixSpoofModel" />
6363

64+
<!-- Whether to use Richtap vibration -->
65+
<java-symbol type="bool" name="config_usesRichtapVibration" />
66+
6467
</resources>

services/core/Android.bp

+1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ java_library_static {
241241
"powerstats_flags_lib",
242242
"locksettings_flags_lib",
243243
"framework-droidx.static",
244+
"vendor.aac.hardware.richtap.vibrator",
244245
],
245246
javac_shard_size: 50,
246247
javacflags: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (C) 2023 Paranoid Android
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.server.vibrator;
18+
19+
import android.hardware.vibrator.IVibrator;
20+
import android.os.Binder;
21+
import android.os.IBinder;
22+
import android.os.ServiceManager;
23+
import android.util.Slog;
24+
25+
import vendor.aac.hardware.richtap.vibrator.IRichtapCallback;
26+
import vendor.aac.hardware.richtap.vibrator.IRichtapVibrator;
27+
28+
public class RichTapVibratorService {
29+
30+
private static final String TAG = "RichTapVibratorService";
31+
private static final String VIBRATOR_DESCRIPTOR = "android.hardware.vibrator.IVibrator/default";
32+
33+
private IRichtapCallback mCallback;
34+
private volatile IRichtapVibrator sRichtapVibratorService = null;
35+
36+
private IRichtapVibrator getRichtapService() {
37+
synchronized (RichTapVibratorService.class) {
38+
if (sRichtapVibratorService == null) {
39+
Slog.d(TAG, "vibratorDescriptor:" + VIBRATOR_DESCRIPTOR);
40+
IVibrator vibratorHalService = IVibrator.Stub.asInterface(ServiceManager.getService(VIBRATOR_DESCRIPTOR));
41+
if (vibratorHalService == null) {
42+
Slog.d(TAG, "can not get hal service");
43+
return null;
44+
}
45+
Slog.d(TAG, "vibratorHalService:" + vibratorHalService);
46+
try {
47+
Slog.d(TAG, "Capabilities:" + vibratorHalService.getCapabilities());
48+
} catch (Exception e) {
49+
Slog.d(TAG, "getCapabilities failed", e);
50+
}
51+
try {
52+
IBinder binder = vibratorHalService.asBinder().getExtension();
53+
if (binder != null) {
54+
sRichtapVibratorService = IRichtapVibrator.Stub.asInterface(Binder.allowBlocking(binder));
55+
binder.linkToDeath(new VibHalDeathRecipient(this), 0);
56+
} else {
57+
sRichtapVibratorService = null;
58+
Slog.e(TAG, "getExtension == null");
59+
}
60+
} catch (Exception e) {
61+
Slog.e(TAG, "getExtension fail", e);
62+
}
63+
}
64+
return sRichtapVibratorService;
65+
}
66+
}
67+
68+
public RichTapVibratorService() { }
69+
70+
public RichTapVibratorService(IRichtapCallback callback) {
71+
mCallback = callback;
72+
}
73+
74+
public void richTapVibratorOn(long millis) {
75+
try {
76+
IRichtapVibrator service = getRichtapService();
77+
if (service != null) {
78+
Slog.d(TAG, "aac richtap doVibratorOn");
79+
service.on((int) millis, mCallback);
80+
}
81+
} catch (Exception e) {
82+
Slog.e(TAG, "aac richtap doVibratorOn fail.", e);
83+
}
84+
}
85+
86+
public void richTapVibratorSetAmplitude(int amplitude) {
87+
try {
88+
IRichtapVibrator service = getRichtapService();
89+
if (service != null) {
90+
Slog.d(TAG, "aac richtap doVibratorSetAmplitude");
91+
service.setAmplitude(amplitude, mCallback);
92+
}
93+
} catch (Exception e) {
94+
Slog.e(TAG, "aac richtap doVibratorSetAmplitude fail.", e);
95+
}
96+
}
97+
98+
public void richTapVibratorOnRawPattern(int[] pattern, int amplitude, int freq) {
99+
try {
100+
IRichtapVibrator service = getRichtapService();
101+
if (service != null) {
102+
Slog.d(TAG, "aac richtap doVibratorOnRawPattern");
103+
service.performHe(1, 0, amplitude, freq, pattern, mCallback);
104+
}
105+
} catch (Exception e) {
106+
Slog.e(TAG, "aac richtap doVibratorOnRawPattern fail.", e);
107+
}
108+
}
109+
110+
void resetHalServiceProxy() {
111+
sRichtapVibratorService = null;
112+
}
113+
114+
public static final class VibHalDeathRecipient implements IBinder.DeathRecipient {
115+
RichTapVibratorService mRichTapService;
116+
117+
VibHalDeathRecipient(RichTapVibratorService richtapService) {
118+
mRichTapService = richtapService;
119+
}
120+
121+
@Override
122+
public void binderDied() {
123+
Slog.d(TAG, "vibrator hal died,should reset hal proxy!!");
124+
synchronized (VibHalDeathRecipient.class) {
125+
if (mRichTapService != null) {
126+
Slog.d(TAG, "vibrator hal reset hal proxy");
127+
mRichTapService.resetHalServiceProxy();
128+
}
129+
}
130+
}
131+
}
132+
}

services/core/java/com/android/server/vibrator/VibratorController.java

+30-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.os.Parcel;
2424
import android.os.RemoteCallbackList;
2525
import android.os.RemoteException;
26+
import android.os.RichTapVibrationEffect;
2627
import android.os.Trace;
2728
import android.os.VibrationEffect;
2829
import android.os.VibratorInfo;
@@ -59,6 +60,8 @@ final class VibratorController {
5960
private volatile boolean mIsUnderExternalControl;
6061
private volatile float mCurrentAmplitude;
6162

63+
private RichTapVibratorService mRichTapService;
64+
6265
/**
6366
* Listener for vibration completion callbacks from native.
6467
*
@@ -86,6 +89,10 @@ public interface OnVibrationCompleteListener {
8689
mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder);
8790
mVibratorInfo = vibratorInfoBuilder.build();
8891

92+
if (RichTapVibrationEffect.isSupported()) {
93+
mRichTapService = new RichTapVibratorService();
94+
}
95+
8996
if (!mVibratorInfoLoadSuccessful) {
9097
Slog.e(TAG,
9198
"Vibrator controller initialization failed to load some HAL info for vibrator "
@@ -257,7 +264,10 @@ public void setAmplitude(float amplitude) {
257264
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#setAmplitude");
258265
try {
259266
synchronized (mLock) {
260-
if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
267+
if (mRichTapService != null) {
268+
int strength = (int) (255.0f * amplitude);
269+
mRichTapService.richTapVibratorSetAmplitude(strength);
270+
} else if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
261271
mNativeWrapper.setAmplitude(amplitude);
262272
}
263273
if (mIsVibrating) {
@@ -282,7 +292,13 @@ public long on(long milliseconds, long vibrationId) {
282292
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on");
283293
try {
284294
synchronized (mLock) {
285-
long duration = mNativeWrapper.on(milliseconds, vibrationId);
295+
long duration = 0;
296+
if (mRichTapService != null) {
297+
duration = milliseconds;
298+
mRichTapService.richTapVibratorOn(duration);
299+
} else {
300+
duration = mNativeWrapper.on(milliseconds, vibrationId);
301+
}
286302
if (duration > 0) {
287303
mCurrentAmplitude = -1;
288304
notifyListenerOnVibrating(true);
@@ -338,8 +354,18 @@ public long on(PrebakedSegment prebaked, long vibrationId) {
338354
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on (Prebaked)");
339355
try {
340356
synchronized (mLock) {
341-
long duration = mNativeWrapper.perform(prebaked.getEffectId(),
342-
prebaked.getEffectStrength(), vibrationId);
357+
long duration = 0;
358+
if (mRichTapService != null) {
359+
int[] pattern = RichTapVibrationEffect.getInnerEffect(prebaked.getEffectId());
360+
int strength = RichTapVibrationEffect.getInnerEffectStrength(prebaked.getEffectStrength());
361+
if (pattern != null) {
362+
duration = 30;
363+
mRichTapService.richTapVibratorOnRawPattern(pattern, strength, 0);
364+
}
365+
} else {
366+
duration = mNativeWrapper.perform(prebaked.getEffectId(),
367+
prebaked.getEffectStrength(), vibrationId);
368+
}
343369
if (duration > 0) {
344370
mCurrentAmplitude = -1;
345371
notifyListenerOnVibrating(true);

0 commit comments

Comments
 (0)