Merge "Add dump entry for ManagerRecord#mTargetPackageName" into main
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7c5885a..7e325a5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -2187,6 +2187,7 @@
}
if (multiuser_get_app_id(uid) == AID_NETWORK_STACK) {
+ capabilities |= (1LL << CAP_WAKE_ALARM);
capabilities |= (1LL << CAP_NET_ADMIN);
capabilities |= (1LL << CAP_NET_BROADCAST);
capabilities |= (1LL << CAP_NET_BIND_SERVICE);
diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java
index 59b55bf7..0a7872f 100644
--- a/services/core/java/com/android/server/vibrator/VibrationScaler.java
+++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java
@@ -17,11 +17,13 @@
package com.android.server.vibrator;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.hardware.vibrator.V1_0.EffectStrength;
import android.os.IExternalVibratorService;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.os.vibrator.Flags;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.VibrationEffectSegment;
import android.util.Slog;
@@ -56,6 +58,8 @@
private final VibrationSettings mSettingsController;
private final int mDefaultVibrationAmplitude;
+ private SparseArray<Float> mAdaptiveHapticsScales;
+
VibrationScaler(Context context, VibrationSettings settingsController) {
mSettingsController = settingsController;
mDefaultVibrationAmplitude = context.getResources().getInteger(
@@ -140,6 +144,15 @@
if (scaleLevel != null) {
segment = segment.scale(scaleLevel.factor);
}
+
+ // If adaptive haptics scaling is available for this usage, apply it to the segment.
+ if (Flags.adaptiveHapticsEnabled()
+ && mAdaptiveHapticsScales != null && mAdaptiveHapticsScales.size() > 0
+ && mAdaptiveHapticsScales.contains(usageHint)) {
+ float adaptiveScale = mAdaptiveHapticsScales.get(usageHint);
+ segment = segment.scale(adaptiveScale);
+ }
+
segments.set(i, segment);
}
if (segments.equals(composedEffect.getSegments())) {
@@ -173,6 +186,16 @@
return prebaked.applyEffectStrength(newEffectStrength);
}
+ /**
+ * Updates the adaptive haptics scales.
+ * @param scales the new vibration scales to apply.
+ *
+ * @hide
+ */
+ public void updateAdaptiveHapticsScales(@Nullable SparseArray<Float> scales) {
+ mAdaptiveHapticsScales = scales;
+ }
+
/** Mapping of Vibrator.VIBRATION_INTENSITY_* values to {@link EffectStrength}. */
private static int intensityToEffectStrength(int intensity) {
switch (intensity) {
diff --git a/services/core/java/com/android/server/vibrator/VibratorControlService.java b/services/core/java/com/android/server/vibrator/VibratorControlService.java
index 2eeb903..9d75249 100644
--- a/services/core/java/com/android/server/vibrator/VibratorControlService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorControlService.java
@@ -16,14 +16,26 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_MEDIA;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.VibrationAttributes.USAGE_UNKNOWN;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.frameworks.vibrator.IVibratorControlService;
import android.frameworks.vibrator.IVibratorController;
+import android.frameworks.vibrator.ScaleParam;
import android.frameworks.vibrator.VibrationParam;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseArray;
import java.util.Objects;
@@ -37,10 +49,13 @@
private static final String TAG = "VibratorControlService";
private final VibratorControllerHolder mVibratorControllerHolder;
+ private final VibrationScaler mVibrationScaler;
private final Object mLock;
- public VibratorControlService(VibratorControllerHolder vibratorControllerHolder, Object lock) {
+ public VibratorControlService(VibratorControllerHolder vibratorControllerHolder,
+ VibrationScaler vibrationScaler, Object lock) {
mVibratorControllerHolder = vibratorControllerHolder;
+ mVibrationScaler = vibrationScaler;
mLock = lock;
}
@@ -70,25 +85,62 @@
+ "controller doesn't match the registered one. " + this);
return;
}
+ updateAdaptiveHapticsScales(/* params= */ null);
mVibratorControllerHolder.setVibratorController(null);
}
}
@Override
- public void setVibrationParams(
- @SuppressLint("ArrayReturn") VibrationParam[] params, IVibratorController token)
- throws RemoteException {
- // TODO(b/305939964): Add set vibration implementation.
+ public void setVibrationParams(@SuppressLint("ArrayReturn") VibrationParam[] params,
+ @NonNull IVibratorController token) throws RemoteException {
+ Objects.requireNonNull(token);
+
+ synchronized (mLock) {
+ if (mVibratorControllerHolder.getVibratorController() == null) {
+ Slog.w(TAG, "Received request to set VibrationParams for IVibratorController = "
+ + token + ", but no controller was previously registered. Request "
+ + "Ignored.");
+ return;
+ }
+ if (!Objects.equals(mVibratorControllerHolder.getVibratorController().asBinder(),
+ token.asBinder())) {
+ Slog.wtf(TAG, "Failed to set new VibrationParams. The provided "
+ + "controller doesn't match the registered one. " + this);
+ return;
+ }
+
+ updateAdaptiveHapticsScales(params);
+ }
}
@Override
- public void clearVibrationParams(int types, IVibratorController token) throws RemoteException {
- // TODO(b/305939964): Add clear vibration implementation.
+ public void clearVibrationParams(int types, @NonNull IVibratorController token)
+ throws RemoteException {
+ Objects.requireNonNull(token);
+
+ synchronized (mLock) {
+ if (mVibratorControllerHolder.getVibratorController() == null) {
+ Slog.w(TAG, "Received request to clear VibrationParams for IVibratorController = "
+ + token + ", but no controller was previously registered. Request "
+ + "Ignored.");
+ return;
+ }
+ if (!Objects.equals(mVibratorControllerHolder.getVibratorController().asBinder(),
+ token.asBinder())) {
+ Slog.wtf(TAG, "Failed to clear VibrationParams. The provided "
+ + "controller doesn't match the registered one. " + this);
+ return;
+ }
+ //TODO(305942827): Update this method to only clear the specified vibration types.
+ // Perhaps look into whether it makes more sense to have this clear all scales and
+ // rely on setVibrationParams for clearing the scales for specific vibrations.
+ updateAdaptiveHapticsScales(/* params= */ null);
+ }
}
@Override
public void onRequestVibrationParamsComplete(
- IBinder requestToken, @SuppressLint("ArrayReturn") VibrationParam[] result)
+ @NonNull IBinder requestToken, @SuppressLint("ArrayReturn") VibrationParam[] result)
throws RemoteException {
// TODO(305942827): Cache the vibration params in VibrationScaler
}
@@ -102,4 +154,52 @@
public String getInterfaceHash() throws RemoteException {
return this.HASH;
}
+
+ /**
+ * Extracts the vibration scales and caches them in {@link VibrationScaler}.
+ *
+ * @param params the new vibration params to cache.
+ */
+ private void updateAdaptiveHapticsScales(@Nullable VibrationParam[] params) {
+ if (params == null || params.length == 0) {
+ mVibrationScaler.updateAdaptiveHapticsScales(null);
+ return;
+ }
+
+ SparseArray<Float> vibrationScales = new SparseArray<>();
+ for (int i = 0; i < params.length; i++) {
+ ScaleParam scaleParam = params[i].getScale();
+ extractVibrationScales(scaleParam, vibrationScales);
+ }
+ mVibrationScaler.updateAdaptiveHapticsScales(vibrationScales);
+ }
+
+ /**
+ * Extracts the vibration scales and map them to their corresponding
+ * {@link android.os.VibrationAttributes} usages.
+ */
+ private void extractVibrationScales(ScaleParam scaleParam, SparseArray<Float> vibrationScales) {
+ if ((ScaleParam.TYPE_ALARM & scaleParam.typesMask) != 0) {
+ vibrationScales.put(USAGE_ALARM, scaleParam.scale);
+ }
+
+ if ((ScaleParam.TYPE_NOTIFICATION & scaleParam.typesMask) != 0) {
+ vibrationScales.put(USAGE_NOTIFICATION, scaleParam.scale);
+ vibrationScales.put(USAGE_COMMUNICATION_REQUEST, scaleParam.scale);
+ }
+
+ if ((ScaleParam.TYPE_RINGTONE & scaleParam.typesMask) != 0) {
+ vibrationScales.put(USAGE_RINGTONE, scaleParam.scale);
+ }
+
+ if ((ScaleParam.TYPE_MEDIA & scaleParam.typesMask) != 0) {
+ vibrationScales.put(USAGE_MEDIA, scaleParam.scale);
+ vibrationScales.put(USAGE_UNKNOWN, scaleParam.scale);
+ }
+
+ if ((ScaleParam.TYPE_INTERACTIVE & scaleParam.typesMask) != 0) {
+ vibrationScales.put(USAGE_TOUCH, scaleParam.scale);
+ vibrationScales.put(USAGE_HARDWARE_FEEDBACK, scaleParam.scale);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index fc824ab..2c1ab95 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -273,7 +273,8 @@
injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService());
if (ServiceManager.isDeclared(VIBRATOR_CONTROL_SERVICE)) {
injector.addService(VIBRATOR_CONTROL_SERVICE,
- new VibratorControlService(new VibratorControllerHolder(), mLock));
+ new VibratorControlService(new VibratorControllerHolder(), mVibrationScaler,
+ mLock));
}
}
diff --git a/services/tests/vibrator/Android.bp b/services/tests/vibrator/Android.bp
index 6f37967..66dcaff 100644
--- a/services/tests/vibrator/Android.bp
+++ b/services/tests/vibrator/Android.bp
@@ -31,13 +31,13 @@
"frameworks-base-testutils",
"frameworks-services-vibrator-testutils",
"junit",
- "mockito-target-minus-junit4",
+ "mockito-target-inline-minus-junit4",
"platform-test-annotations",
"service-permission.stubs.system_server",
"services.core",
"flag-junit",
],
-
+ jni_libs: ["libdexmakerjvmtiagent"],
platform_apis: true,
certificate: "platform",
dxflags: ["--multi-dex"],
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java
index bbca704e..f9fe6a9 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -43,12 +43,17 @@
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.test.TestLooper;
+import android.os.vibrator.Flags;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
@@ -68,6 +73,9 @@
@Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock private PowerManagerInternal mPowerManagerInternalMock;
@Mock private PackageManagerInternal mPackageManagerInternalMock;
@@ -256,6 +264,29 @@
assertEquals(0.5, scaled.getScale(), 1e-5);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
+ public void scale_withAdaptiveHaptics_scalesVibrationsCorrectly() {
+ setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH);
+
+ SparseArray<Float> adaptiveHapticsScales = new SparseArray<>();
+ adaptiveHapticsScales.put(USAGE_RINGTONE, 0.5f);
+ adaptiveHapticsScales.put(USAGE_NOTIFICATION, 0.5f);
+ mVibrationScaler.updateAdaptiveHapticsScales(adaptiveHapticsScales);
+
+ StepSegment scaled = getFirstSegment(mVibrationScaler.scale(
+ VibrationEffect.createOneShot(128, 128), USAGE_RINGTONE));
+ // Ringtone scales down.
+ assertTrue(scaled.getAmplitude() < 0.5);
+
+ scaled = getFirstSegment(mVibrationScaler.scale(
+ VibrationEffect.createWaveform(new long[]{128}, new int[]{128}, -1),
+ USAGE_NOTIFICATION));
+ // Notification scales down.
+ assertTrue(scaled.getAmplitude() < 0.5);
+ }
+
private void setDefaultIntensity(@VibrationAttributes.Usage int usage,
@Vibrator.VibrationIntensity int intensity) {
when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
index 49efd1b..1e0b1df 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
@@ -16,21 +16,49 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.frameworks.vibrator.ScaleParam;
+import android.frameworks.vibrator.VibrationParam;
import android.os.RemoteException;
+import android.util.SparseArray;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
public class VibratorControlServiceTest {
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+
+ @Mock
+ private VibrationScaler mMockVibrationScaler;
+ @Captor
+ private ArgumentCaptor<SparseArray<Float>> mVibrationScalesCaptor;
+
private VibratorControlService mVibratorControlService;
private final Object mLock = new Object();
@Before
public void setUp() throws Exception {
- mVibratorControlService = new VibratorControlService(new VibratorControllerHolder(), mLock);
+ mVibratorControlService = new VibratorControlService(new VibratorControllerHolder(),
+ mMockVibrationScaler, mLock);
}
@Test
@@ -47,6 +75,8 @@
FakeVibratorController fakeController = new FakeVibratorController();
mVibratorControlService.registerVibratorController(fakeController);
mVibratorControlService.unregisterVibratorController(fakeController);
+
+ verify(mMockVibrationScaler).updateAdaptiveHapticsScales(null);
assertThat(fakeController.isLinkedToDeath).isFalse();
}
@@ -56,8 +86,91 @@
FakeVibratorController fakeController1 = new FakeVibratorController();
FakeVibratorController fakeController2 = new FakeVibratorController();
mVibratorControlService.registerVibratorController(fakeController1);
-
mVibratorControlService.unregisterVibratorController(fakeController2);
+
+ verifyZeroInteractions(mMockVibrationScaler);
assertThat(fakeController1.isLinkedToDeath).isTrue();
}
+
+ @Test
+ public void testSetVibrationParams_cachesAdaptiveHapticsScalesCorrectly()
+ throws RemoteException {
+ FakeVibratorController fakeController = new FakeVibratorController();
+ mVibratorControlService.registerVibratorController(fakeController);
+ SparseArray<Float> vibrationScales = new SparseArray<>();
+ vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f);
+ vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f);
+
+ mVibratorControlService.setVibrationParams(generateVibrationParams(vibrationScales),
+ fakeController);
+
+ verify(mMockVibrationScaler).updateAdaptiveHapticsScales(mVibrationScalesCaptor.capture());
+ SparseArray<Float> cachedVibrationScales = mVibrationScalesCaptor.getValue();
+ assertThat(cachedVibrationScales.size()).isEqualTo(3);
+ assertThat(cachedVibrationScales.keyAt(0)).isEqualTo(USAGE_ALARM);
+ assertThat(cachedVibrationScales.valueAt(0)).isEqualTo(0.7f);
+ assertThat(cachedVibrationScales.keyAt(1)).isEqualTo(USAGE_NOTIFICATION);
+ assertThat(cachedVibrationScales.valueAt(1)).isEqualTo(0.4f);
+ // Setting ScaleParam.TYPE_NOTIFICATION will update vibration scaling for both
+ // notification and communication request usages.
+ assertThat(cachedVibrationScales.keyAt(2)).isEqualTo(USAGE_COMMUNICATION_REQUEST);
+ assertThat(cachedVibrationScales.valueAt(2)).isEqualTo(0.4f);
+ }
+
+ @Test
+ public void testSetVibrationParams_withUnregisteredController_ignoresRequest()
+ throws RemoteException {
+ FakeVibratorController fakeController = new FakeVibratorController();
+
+ SparseArray<Float> vibrationScales = new SparseArray<>();
+ vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f);
+ vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f);
+
+ mVibratorControlService.setVibrationParams(generateVibrationParams(vibrationScales),
+ fakeController);
+
+ verifyZeroInteractions(mMockVibrationScaler);
+ }
+
+ @Test
+ public void testClearVibrationParams_clearsCachedAdaptiveHapticsScales()
+ throws RemoteException {
+ FakeVibratorController fakeController = new FakeVibratorController();
+ mVibratorControlService.registerVibratorController(fakeController);
+ mVibratorControlService.clearVibrationParams(ScaleParam.TYPE_ALARM, fakeController);
+
+ verify(mMockVibrationScaler).updateAdaptiveHapticsScales(null);
+ }
+
+ @Test
+ public void testClearVibrationParams_withUnregisteredController_ignoresRequest()
+ throws RemoteException {
+ FakeVibratorController fakeController = new FakeVibratorController();
+
+ mVibratorControlService.clearVibrationParams(ScaleParam.TYPE_ALARM, fakeController);
+
+ verifyZeroInteractions(mMockVibrationScaler);
+ }
+
+ private VibrationParam[] generateVibrationParams(SparseArray<Float> vibrationScales) {
+ List<VibrationParam> vibrationParamList = new ArrayList<>();
+ for (int i = 0; i < vibrationScales.size(); i++) {
+ int type = vibrationScales.keyAt(i);
+ float scale = vibrationScales.valueAt(i);
+
+ vibrationParamList.add(generateVibrationParam(type, scale));
+ }
+
+ return vibrationParamList.toArray(new VibrationParam[0]);
+ }
+
+ private VibrationParam generateVibrationParam(int type, float scale) {
+ ScaleParam scaleParam = new ScaleParam();
+ scaleParam.typesMask = type;
+ scaleParam.scale = scale;
+ VibrationParam vibrationParam = new VibrationParam();
+ vibrationParam.setScale(scaleParam);
+
+ return vibrationParam;
+ }
}