Loading core/java/android/os/vibrator/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -64,3 +64,13 @@ flag { purpose: PURPOSE_FEATURE } } flag { namespace: "haptics" name: "throttle_vibration_params_requests" description: "Control the frequency of vibration params requests to prevent overloading the vendor service" bug: "355320860" metadata { purpose: PURPOSE_BUGFIX } } services/core/java/com/android/server/vibrator/VibratorControlService.java +11 −2 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.Slog; Loading Loading @@ -265,9 +266,15 @@ final class VibratorControlService extends IVibratorControlService.Stub { return null; } if (Flags.throttleVibrationParamsRequests() && mVibrationParamRequest != null && mVibrationParamRequest.usage == usage) { // Reuse existing future for ongoing request with same usage. return mVibrationParamRequest.future; } try { endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ true); mVibrationParamRequest = new VibrationParamRequest(uid); mVibrationParamRequest = new VibrationParamRequest(uid, usage); vibratorController.requestVibrationParams(vibrationType, timeoutInMillis, mVibrationParamRequest.token); return mVibrationParamRequest.future; Loading Loading @@ -533,10 +540,12 @@ final class VibratorControlService extends IVibratorControlService.Stub { public final CompletableFuture<Void> future = new CompletableFuture<>(); public final IBinder token = new Binder(); public final int uid; public final @VibrationAttributes.Usage int usage; public final long uptimeMs; VibrationParamRequest(int uid) { VibrationParamRequest(int uid, @VibrationAttributes.Usage int usage) { this.uid = uid; this.usage = usage; uptimeMs = SystemClock.uptimeMillis(); } Loading services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +52 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.test.TestLooper; import android.os.vibrator.Flags; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; Loading @@ -63,7 +68,6 @@ import org.mockito.junit.MockitoRule; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class VibratorControlServiceTest { Loading @@ -71,6 +75,8 @@ public class VibratorControlServiceTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private VibrationScaler mMockVibrationScaler; @Mock private PackageManagerInternal mPackageManagerInternalMock; Loading Loading @@ -98,6 +104,7 @@ public class VibratorControlServiceTest { mVibratorControlService = new VibratorControlService( InstrumentationRegistry.getContext(), new VibratorControllerHolder(), mMockVibrationScaler, mVibrationSettings, mStatsLoggerMock, mLock); mFakeVibratorController.setVibratorControlService(mVibratorControlService); } @Test Loading Loading @@ -280,10 +287,10 @@ public class VibratorControlServiceTest { CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); try { future.orTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).get(); } catch (Throwable ignored) { } mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future.isDone()).isTrue(); assertThat(mFakeVibratorController.didRequestVibrationParams).isTrue(); assertThat(mFakeVibratorController.requestVibrationType).isEqualTo( ScaleParam.TYPE_RINGTONE); Loading Loading @@ -315,6 +322,46 @@ public class VibratorControlServiceTest { } } @Test @RequiresFlagsEnabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnOngoingFuture() { int timeoutInMillis = 10; mVibratorControlService.registerVibratorController(mFakeVibratorController); CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); CompletableFuture<Void> future2 = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future).isEqualTo(future2); assertThat(future.isDone()).isTrue(); assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(1); } @Test @RequiresFlagsDisabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnNewFuture() { int timeoutInMillis = 10; mVibratorControlService.registerVibratorController(mFakeVibratorController); CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); CompletableFuture<Void> future2 = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future2).isNotNull(); assertThat(future).isNotEqualTo(future2); assertThat(future.isDone()).isTrue(); assertThat(future2.isDone()).isTrue(); assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(2); } private static int buildVibrationTypesMask(int... types) { int typesMask = 0; for (int type : types) { Loading services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { public boolean didRequestVibrationParams = false; public int requestVibrationType = VibrationAttributes.USAGE_UNKNOWN; public long requestTimeoutInMillis = 0; public int requestVibrationParamsCounter = 0; public FakeVibratorController(Looper looper) { mHandler = new Handler(looper); Loading @@ -58,6 +59,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { didRequestVibrationParams = true; requestVibrationType = vibrationType; requestTimeoutInMillis = timeoutInMillis; requestVibrationParamsCounter++; mHandler.post(() -> { if (mVibratorControlService != null) { mVibratorControlService.onRequestVibrationParamsComplete(token, mRequestResult); Loading Loading
core/java/android/os/vibrator/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -64,3 +64,13 @@ flag { purpose: PURPOSE_FEATURE } } flag { namespace: "haptics" name: "throttle_vibration_params_requests" description: "Control the frequency of vibration params requests to prevent overloading the vendor service" bug: "355320860" metadata { purpose: PURPOSE_BUGFIX } }
services/core/java/com/android/server/vibrator/VibratorControlService.java +11 −2 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.Slog; Loading Loading @@ -265,9 +266,15 @@ final class VibratorControlService extends IVibratorControlService.Stub { return null; } if (Flags.throttleVibrationParamsRequests() && mVibrationParamRequest != null && mVibrationParamRequest.usage == usage) { // Reuse existing future for ongoing request with same usage. return mVibrationParamRequest.future; } try { endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ true); mVibrationParamRequest = new VibrationParamRequest(uid); mVibrationParamRequest = new VibrationParamRequest(uid, usage); vibratorController.requestVibrationParams(vibrationType, timeoutInMillis, mVibrationParamRequest.token); return mVibrationParamRequest.future; Loading Loading @@ -533,10 +540,12 @@ final class VibratorControlService extends IVibratorControlService.Stub { public final CompletableFuture<Void> future = new CompletableFuture<>(); public final IBinder token = new Binder(); public final int uid; public final @VibrationAttributes.Usage int usage; public final long uptimeMs; VibrationParamRequest(int uid) { VibrationParamRequest(int uid, @VibrationAttributes.Usage int usage) { this.uid = uid; this.usage = usage; uptimeMs = SystemClock.uptimeMillis(); } Loading
services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +52 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.test.TestLooper; import android.os.vibrator.Flags; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; Loading @@ -63,7 +68,6 @@ import org.mockito.junit.MockitoRule; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class VibratorControlServiceTest { Loading @@ -71,6 +75,8 @@ public class VibratorControlServiceTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private VibrationScaler mMockVibrationScaler; @Mock private PackageManagerInternal mPackageManagerInternalMock; Loading Loading @@ -98,6 +104,7 @@ public class VibratorControlServiceTest { mVibratorControlService = new VibratorControlService( InstrumentationRegistry.getContext(), new VibratorControllerHolder(), mMockVibrationScaler, mVibrationSettings, mStatsLoggerMock, mLock); mFakeVibratorController.setVibratorControlService(mVibratorControlService); } @Test Loading Loading @@ -280,10 +287,10 @@ public class VibratorControlServiceTest { CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); try { future.orTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).get(); } catch (Throwable ignored) { } mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future.isDone()).isTrue(); assertThat(mFakeVibratorController.didRequestVibrationParams).isTrue(); assertThat(mFakeVibratorController.requestVibrationType).isEqualTo( ScaleParam.TYPE_RINGTONE); Loading Loading @@ -315,6 +322,46 @@ public class VibratorControlServiceTest { } } @Test @RequiresFlagsEnabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnOngoingFuture() { int timeoutInMillis = 10; mVibratorControlService.registerVibratorController(mFakeVibratorController); CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); CompletableFuture<Void> future2 = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future).isEqualTo(future2); assertThat(future.isDone()).isTrue(); assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(1); } @Test @RequiresFlagsDisabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnNewFuture() { int timeoutInMillis = 10; mVibratorControlService.registerVibratorController(mFakeVibratorController); CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); CompletableFuture<Void> future2 = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); mTestLooper.dispatchAll(); assertThat(future).isNotNull(); assertThat(future2).isNotNull(); assertThat(future).isNotEqualTo(future2); assertThat(future.isDone()).isTrue(); assertThat(future2.isDone()).isTrue(); assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(2); } private static int buildVibrationTypesMask(int... types) { int typesMask = 0; for (int type : types) { Loading
services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { public boolean didRequestVibrationParams = false; public int requestVibrationType = VibrationAttributes.USAGE_UNKNOWN; public long requestTimeoutInMillis = 0; public int requestVibrationParamsCounter = 0; public FakeVibratorController(Looper looper) { mHandler = new Handler(looper); Loading @@ -58,6 +59,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { didRequestVibrationParams = true; requestVibrationType = vibrationType; requestTimeoutInMillis = timeoutInMillis; requestVibrationParamsCounter++; mHandler.post(() -> { if (mVibratorControlService != null) { mVibratorControlService.onRequestVibrationParamsComplete(token, mRequestResult); Loading