1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; 20 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW; 21 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; 22 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; 23 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH; 24 25 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 26 27 import static org.junit.Assert.assertEquals; 28 import static org.junit.Assert.assertTrue; 29 import static org.mockito.Mockito.atLeastOnce; 30 import static org.mockito.Mockito.clearInvocations; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 35 import android.content.ContentResolver; 36 import android.net.Uri; 37 import android.platform.test.annotations.Presubmit; 38 import android.provider.Settings; 39 40 import androidx.test.filters.SmallTest; 41 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.mockito.ArgumentCaptor; 45 46 import java.util.List; 47 48 /** 49 * Test for {@link WindowManagerService.SettingsObserver}. 50 * 51 * Build/Install/Run: 52 * atest WmTests:WindowManagerSettingsTests 53 */ 54 @Presubmit 55 @SmallTest 56 @RunWith(WindowTestRunner.class) 57 public class WindowManagerSettingsTests extends WindowTestsBase { 58 59 @Test testForceDesktopModeOnExternalDisplays()60 public void testForceDesktopModeOnExternalDisplays() { 61 try (BoolSettingsSession forceDesktopModeSession = new 62 BoolSettingsSession(DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS)) { 63 final boolean forceDesktopMode = !forceDesktopModeSession.getSetting(); 64 final Uri forceDesktopModeUri = forceDesktopModeSession.setSetting(forceDesktopMode); 65 mWm.mSettingsObserver.onChange(false, forceDesktopModeUri); 66 67 assertEquals(mWm.mForceDesktopModeOnExternalDisplays, forceDesktopMode); 68 } 69 } 70 71 @Test testFreeformWindow()72 public void testFreeformWindow() { 73 try (BoolSettingsSession freeformWindowSession = new 74 BoolSettingsSession(DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT)) { 75 final boolean curFreeformWindow = freeformWindowSession.getSetting(); 76 final boolean newFreeformWindow = !curFreeformWindow; 77 final Uri freeformWindowUri = freeformWindowSession.setSetting(newFreeformWindow); 78 mWm.mAtmService.mSupportsFreeformWindowManagement = curFreeformWindow; 79 mWm.mSettingsObserver.onChange(false, freeformWindowUri); 80 81 assertEquals(mWm.mAtmService.mSupportsFreeformWindowManagement, newFreeformWindow); 82 } 83 } 84 85 @Test testFreeformWindow_valueChanged_updatesDisplaySettings()86 public void testFreeformWindow_valueChanged_updatesDisplaySettings() { 87 try (BoolSettingsSession freeformWindowSession = new 88 BoolSettingsSession(DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT)) { 89 final boolean curFreeformWindow = freeformWindowSession.getSetting(); 90 final boolean newFreeformWindow = !curFreeformWindow; 91 final Uri freeformWindowUri = freeformWindowSession.setSetting(newFreeformWindow); 92 mWm.mAtmService.mSupportsFreeformWindowManagement = curFreeformWindow; 93 clearInvocations(mWm.mRoot); 94 mWm.mSettingsObserver.onChange(false, freeformWindowUri); 95 96 // Changed value should update display settings. 97 verify(mWm.mRoot).onSettingsRetrieved(); 98 99 clearInvocations(mWm.mRoot); 100 mWm.mSettingsObserver.onChange(false, freeformWindowUri); 101 102 // Unchanged value should not update display settings. 103 verify(mWm.mRoot, never()).onSettingsRetrieved(); 104 } 105 } 106 107 @Test testForceResizableMode()108 public void testForceResizableMode() { 109 try (BoolSettingsSession forceResizableSession = new 110 BoolSettingsSession(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES)) { 111 final boolean forceResizableMode = !forceResizableSession.getSetting(); 112 final Uri forceResizableUri = forceResizableSession.setSetting(forceResizableMode); 113 114 mWm.mSettingsObserver.onChange(false, forceResizableUri); 115 116 assertEquals(mWm.mAtmService.mForceResizableActivities, forceResizableMode); 117 } 118 } 119 120 @Test testSupportsNonResizableMultiWindow()121 public void testSupportsNonResizableMultiWindow() { 122 try (BoolSettingsSession supportsNonResizableMultiWindowSession = new 123 BoolSettingsSession(DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)) { 124 final boolean supportsNonResizableMultiWindow = 125 !supportsNonResizableMultiWindowSession.getSetting(); 126 final Uri supportsNonResizableMultiWindowUri = supportsNonResizableMultiWindowSession 127 .setSetting(supportsNonResizableMultiWindow); 128 mWm.mSettingsObserver.onChange(false, supportsNonResizableMultiWindowUri); 129 130 assertEquals(mWm.mAtmService.mDevEnableNonResizableMultiWindow, 131 supportsNonResizableMultiWindow); 132 } 133 } 134 135 @Test testChangeBaseDisplaySettingsPath()136 public void testChangeBaseDisplaySettingsPath() { 137 try (StringSettingsSession baseDisplaySettingsPathSession = new 138 StringSettingsSession(DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH)) { 139 final String path = baseDisplaySettingsPathSession.getSetting() + "-test"; 140 final Uri baseDisplaySettingsPathUri = baseDisplaySettingsPathSession.setSetting(path); 141 142 clearInvocations(mWm.mRoot); 143 clearInvocations(mWm.mDisplayWindowSettings); 144 clearInvocations(mWm.mDisplayWindowSettingsProvider); 145 146 mWm.mSettingsObserver.onChange(false /* selfChange */, baseDisplaySettingsPathUri); 147 148 ArgumentCaptor<String> pathCaptor = ArgumentCaptor.forClass(String.class); 149 verify(mWm.mDisplayWindowSettingsProvider).setBaseSettingsFilePath( 150 pathCaptor.capture()); 151 assertEquals(path, pathCaptor.getValue()); 152 153 ArgumentCaptor<DisplayContent> captor = 154 ArgumentCaptor.forClass(DisplayContent.class); 155 verify(mWm.mDisplayWindowSettings, times(mWm.mRoot.mChildren.size())) 156 .applySettingsToDisplayLocked(captor.capture()); 157 List<DisplayContent> configuredDisplays = captor.getAllValues(); 158 for (DisplayContent dc : mWm.mRoot.mChildren) { 159 assertTrue(configuredDisplays.contains(dc)); 160 } 161 162 verify(mWm.mRoot, atLeastOnce()).performSurfacePlacement(); 163 } 164 } 165 166 private class BoolSettingsSession implements AutoCloseable { 167 168 private static final int SETTING_VALUE_OFF = 0; 169 private static final int SETTING_VALUE_ON = 1; 170 private final String mSettingName; 171 private final int mInitialValue; 172 BoolSettingsSession(String name)173 BoolSettingsSession(String name) { 174 mSettingName = name; 175 mInitialValue = getSetting() ? SETTING_VALUE_ON : SETTING_VALUE_OFF; 176 } 177 getSetting()178 boolean getSetting() { 179 return Settings.Global.getInt(getContentResolver(), mSettingName, 0) != 0; 180 } 181 setSetting(boolean enable)182 Uri setSetting(boolean enable) { 183 Settings.Global.putInt(getContentResolver(), mSettingName, 184 enable ? SETTING_VALUE_ON : SETTING_VALUE_OFF); 185 return Settings.Global.getUriFor(mSettingName); 186 } 187 getContentResolver()188 private ContentResolver getContentResolver() { 189 return getInstrumentation().getTargetContext().getContentResolver(); 190 } 191 192 @Override close()193 public void close() { 194 setSetting(mInitialValue == SETTING_VALUE_ON); 195 } 196 } 197 198 private class StringSettingsSession implements AutoCloseable { 199 private final String mSettingName; 200 private final String mInitialValue; 201 StringSettingsSession(String name)202 StringSettingsSession(String name) { 203 mSettingName = name; 204 mInitialValue = getSetting(); 205 } 206 getSetting()207 String getSetting() { 208 return Settings.Global.getString(getContentResolver(), mSettingName); 209 } 210 setSetting(String value)211 Uri setSetting(String value) { 212 Settings.Global.putString(getContentResolver(), mSettingName, value); 213 return Settings.Global.getUriFor(mSettingName); 214 } 215 getContentResolver()216 private ContentResolver getContentResolver() { 217 return getInstrumentation().getTargetContext().getContentResolver(); 218 } 219 220 @Override close()221 public void close() { 222 setSetting(mInitialValue); 223 } 224 } 225 } 226