Merge "1/ Make One handed mode support multiple user switch" into sc-dev
This commit is contained in:
@@ -89,4 +89,9 @@ public interface OneHanded {
|
||||
* Receive onConfigurationChanged() events
|
||||
*/
|
||||
void onConfigChanged(Configuration newConfig);
|
||||
|
||||
/**
|
||||
* Notifies when user switch complete
|
||||
*/
|
||||
void onUserSwitch(int userId);
|
||||
}
|
||||
|
||||
@@ -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<OneHandedController>
|
||||
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<OneHandedController>
|
||||
}
|
||||
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<OneHandedController>
|
||||
mTimeoutHandler.setTimeout(timeout / 1000);
|
||||
} else {
|
||||
mTimeoutHandler.setTimeout(mOneHandedSettingsUtil
|
||||
.getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
|
||||
.getSettingsOneHandedModeTimeout(
|
||||
mContext.getContentResolver(), mUserId));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -247,12 +251,13 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
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<OneHandedController>
|
||||
getObserver(this::onSwipeToNotificationEnabledSettingChanged);
|
||||
|
||||
mDisplayController.addDisplayChangingController(mRotationController);
|
||||
|
||||
setupCallback();
|
||||
setupSettingObservers();
|
||||
registerSettingObservers(mUserId);
|
||||
setupTimeoutListener();
|
||||
setupGesturalOverlay();
|
||||
updateSettings();
|
||||
@@ -379,27 +383,38 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
}
|
||||
}
|
||||
|
||||
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<OneHandedController>
|
||||
@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<OneHandedController>
|
||||
// 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<OneHandedController>
|
||||
@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<OneHandedController>
|
||||
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<OneHandedController>
|
||||
|
||||
private void setupGesturalOverlay() {
|
||||
if (!mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
|
||||
mContext.getContentResolver())) {
|
||||
mContext.getContentResolver(), mUserId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -572,6 +587,14 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
}
|
||||
}
|
||||
|
||||
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<OneHandedController>
|
||||
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<OneHandedController>
|
||||
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>
|
||||
OneHandedController.this.onConfigChanged(newConfig);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserSwitch(int userId) {
|
||||
mMainExecutor.execute(() -> {
|
||||
OneHandedController.this.onUserSwitch(userId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -296,6 +296,11 @@ public final class WMShell extends SystemUI
|
||||
}
|
||||
oneHanded.stopOneHanded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserSwitchComplete(int userId) {
|
||||
oneHanded.onUserSwitch(userId);
|
||||
}
|
||||
};
|
||||
mKeyguardUpdateMonitor.registerCallback(mOneHandedKeyguardCallback);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user