diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java index a7e9a0135de0e..242f8f120e274 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java @@ -89,4 +89,9 @@ public interface OneHanded { * Receive onConfigurationChanged() events */ void onConfigChanged(Configuration newConfig); + + /** + * Notifies when user switch complete + */ + void onUserSwitch(int userId); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 7965a80deead2..c5c29a85fbfcd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -17,6 +17,7 @@ package com.android.wm.shell.onehanded; import static android.os.UserHandle.USER_CURRENT; +import static android.os.UserHandle.myUserId; import static android.view.Display.DEFAULT_DISPLAY; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; @@ -74,6 +75,7 @@ public class OneHandedController implements RemoteCallable private volatile boolean mIsSwipeToNotificationEnabled; private boolean mTaskChangeToExit; private boolean mLockedDisabled; + private int mUserId; private float mOffSetFraction; private Context mContext; @@ -141,7 +143,8 @@ public class OneHandedController implements RemoteCallable } if (enabled) { final int mOneHandedTimeout = mOneHandedSettingsUtil - .getSettingsOneHandedModeTimeout(mContext.getContentResolver()); + .getSettingsOneHandedModeTimeout( + mContext.getContentResolver(), mUserId); final int timeout = mAccessibilityManager .getRecommendedTimeoutMillis(mOneHandedTimeout * 1000 /* align with A11y timeout millis */, @@ -149,7 +152,8 @@ public class OneHandedController implements RemoteCallable mTimeoutHandler.setTimeout(timeout / 1000); } else { mTimeoutHandler.setTimeout(mOneHandedSettingsUtil - .getSettingsOneHandedModeTimeout(mContext.getContentResolver())); + .getSettingsOneHandedModeTimeout( + mContext.getContentResolver(), mUserId)); } } }; @@ -247,12 +251,13 @@ public class OneHandedController implements RemoteCallable R.fraction.config_one_handed_offset, 1, 1); final int sysPropPercentageConfig = SystemProperties.getInt( ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f)); + mUserId = myUserId(); mOffSetFraction = sysPropPercentageConfig / 100.0f; mIsOneHandedEnabled = mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( - context.getContentResolver()); + context.getContentResolver(), mUserId); mIsSwipeToNotificationEnabled = mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( - context.getContentResolver()); + context.getContentResolver(), mUserId); mTimeoutHandler = timeoutHandler; mEnabledObserver = getObserver(this::onEnabledSettingChanged); @@ -262,9 +267,8 @@ public class OneHandedController implements RemoteCallable getObserver(this::onSwipeToNotificationEnabledSettingChanged); mDisplayController.addDisplayChangingController(mRotationController); - setupCallback(); - setupSettingObservers(); + registerSettingObservers(mUserId); setupTimeoutListener(); setupGesturalOverlay(); updateSettings(); @@ -379,27 +383,38 @@ public class OneHandedController implements RemoteCallable } } - private void setupSettingObservers() { + private void registerSettingObservers(int newUserId) { mOneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED, - mContext.getContentResolver(), mEnabledObserver); + mContext.getContentResolver(), mEnabledObserver, newUserId); mOneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT, - mContext.getContentResolver(), mTimeoutObserver); + mContext.getContentResolver(), mTimeoutObserver, newUserId); mOneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT, - mContext.getContentResolver(), mTaskChangeExitObserver); + mContext.getContentResolver(), mTaskChangeExitObserver, newUserId); mOneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, - mContext.getContentResolver(), mSwipeToNotificationEnabledObserver); + mContext.getContentResolver(), mSwipeToNotificationEnabledObserver, newUserId); + } + + private void unregisterSettingObservers() { + mOneHandedSettingsUtil.unregisterSettingsKeyObserver(mContext.getContentResolver(), + mEnabledObserver); + mOneHandedSettingsUtil.unregisterSettingsKeyObserver(mContext.getContentResolver(), + mTimeoutObserver); + mOneHandedSettingsUtil.unregisterSettingsKeyObserver(mContext.getContentResolver(), + mTaskChangeExitObserver); + mOneHandedSettingsUtil.unregisterSettingsKeyObserver(mContext.getContentResolver(), + mSwipeToNotificationEnabledObserver); } private void updateSettings() { setOneHandedEnabled(mOneHandedSettingsUtil - .getSettingsOneHandedModeEnabled(mContext.getContentResolver())); + .getSettingsOneHandedModeEnabled(mContext.getContentResolver(), mUserId)); mTimeoutHandler.setTimeout(mOneHandedSettingsUtil - .getSettingsOneHandedModeTimeout(mContext.getContentResolver())); + .getSettingsOneHandedModeTimeout(mContext.getContentResolver(), mUserId)); setTaskChangeToExit(mOneHandedSettingsUtil - .getSettingsTapsAppToExit(mContext.getContentResolver())); + .getSettingsTapsAppToExit(mContext.getContentResolver(), mUserId)); setSwipeToNotificationEnabled(mOneHandedSettingsUtil - .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver())); + .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver(), mUserId)); } private void updateDisplayLayout(int displayId) { @@ -420,7 +435,7 @@ public class OneHandedController implements RemoteCallable @VisibleForTesting void onEnabledSettingChanged() { final boolean enabled = mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( - mContext.getContentResolver()); + mContext.getContentResolver(), mUserId); mOneHandedUiEventLogger.writeEvent(enabled ? OneHandedUiEventLogger.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON : OneHandedUiEventLogger.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF); @@ -430,13 +445,13 @@ public class OneHandedController implements RemoteCallable // Also checks swipe to notification settings since they all need gesture overlay. setEnabledGesturalOverlay( enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( - mContext.getContentResolver())); + mContext.getContentResolver(), mUserId)); } @VisibleForTesting void onTimeoutSettingChanged() { final int newTimeout = mOneHandedSettingsUtil.getSettingsOneHandedModeTimeout( - mContext.getContentResolver()); + mContext.getContentResolver(), mUserId); int metricsId = OneHandedUiEventLogger.OneHandedSettingsTogglesEvent.INVALID.getId(); switch (newTimeout) { case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER: @@ -465,7 +480,7 @@ public class OneHandedController implements RemoteCallable @VisibleForTesting void onTaskChangeExitSettingChanged() { final boolean enabled = mOneHandedSettingsUtil.getSettingsTapsAppToExit( - mContext.getContentResolver()); + mContext.getContentResolver(), mUserId); mOneHandedUiEventLogger.writeEvent(enabled ? OneHandedUiEventLogger.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON : OneHandedUiEventLogger.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF); @@ -477,13 +492,13 @@ public class OneHandedController implements RemoteCallable void onSwipeToNotificationEnabledSettingChanged() { final boolean enabled = mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( - mContext.getContentResolver()); + mContext.getContentResolver(), mUserId); setSwipeToNotificationEnabled(enabled); // Also checks one handed mode settings since they all need gesture overlay. setEnabledGesturalOverlay( enabled || mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( - mContext.getContentResolver())); + mContext.getContentResolver(), mUserId)); } private void setupTimeoutListener() { @@ -524,7 +539,7 @@ public class OneHandedController implements RemoteCallable private void setupGesturalOverlay() { if (!mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( - mContext.getContentResolver())) { + mContext.getContentResolver(), mUserId)) { return; } @@ -572,6 +587,14 @@ public class OneHandedController implements RemoteCallable } } + private void onUserSwitch(int newUserId) { + unregisterSettingObservers(); + mUserId = newUserId; + registerSettingObservers(newUserId); + updateSettings(); + updateOneHandedEnabled(); + } + public void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; pw.println(TAG + "States: "); @@ -579,6 +602,8 @@ public class OneHandedController implements RemoteCallable pw.println(mOffSetFraction); pw.print(innerPrefix + "mLockedDisabled="); pw.println(mLockedDisabled); + pw.print(innerPrefix + "mUserId="); + pw.println(mUserId); if (mBackgroundPanelOrganizer != null) { mBackgroundPanelOrganizer.dump(pw); @@ -604,7 +629,7 @@ public class OneHandedController implements RemoteCallable mTutorialHandler.dump(pw); } - mOneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver()); + mOneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver(), mUserId); if (mOverlayManager != null) { OverlayInfo info = null; @@ -703,6 +728,13 @@ public class OneHandedController implements RemoteCallable OneHandedController.this.onConfigChanged(newConfig); }); } + + @Override + public void onUserSwitch(int userId) { + mMainExecutor.execute(() -> { + OneHandedController.this.onUserSwitch(userId); + }); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java index fa94ec5578830..1b2fcdd6313e6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java @@ -22,6 +22,8 @@ import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; +import androidx.annotation.Nullable; + import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -62,17 +64,19 @@ public final class OneHandedSettingsUtil { /** * Register one handed preference settings observer * - * @param key Setting key to monitor in observer - * @param resolver ContentResolver of context - * @param observer Observer from caller + * @param key Setting key to monitor in observer + * @param resolver ContentResolver of context + * @param observer Observer from caller + * @param newUserId New user id to be registered * @return uri key for observing */ + @Nullable public Uri registerSettingsKeyObserver(String key, ContentResolver resolver, - ContentObserver observer) { + ContentObserver observer, int newUserId) { Uri uriKey = null; uriKey = Settings.Secure.getUriFor(key); if (resolver != null && uriKey != null) { - resolver.registerContentObserver(uriKey, false, observer); + resolver.registerContentObserver(uriKey, false, observer, newUserId); } return uriKey; } @@ -80,8 +84,8 @@ public final class OneHandedSettingsUtil { /** * Unregister one handed preference settings observer * - * @param resolver ContentResolver of context - * @param observer preference key change observer + * @param resolver ContentResolver of context + * @param observer preference key change observer */ public void unregisterSettingsKeyObserver(ContentResolver resolver, ContentObserver observer) { @@ -95,9 +99,9 @@ public final class OneHandedSettingsUtil { * * @return enable or disable one handed mode flag. */ - public boolean getSettingsOneHandedModeEnabled(ContentResolver resolver) { - return Settings.Secure.getInt(resolver, - Settings.Secure.ONE_HANDED_MODE_ENABLED, 0 /* Disabled */) == 1; + public boolean getSettingsOneHandedModeEnabled(ContentResolver resolver, int userId) { + return Settings.Secure.getIntForUser(resolver, + Settings.Secure.ONE_HANDED_MODE_ENABLED, 0 /* Disabled */, userId) == 1; } /** @@ -105,40 +109,44 @@ public final class OneHandedSettingsUtil { * * @return enable or disable taps app exit. */ - public boolean getSettingsTapsAppToExit(ContentResolver resolver) { - return Settings.Secure.getInt(resolver, - Settings.Secure.TAPS_APP_TO_EXIT, 0) == 1; + public boolean getSettingsTapsAppToExit(ContentResolver resolver, int userId) { + return Settings.Secure.getIntForUser(resolver, + Settings.Secure.TAPS_APP_TO_EXIT, 0, userId) == 1; } /** - * Query timeout value from Settings provider. - * Default is {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS} + * Query timeout value from Settings provider. Default is + * {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS} * * @return timeout value in seconds. */ - public @OneHandedTimeout int getSettingsOneHandedModeTimeout(ContentResolver resolver) { - return Settings.Secure.getInt(resolver, - Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS); + public @OneHandedTimeout int getSettingsOneHandedModeTimeout(ContentResolver resolver, + int userId) { + return Settings.Secure.getIntForUser(resolver, + Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS, + userId); } /** * Returns whether swipe bottom to notification gesture enabled or not. */ - public boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver) { + public boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver, int userId) { return Settings.Secure.getInt(resolver, Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0 /* Default OFF */) == 1; } - void dump(PrintWriter pw, String prefix, ContentResolver resolver) { + void dump(PrintWriter pw, String prefix, ContentResolver resolver, + int userId) { final String innerPrefix = prefix + " "; - pw.println(prefix + TAG); + pw.println(innerPrefix + TAG); pw.print(innerPrefix + "isOneHandedModeEnable="); - pw.println(getSettingsOneHandedModeEnabled(resolver)); + pw.println(getSettingsOneHandedModeEnabled(resolver, userId)); pw.print(innerPrefix + "oneHandedTimeOut="); - pw.println(getSettingsOneHandedModeTimeout(resolver)); + pw.println(getSettingsOneHandedModeTimeout(resolver, userId)); pw.print(innerPrefix + "tapsAppToExit="); - pw.println(getSettingsTapsAppToExit(resolver)); + pw.println(getSettingsTapsAppToExit(resolver, userId)); } + public OneHandedSettingsUtil() { } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index b0fc4c14a6bfc..e309f9659338d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.when; import android.content.om.IOverlayManager; import android.graphics.Rect; import android.os.Handler; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.util.ArrayMap; import android.view.Display; @@ -53,6 +54,8 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) public class OneHandedControllerTest extends OneHandedTestCase { + private int mCurrentUser = UserHandle.myUserId(); + Display mDisplay; DisplayLayout mDisplayLayout; OneHandedController mSpiedOneHandedController; @@ -100,13 +103,13 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false); when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>()); when(mMockBackgroundOrganizer.getBackgroundSurface()).thenReturn(mMockLeash); - when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any())).thenReturn( + when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn( mDefaultEnabled); - when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any())).thenReturn( + when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any(), anyInt())).thenReturn( OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS); - when(mMockSettingsUitl.getSettingsTapsAppToExit(any())).thenReturn( + when(mMockSettingsUitl.getSettingsTapsAppToExit(any(), anyInt())).thenReturn( mDefaultTapAppToExitEnabled); - when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any())).thenReturn( + when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn( mDefaultSwipeToNotificationEnabled); when(mMockDisplayAreaOrganizer.getLastDisplayBounds()).thenReturn( diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 4eb75ebe4553f..74b79d57adcb0 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -296,6 +296,11 @@ public final class WMShell extends SystemUI } oneHanded.stopOneHanded(); } + + @Override + public void onUserSwitchComplete(int userId) { + oneHanded.onUserSwitch(userId); + } }; mKeyguardUpdateMonitor.registerCallback(mOneHandedKeyguardCallback);