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

Commit 03b9a543 authored by Lais Andrade's avatar Lais Andrade
Browse files

Replace observer for USER_SWITCHED broadbast by a UserSwitchObserver

Replace a broadcast intent observer for USER_SWITCHED by a
UserSwitchObserver instance registered to the ActivityManager.

Add an early reaction to user switch by implementing the method
onUserSwitching, which is triggered before any app is notified. Reload
user vibration settings based on the new user ID.

Fix: 308932536
Test: atest VibrationSettingsTest
Change-Id: I185903a0679da01409bcc5db6e0703d451bae0c2
parent a892df45
Loading
Loading
Loading
Loading
+56 −34
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.os.VibrationAttributes.USAGE_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.SynchronousUserSwitchObserver;
import android.app.UidObserver;
import android.app.UidObserver;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
@@ -145,8 +146,6 @@ final class VibrationSettings {
                    PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
                    PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT));
                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT));


    private static final IntentFilter USER_SWITCHED_INTENT_FILTER =
            new IntentFilter(Intent.ACTION_USER_SWITCHED);
    private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER =
    private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER =
            new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
            new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);


@@ -162,9 +161,11 @@ final class VibrationSettings {
    @VisibleForTesting
    @VisibleForTesting
    final SettingsContentObserver mSettingObserver;
    final SettingsContentObserver mSettingObserver;
    @VisibleForTesting
    @VisibleForTesting
    final MyUidObserver mUidObserver;
    @VisibleForTesting
    final SettingsBroadcastReceiver mSettingChangeReceiver;
    final SettingsBroadcastReceiver mSettingChangeReceiver;
    @VisibleForTesting
    final VibrationUidObserver mUidObserver;
    @VisibleForTesting
    final VibrationUserSwitchObserver mUserSwitchObserver;


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
    private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -205,8 +206,9 @@ final class VibrationSettings {
        mContext = context;
        mContext = context;
        mVibrationConfig = config;
        mVibrationConfig = config;
        mSettingObserver = new SettingsContentObserver(handler);
        mSettingObserver = new SettingsContentObserver(handler);
        mUidObserver = new MyUidObserver();
        mSettingChangeReceiver = new SettingsBroadcastReceiver();
        mSettingChangeReceiver = new SettingsBroadcastReceiver();
        mUidObserver = new VibrationUidObserver();
        mUserSwitchObserver = new VibrationUserSwitchObserver();
        mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class)
        mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class)
                .getSystemUiServiceComponent().getPackageName();
                .getSystemUiServiceComponent().getPackageName();


@@ -245,7 +247,13 @@ final class VibrationSettings {
        try {
        try {
            ActivityManager.getService().registerUidObserver(mUidObserver,
            ActivityManager.getService().registerUidObserver(mUidObserver,
                    ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
                    ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
                    ActivityManager.PROCESS_STATE_UNKNOWN, null);
                    ActivityManager.PROCESS_STATE_UNKNOWN, /* callingPackage= */ null);
        } catch (RemoteException e) {
            // ignored; both services live in system_server
        }

        try {
            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // ignored; both services live in system_server
            // ignored; both services live in system_server
        }
        }
@@ -270,7 +278,6 @@ final class VibrationSettings {
                    }
                    }
                });
                });


        registerSettingsChangeReceiver(USER_SWITCHED_INTENT_FILTER);
        registerSettingsChangeReceiver(INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER);
        registerSettingsChangeReceiver(INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER);


        // Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
        // Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
