diff options
| author | 2019-07-10 11:38:05 +0800 | |
|---|---|---|
| committer | 2019-09-02 14:27:16 +0800 | |
| commit | 0c53e5e5680c2d5254a33d9ae4cd92f7062f96a8 (patch) | |
| tree | d22061e3ce89cddee318872b4df303153e6046a6 | |
| parent | e303b217321aeaf519829b48f8754969b0e29e0d (diff) | |
Add observer for WindowManager developer options
Some WM-related developer options write a setting entry, which is
initialized only at system boot. We need to reboot after the setting
chanaged. The CL register an observer to "Enable freeform windows",
"Force desktop mode" and "Force resizable activities". It will take
effect after setting changed without reboot.
Bug: 129279411
Test: A. atest WmTests:WindowManagerSettingsTests
B. Manual test.
1. Enable "Force desktop mode",Freefome window","Force resizable activities" from
developer option.
2. connect mouse (USB or Bluetooth).
3. Create simulated display from developer options.
4. Launch activities from launcher on simulated display and interact with mouse.
Change-Id: I7b5e15f548de5c2f163a1816020fe46756968f5e
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 58 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java | 111 |
2 files changed, 168 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d49d24545666..fa1ace630856 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -28,6 +28,7 @@ import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LE import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; import static android.app.StatusBarManager.DISABLE_MASK; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; +import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; import static android.content.pm.PackageManager.FEATURE_PC; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Process.SYSTEM_UID; @@ -36,7 +37,9 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE; import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP; import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS; +import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; +import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.DOCKED_INVALID; @@ -666,7 +669,8 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; SettingsObserver mSettingsObserver; - private final class SettingsObserver extends ContentObserver { + @VisibleForTesting + final class SettingsObserver extends ContentObserver { private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); private final Uri mWindowAnimationScaleUri = @@ -681,6 +685,12 @@ public class WindowManagerService extends IWindowManager.Stub Settings.Global.getUriFor(Settings.Global.POLICY_CONTROL); private final Uri mPointerLocationUri = Settings.System.getUriFor(Settings.System.POINTER_LOCATION); + private final Uri mForceDesktopModeOnExternalDisplaysUri = Settings.Global.getUriFor( + Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS); + private final Uri mFreeformWindowUri = Settings.Global.getUriFor( + Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT); + private final Uri mForceResizableUri = Settings.Global.getUriFor( + DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); public SettingsObserver() { super(new Handler()); @@ -697,6 +707,10 @@ public class WindowManagerService extends IWindowManager.Stub UserHandle.USER_ALL); resolver.registerContentObserver(mPolicyControlUri, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(mPointerLocationUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mForceDesktopModeOnExternalDisplaysUri, false, this, + UserHandle.USER_ALL); + resolver.registerContentObserver(mFreeformWindowUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL); } @Override @@ -720,6 +734,21 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (mForceDesktopModeOnExternalDisplaysUri.equals(uri)) { + updateForceDesktopModeOnExternalDisplays(); + return; + } + + if (mFreeformWindowUri.equals(uri)) { + updateFreeformWindowManagement(); + return; + } + + if (mForceResizableUri.equals(uri)) { + updateForceResizableTasks(); + return; + } + @UpdateAnimationScaleMode final int mode; if (mWindowAnimationScaleUri.equals(uri)) { @@ -762,6 +791,33 @@ public class WindowManagerService extends IWindowManager.Stub mPointerLocationEnabled)); } } + + void updateForceDesktopModeOnExternalDisplays() { + ContentResolver resolver = mContext.getContentResolver(); + final boolean enableForceDesktopMode = Settings.Global.getInt(resolver, + DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0; + if (mForceDesktopModeOnExternalDisplays == enableForceDesktopMode) { + return; + } + setForceDesktopModeOnExternalDisplays(enableForceDesktopMode); + } + + void updateFreeformWindowManagement() { + ContentResolver resolver = mContext.getContentResolver(); + final boolean freeformWindowManagement = mContext.getPackageManager().hasSystemFeature( + FEATURE_FREEFORM_WINDOW_MANAGEMENT) || Settings.Global.getInt( + resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0; + + mAtmService.mSupportsFreeformWindowManagement = freeformWindowManagement; + } + + void updateForceResizableTasks() { + ContentResolver resolver = mContext.getContentResolver(); + final boolean forceResizable = Settings.Global.getInt(resolver, + DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0; + + mAtmService.mForceResizableActivities = forceResizable; + } } PowerManager mPowerManager; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java new file mode 100644 index 000000000000..86f0f8bc1bb9 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; +import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; +import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.junit.Assert.assertEquals; + +import android.content.ContentResolver; +import android.net.Uri; +import android.provider.Settings; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +/** + * Test for {@link WindowManagerService.SettingsObserver}. + * + * Build/Install/Run: + * atest WmTests:WindowManagerSettingsTests + */ +@SmallTest +public class WindowManagerSettingsTests extends WindowTestsBase { + + @Test + public void testForceDesktopModeOnExternalDisplays() { + try (SettingsSession forceDesktopModeSession = new + SettingsSession(DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS)) { + final boolean forceDesktopMode = !forceDesktopModeSession.getSetting(); + final Uri forceDesktopModeUri = forceDesktopModeSession.setSetting(forceDesktopMode); + mWm.mSettingsObserver.onChange(false, forceDesktopModeUri); + + assertEquals(mWm.mForceDesktopModeOnExternalDisplays, forceDesktopMode); + } + } + + @Test + public void testFreeformWindow() { + try (SettingsSession freeformWindowSession = new + SettingsSession(DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT)) { + final boolean freeformWindow = !freeformWindowSession.getSetting(); + final Uri freeformWindowUri = freeformWindowSession.setSetting(freeformWindow); + mWm.mSettingsObserver.onChange(false, freeformWindowUri); + + assertEquals(mWm.mAtmService.mSupportsFreeformWindowManagement, freeformWindow); + } + } + + @Test + public void testForceResizableMode() { + try (SettingsSession forceResizableSession = new + SettingsSession(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES)) { + final boolean forceResizableMode = !forceResizableSession.getSetting(); + final Uri forceResizableUri = forceResizableSession.setSetting(forceResizableMode); + mWm.mSettingsObserver.onChange(false, forceResizableUri); + + assertEquals(mWm.mAtmService.mForceResizableActivities, forceResizableMode); + } + } + + private class SettingsSession implements AutoCloseable { + + private static final int SETTING_VALUE_OFF = 0; + private static final int SETTING_VALUE_ON = 1; + private final String mSettingName; + private final int mInitialValue; + + SettingsSession(String name) { + mSettingName = name; + mInitialValue = getSetting() ? SETTING_VALUE_ON : SETTING_VALUE_OFF; + } + + boolean getSetting() { + return Settings.Global.getInt(getContentResolver(), mSettingName, 0) != 0; + } + + Uri setSetting(boolean enable) { + Settings.Global.putInt(getContentResolver(), mSettingName, + enable ? SETTING_VALUE_ON : SETTING_VALUE_OFF); + return Settings.Global.getUriFor(mSettingName); + } + + private ContentResolver getContentResolver() { + return getInstrumentation().getTargetContext().getContentResolver(); + } + + @Override + public void close() { + setSetting(mInitialValue == SETTING_VALUE_ON); + } + } +} |