summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Chang <chengjeff@google.com> 2019-07-10 11:38:05 +0800
committer Jeff Chang <chengjeff@google.com> 2019-09-02 14:27:16 +0800
commit0c53e5e5680c2d5254a33d9ae4cd92f7062f96a8 (patch)
treed22061e3ce89cddee318872b4df303153e6046a6
parente303b217321aeaf519829b48f8754969b0e29e0d (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.java58
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java111
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);
+ }
+ }
+}