@@ -540,41 +547,44 @@ final class VibrationSettings {


    /** Update all cached settings and triggers registered listeners. */
    /** Update all cached settings and triggers registered listeners. */
    void update() {
    void update() {
        updateSettings();
        updateSettings(UserHandle.USER_CURRENT);
        updateRingerMode();
        updateRingerMode();
        notifyListeners();
        notifyListeners();
    }
    }


    private void updateSettings() {
    private void updateSettings(int userHandle) {
        synchronized (mLock) {
        synchronized (mLock) {
            mVibrateInputDevices = loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
            mVibrateInputDevices =
            mVibrateOn = loadSystemSetting(Settings.System.VIBRATE_ON, 1) > 0;
                    loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0, userHandle) > 0;
            mVibrateOn = loadSystemSetting(Settings.System.VIBRATE_ON, 1, userHandle) > 0;
            mKeyboardVibrationOn = loadSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED,
            mKeyboardVibrationOn = loadSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED,
                    mVibrationConfig.isDefaultKeyboardVibrationEnabled() ? 1 : 0) > 0;
                    mVibrationConfig.isDefaultKeyboardVibrationEnabled() ? 1 : 0, userHandle) > 0;


            int alarmIntensity = toIntensity(
            int alarmIntensity = toIntensity(
                    loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1),
                    loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1, userHandle),
                    getDefaultIntensity(USAGE_ALARM));
                    getDefaultIntensity(USAGE_ALARM));
            int defaultHapticFeedbackIntensity = getDefaultIntensity(USAGE_TOUCH);
            int defaultHapticFeedbackIntensity = getDefaultIntensity(USAGE_TOUCH);
            int hapticFeedbackIntensity = toIntensity(
            int hapticFeedbackIntensity = toIntensity(
                    loadSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, -1),
                    loadSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, -1, userHandle),
                    defaultHapticFeedbackIntensity);
                    defaultHapticFeedbackIntensity);
            int positiveHapticFeedbackIntensity = toPositiveIntensity(
            int positiveHapticFeedbackIntensity = toPositiveIntensity(
                    hapticFeedbackIntensity, defaultHapticFeedbackIntensity);
                    hapticFeedbackIntensity, defaultHapticFeedbackIntensity);
            int hardwareFeedbackIntensity = toIntensity(
            int hardwareFeedbackIntensity = toIntensity(
                    loadSystemSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, -1),
                    loadSystemSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, -1,
                            userHandle),
                    positiveHapticFeedbackIntensity);
                    positiveHapticFeedbackIntensity);
            int mediaIntensity = toIntensity(
            int mediaIntensity = toIntensity(
                    loadSystemSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, -1),
                    loadSystemSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, -1, userHandle),
                    getDefaultIntensity(USAGE_MEDIA));
                    getDefaultIntensity(USAGE_MEDIA));
            int defaultNotificationIntensity = getDefaultIntensity(USAGE_NOTIFICATION);
            int defaultNotificationIntensity = getDefaultIntensity(USAGE_NOTIFICATION);
            int notificationIntensity = toIntensity(
            int notificationIntensity = toIntensity(
                    loadSystemSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, -1),
                    loadSystemSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, -1,
                            userHandle),
                    defaultNotificationIntensity);
                    defaultNotificationIntensity);
            int positiveNotificationIntensity = toPositiveIntensity(
            int positiveNotificationIntensity = toPositiveIntensity(
                    notificationIntensity, defaultNotificationIntensity);
                    notificationIntensity, defaultNotificationIntensity);
            int ringIntensity = toIntensity(
            int ringIntensity = toIntensity(
                    loadSystemSetting(Settings.System.RING_VIBRATION_INTENSITY, -1),
                    loadSystemSetting(Settings.System.RING_VIBRATION_INTENSITY, -1, userHandle),
                    getDefaultIntensity(USAGE_RINGTONE));
                    getDefaultIntensity(USAGE_RINGTONE));


            mCurrentVibrationIntensities.clear();
            mCurrentVibrationIntensities.clear();
@@ -593,7 +603,7 @@ final class VibrationSettings {
            mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity);
            mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity);
            mCurrentVibrationIntensities.put(USAGE_PHYSICAL_EMULATION, hardwareFeedbackIntensity);
            mCurrentVibrationIntensities.put(USAGE_PHYSICAL_EMULATION, hardwareFeedbackIntensity);


            if (!loadBooleanSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)) {
            if (!loadBooleanSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, userHandle)) {
                // Make sure deprecated boolean setting still disables touch vibrations.
                // Make sure deprecated boolean setting still disables touch vibrations.
                mCurrentVibrationIntensities.put(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_OFF);
                mCurrentVibrationIntensities.put(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_OFF);
            } else {
            } else {
@@ -744,14 +754,13 @@ final class VibrationSettings {
        return value;
        return value;
    }
    }


    private boolean loadBooleanSetting(String settingKey) {
    private boolean loadBooleanSetting(String settingKey, int userHandle) {
        return Settings.System.getIntForUser(mContext.getContentResolver(),
        return loadSystemSetting(settingKey, 0, userHandle) != 0;
                settingKey, 0, UserHandle.USER_CURRENT) != 0;
    }
    }


    private int loadSystemSetting(String settingName, int defaultValue) {
    private int loadSystemSetting(String settingName, int defaultValue, int userHandle) {
        return Settings.System.getIntForUser(mContext.getContentResolver(),
        return Settings.System.getIntForUser(mContext.getContentResolver(),
                settingName, defaultValue, UserHandle.USER_CURRENT);
                settingName, defaultValue, userHandle);
    }
    }


    private void registerSettingsObserver(Uri settingUri) {
    private void registerSettingsObserver(Uri settingUri) {
@@ -828,24 +837,18 @@ final class VibrationSettings {


        @Override
        @Override
        public void onChange(boolean selfChange) {
        public void onChange(boolean selfChange) {
            updateSettings();
            updateSettings(UserHandle.USER_CURRENT);
            notifyListeners();
            notifyListeners();
        }
        }
    }
    }


    /**
    /** Implementation of {@link BroadcastReceiver} to update on ringer mode change. */
     * Implementation of {@link BroadcastReceiver} to update settings on current user or ringer
     * mode change.
     */
    @VisibleForTesting
    @VisibleForTesting
    final class SettingsBroadcastReceiver extends BroadcastReceiver {
    final class SettingsBroadcastReceiver extends BroadcastReceiver {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String action = intent.getAction();
            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
            if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
                // Reload all settings, as they are user-based.
                update();
            } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
                updateRingerMode();
                updateRingerMode();
                notifyListeners();
                notifyListeners();
            }
            }
