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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user