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

Commit 2cd9c512 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix crash when using VibratorManagerService before system ready" into sc-dev

parents ced14474 de172a43
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.vibrator;

import android.annotation.Nullable;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.CombinedVibrationEffect;
@@ -33,7 +34,11 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {

    private final Object mLock = new Object();
    private final Handler mHandler;
    private final InputManager mInputManager;
    private final Context mContext;

    @GuardedBy("mLock")
    @Nullable
    private InputManager mInputManager;

    @GuardedBy("mLock")
    private final SparseArray<VibratorManager> mInputDeviceVibrators = new SparseArray<>();
@@ -47,7 +52,13 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {

    InputDeviceDelegate(Context context, Handler handler) {
        mHandler = handler;
        mInputManager = context.getSystemService(InputManager.class);
        mContext = context;
    }

    public void onSystemReady() {
        synchronized (mLock) {
            mInputManager = mContext.getSystemService(InputManager.class);
        }
    }

    @Override
@@ -116,6 +127,10 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {
     */
    public boolean updateInputDeviceVibrators(boolean vibrateInputDevices) {
        synchronized (mLock) {
            if (mInputManager == null) {
                // Ignore update, service not loaded yet so change cannot be applied.
                return false;
            }
            if (vibrateInputDevices == mShouldVibrateInputDevices) {
                // No need to update if settings haven't changed.
                return false;
@@ -150,6 +165,10 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {

    private void updateInputDevice(int deviceId) {
        synchronized (mLock) {
            if (mInputManager == null) {
                // Ignore update, service not loaded yet so change cannot be applied.
                return;
            }
            if (!mShouldVibrateInputDevices) {
                // No need to keep this device vibrator if setting is off.
                return;
+52 −32
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.vibrator;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IUidObserver;
import android.content.Context;
@@ -57,8 +58,6 @@ final class VibrationSettings {

    private final Object mLock = new Object();
    private final Context mContext;
    private final Vibrator mVibrator;
    private final AudioManager mAudioManager;
    private final SettingsObserver mSettingObserver;
    @VisibleForTesting
    final UidObserver mUidObserver;
@@ -67,6 +66,13 @@ final class VibrationSettings {
    private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
    private final SparseArray<VibrationEffect> mFallbackEffects;

    @GuardedBy("mLock")
    @Nullable
    private Vibrator mVibrator;
    @GuardedBy("mLock")
    @Nullable
    private AudioManager mAudioManager;

    @GuardedBy("mLock")
    private boolean mVibrateInputDevices;
    @GuardedBy("mLock")
@@ -86,22 +92,9 @@ final class VibrationSettings {

    VibrationSettings(Context context, Handler handler) {
        mContext = context;
        mVibrator = context.getSystemService(Vibrator.class);
        mAudioManager = context.getSystemService(AudioManager.class);
        mSettingObserver = new SettingsObserver(handler);
        mUidObserver = new UidObserver();

        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.APPLY_RAMPING_RINGER));
        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.ZEN_MODE));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY));

        VibrationEffect clickEffect = createEffectFromResource(
                com.android.internal.R.array.config_virtualKeyVibePattern);
        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
@@ -119,6 +112,15 @@ final class VibrationSettings {
        mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK,
                VibrationEffect.get(VibrationEffect.EFFECT_TICK, false));

        // Update with current values from settings.
        updateSettings();
    }

    public void onSystemReady() {
        synchronized (mLock) {
            mVibrator = mContext.getSystemService(Vibrator.class);
            mAudioManager = mContext.getSystemService(AudioManager.class);
        }
        try {
            ActivityManager.getService().registerUidObserver(mUidObserver,
                    ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
@@ -148,7 +150,18 @@ final class VibrationSettings {
                    }
                });

        // Update with current values from settings.
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.APPLY_RAMPING_RINGER));
        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.ZEN_MODE));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY));

        // Update with newly loaded services.
        updateSettings();
    }

@@ -178,18 +191,22 @@ final class VibrationSettings {
     * @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
     */
    public int getDefaultIntensity(int usageHint) {
        if (isAlarm(usageHint)) {
            return Vibrator.VIBRATION_INTENSITY_HIGH;
        }
        synchronized (mLock) {
            if (mVibrator != null) {
                if (isRingtone(usageHint)) {
                    return mVibrator.getDefaultRingVibrationIntensity();
                } else if (isNotification(usageHint)) {
                    return mVibrator.getDefaultNotificationVibrationIntensity();
                } else if (isHapticFeedback(usageHint)) {
                    return mVibrator.getDefaultHapticFeedbackIntensity();
        } else if (isAlarm(usageHint)) {
            return Vibrator.VIBRATION_INTENSITY_HIGH;
        } else {
            return Vibrator.VIBRATION_INTENSITY_MEDIUM;
                }
            }
        }
        return Vibrator.VIBRATION_INTENSITY_MEDIUM;
    }

    /**
     * Return the current vibration intensity set for given usage at the user settings.
@@ -234,8 +251,11 @@ final class VibrationSettings {
        if (!isRingtone(usageHint)) {
            return true;
        }
        int ringerMode = mAudioManager.getRingerModeInternal();
        synchronized (mLock) {
            if (mAudioManager == null) {
                return false;
            }
            int ringerMode = mAudioManager.getRingerModeInternal();
            if (mVibrateWhenRinging) {
                return ringerMode != AudioManager.RINGER_MODE_SILENT;
            } else if (mApplyRampingRinger) {
@@ -304,12 +324,12 @@ final class VibrationSettings {
            mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
            mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0;
            mHapticFeedbackIntensity = getSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
                    mVibrator.getDefaultHapticFeedbackIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
            mNotificationIntensity = getSystemSetting(
                    Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
                    mVibrator.getDefaultNotificationVibrationIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
            mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
                    mVibrator.getDefaultRingVibrationIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
            mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
            mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
        }
@@ -346,15 +366,15 @@ final class VibrationSettings {
            proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
                    mHapticFeedbackIntensity);
            proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
                    mVibrator.getDefaultHapticFeedbackIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
            proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY,
                    mNotificationIntensity);
            proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY,
                    mVibrator.getDefaultNotificationVibrationIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
            proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY,
                    mRingIntensity);
            proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY,
                    mVibrator.getDefaultRingVibrationIntensity());
                    getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
        }
    }

+10 −6
Original line number Diff line number Diff line
@@ -127,9 +127,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
    @GuardedBy("mLock")
    private ExternalVibrationHolder mCurrentExternalVibration;

    private VibrationSettings mVibrationSettings;
    private VibrationScaler mVibrationScaler;
    private InputDeviceDelegate mInputDeviceDelegate;
    private final VibrationSettings mVibrationSettings;
    private final VibrationScaler mVibrationScaler;
    private final InputDeviceDelegate mInputDeviceDelegate;

    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
@@ -170,6 +170,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
        mContext = context;
        mHandler = injector.createHandler(Looper.myLooper());

        mVibrationSettings = new VibrationSettings(mContext, mHandler);
        mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
        mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler);

        VibrationCompleteListener listener = new VibrationCompleteListener(this);
        mNativeWrapper = injector.getNativeWrapper();
        mNativeWrapper.init(listener);
@@ -224,12 +228,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
        Slog.v(TAG, "Initializing VibratorManager service...");
        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "systemReady");
        try {
            mVibrationSettings = new VibrationSettings(mContext, mHandler);
            mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
            mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler);
            mVibrationSettings.onSystemReady();
            mInputDeviceDelegate.onSystemReady();

            mVibrationSettings.addListener(this::updateServiceState);

            // Will update settings and input devices.
            updateServiceState();
        } finally {
            Slog.v(TAG, "VibratorManager service initialized");
+19 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ public class InputDeviceDelegateTest {

        mInputDeviceDelegate = new InputDeviceDelegate(
                mContextSpy, new Handler(mTestLooper.getLooper()));
        mInputDeviceDelegate.onSystemReady();
    }

    @After
@@ -98,6 +99,24 @@ public class InputDeviceDelegateTest {
        InputManager.clearInstance();
    }

    @Test
    public void beforeSystemReady_ignoresAnyUpdate() throws Exception {
        when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
        InputDeviceDelegate inputDeviceDelegate = new InputDeviceDelegate(
                mContextSpy, new Handler(mTestLooper.getLooper()));

        inputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true);
        assertFalse(inputDeviceDelegate.isAvailable());

        inputDeviceDelegate.onInputDeviceAdded(1);
        assertFalse(inputDeviceDelegate.isAvailable());

        updateInputDevices(new int[]{1});
        assertFalse(inputDeviceDelegate.isAvailable());

        verify(mIInputManagerMock, never()).getInputDevice(anyInt());
    }

    @Test
    public void onInputDeviceAdded_withSettingsDisabled_ignoresNewDevice() throws Exception {
        when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ public class VibrationScalerTest {
        mVibrationSettings = new VibrationSettings(
                mContextSpy, new Handler(mTestLooper.getLooper()));
        mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings);
        mVibrationSettings.onSystemReady();
    }

    @After
Loading