@@ -854,7 +857,7 @@ final class VibrationSettings {


    /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
    /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
    @VisibleForTesting
    @VisibleForTesting
    final class MyUidObserver extends UidObserver {
    final class VibrationUidObserver extends UidObserver {
        private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
        private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();


        public boolean isUidForeground(int uid) {
        public boolean isUidForeground(int uid) {
@@ -878,4 +881,23 @@ final class VibrationSettings {
            }
            }
        }
        }
    }
    }

    /** Implementation of {@link SynchronousUserSwitchObserver} to update on user switch. */
    @VisibleForTesting
    final class VibrationUserSwitchObserver extends SynchronousUserSwitchObserver {

        @Override
        public void onUserSwitching(int newUserId) {
            // Reload settings early based on new user id.
            updateSettings(newUserId);
            notifyListeners();
        }

        @Override
        public void onUserSwitchComplete(int newUserId) {
            // Reload all settings including ones from AudioManager,
            // as they are based on UserHandle.USER_CURRENT.
            update();
        }
    }
}
}
+22 −13
Original line number Original line Diff line number Diff line
@@ -100,6 +100,8 @@ public class VibrationSettingsTest {
    @Rule
    @Rule
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();


    private static final int OLD_USER_ID = 123;
    private static final int NEW_USER_ID = 456;
    private static final int UID = 1;
    private static final int UID = 1;
    private static final int VIRTUAL_DEVICE_ID = 1;
    private static final int VIRTUAL_DEVICE_ID = 1;
    private static final String SYSUI_PACKAGE_NAME = "sysui";
    private static final String SYSUI_PACKAGE_NAME = "sysui";
@@ -211,10 +213,10 @@ public class VibrationSettingsTest {
        mVibrationSettings.addListener(mListenerMock);
        mVibrationSettings.addListener(mListenerMock);


        // Testing the broadcast flow manually.
        // Testing the broadcast flow manually.
        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
        mVibrationSettings.mUserSwitchObserver.onUserSwitching(NEW_USER_ID);
                new Intent(Intent.ACTION_USER_SWITCHED));
        mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);


        verify(mListenerMock).onChange();
        verify(mListenerMock, times(2)).onChange();
    }
    }


    @Test
    @Test
@@ -265,8 +267,7 @@ public class VibrationSettingsTest {
        // Trigger multiple observers manually.
        // Trigger multiple observers manually.
        mVibrationSettings.mSettingObserver.onChange(false);
        mVibrationSettings.mSettingObserver.onChange(false);
        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
        mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);
                new Intent(Intent.ACTION_USER_SWITCHED));
        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));


@@ -834,13 +835,17 @@ public class VibrationSettingsTest {
        assertEquals(VIBRATION_INTENSITY_HIGH,
        assertEquals(VIBRATION_INTENSITY_HIGH,
                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));


        // Switching user is not working with FakeSettingsProvider.
        // Test early update of settings based on new user id.
        // Testing the broadcast flow manually.
        putUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
        Settings.System.putIntForUser(mContextSpy.getContentResolver(),
                NEW_USER_ID);
                Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
        mVibrationSettings.mUserSwitchObserver.onUserSwitching(NEW_USER_ID);
        assertEquals(VIBRATION_INTENSITY_LOW,
                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));

        // Test later update of settings for UserHandle.USER_CURRENT.
        putUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
                UserHandle.USER_CURRENT);
                UserHandle.USER_CURRENT);
        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
        mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);
                new Intent(Intent.ACTION_USER_SWITCHED));
        assertEquals(VIBRATION_INTENSITY_LOW,
        assertEquals(VIBRATION_INTENSITY_LOW,
                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
    }
    }
@@ -956,12 +961,16 @@ public class VibrationSettingsTest {
    }
    }


    private void setUserSetting(String settingName, int value) {
    private void setUserSetting(String settingName, int value) {
        Settings.System.putIntForUser(
        putUserSetting(settingName, value, UserHandle.USER_CURRENT);
                mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
        // FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
        // FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
        mVibrationSettings.mSettingObserver.onChange(false);
        mVibrationSettings.mSettingObserver.onChange(false);
    }
    }


    private void putUserSetting(String settingName, int value, int userHandle) {
        Settings.System.putIntForUser(
                mContextSpy.getContentResolver(), settingName, value, userHandle);
    }

    private void setRingerMode(int ringerMode) {
    private void setRingerMode(int ringerMode) {
        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
        // Mock AudioManager broadcast of internal ringer mode change.
        // Mock AudioManager broadcast of internal ringer mode change.