Loading services/core/java/com/android/server/wm/WindowManagerService.java +42 −27 Original line number Diff line number Diff line Loading @@ -3844,8 +3844,9 @@ public class WindowManagerService extends IWindowManager.Stub * * If {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} is set to true, then * only the display represented by the {@code displayId} parameter will be requested to switch * the touch mode state. Otherwise all all displays will be requested to switch their touch mode * state (disregarding {@code displayId} parameter). * the touch mode state. Otherwise all displays that do not maintain their own focus and touch * mode will be requested to switch their touch mode state (disregarding {@code displayId} * parameter). * * To be able to change touch mode state, the caller must either own the focused window, or must * have the {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE} permission. Instrumented Loading @@ -3857,27 +3858,9 @@ public class WindowManagerService extends IWindowManager.Stub */ @Override // Binder call public void setInTouchMode(boolean inTouch, int displayId) { boolean perDisplayFocusEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_perDisplayFocusEnabled); setInTouchMode(inTouch, displayId, perDisplayFocusEnabled); } /** * Sets the touch mode state on all displays (disregarding the value of * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled}). * * @param inTouch the touch mode to set */ @Override // Binder call public void setInTouchModeOnAllDisplays(boolean inTouch) { setInTouchMode(inTouch, /* any display id */ DEFAULT_DISPLAY, /* perDisplayFocusEnabled= */ false); } private void setInTouchMode(boolean inTouch, int displayId, boolean perDisplayFocusEnabled) { synchronized (mGlobalLock) { final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (perDisplayFocusEnabled && (displayContent == null if (mPerDisplayFocusEnabled && (displayContent == null || displayContent.isInTouchMode() == inTouch)) { return; } Loading @@ -3888,15 +3871,12 @@ public class WindowManagerService extends IWindowManager.Stub } final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final boolean hasPermission = mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()", /* printlog= */ false); final boolean hasPermission = hasTouchModePermission(pid); final long token = Binder.clearCallingIdentity(); try { // If perDisplayFocusEnabled is set or the display maintains its own touch mode, // If mPerDisplayFocusEnabled is set or the display maintains its own touch mode, // then just update the display pointed by displayId if (perDisplayFocusEnabled || displayHasOwnTouchMode) { if (mPerDisplayFocusEnabled || displayHasOwnTouchMode) { if (mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, displayId)) { displayContent.setInTouchMode(inTouch); } Loading @@ -3919,6 +3899,41 @@ public class WindowManagerService extends IWindowManager.Stub } } /** * Sets the touch mode state forcibly on all displays (disregarding both the value of * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} and whether the display * maintains its own focus and touch mode). * * @param inTouch the touch mode to set */ @Override // Binder call public void setInTouchModeOnAllDisplays(boolean inTouch) { final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final boolean hasPermission = hasTouchModePermission(pid); final long token = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { for (int i = 0; i < mRoot.mChildren.size(); ++i) { DisplayContent dc = mRoot.mChildren.get(i); if (dc.isInTouchMode() != inTouch && mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, dc.mDisplayId)) { dc.setInTouchMode(inTouch); } } } } finally { Binder.restoreCallingIdentity(token); } } private boolean hasTouchModePermission(int pid) { return mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()", /* printlog= */ false); } /** * Returns the touch mode state for the display id passed as argument. */ Loading services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +45 −0 Original line number Diff line number Diff line Loading @@ -500,6 +500,51 @@ public class WindowManagerServiceTests extends WindowTestsBase { virtualDisplay.getDisplay().getDisplayId()); } @Test public void testSetInTouchModeOnAllDisplays_perDisplayFocusDisabled() { testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ false); } @Test public void testSetInTouchModeOnAllDisplays_perDisplayFocusEnabled() { testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ true); } private void testSetInTouchModeOnAllDisplays(boolean perDisplayFocusEnabled) { // Create a couple of extra displays. // setInTouchModeOnAllDisplays should ignore the ownFocus setting. final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false); final VirtualDisplay virtualDisplayOwnFocus = createVirtualDisplay(/* ownFocus= */ true); // Enable or disable global touch mode (config_perDisplayFocusEnabled setting). // setInTouchModeOnAllDisplays should ignore this value. Resources mockResources = mock(Resources.class); spyOn(mContext); when(mContext.getResources()).thenReturn(mockResources); doReturn(perDisplayFocusEnabled).when(mockResources).getBoolean( com.android.internal.R.bool.config_perDisplayFocusEnabled); int callingPid = Binder.getCallingPid(); int callingUid = Binder.getCallingUid(); doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString(), anyBoolean()); when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid, android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true); for (boolean inTouchMode : new boolean[]{true, false}) { mWm.setInTouchModeOnAllDisplays(inTouchMode); for (int i = 0; i < mWm.mRoot.mChildren.size(); ++i) { DisplayContent dc = mWm.mRoot.mChildren.get(i); // All displays that are not already in the desired touch mode are requested to // change their touch mode. if (dc.isInTouchMode() != inTouchMode) { verify(mWm.mInputManager).setInTouchMode( true, callingPid, callingUid, /* hasPermission= */ true, dc.getDisplay().getDisplayId()); } } } } private VirtualDisplay createVirtualDisplay(boolean ownFocus) { // Create virtual display Point surfaceSize = new Point( Loading Loading
services/core/java/com/android/server/wm/WindowManagerService.java +42 −27 Original line number Diff line number Diff line Loading @@ -3844,8 +3844,9 @@ public class WindowManagerService extends IWindowManager.Stub * * If {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} is set to true, then * only the display represented by the {@code displayId} parameter will be requested to switch * the touch mode state. Otherwise all all displays will be requested to switch their touch mode * state (disregarding {@code displayId} parameter). * the touch mode state. Otherwise all displays that do not maintain their own focus and touch * mode will be requested to switch their touch mode state (disregarding {@code displayId} * parameter). * * To be able to change touch mode state, the caller must either own the focused window, or must * have the {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE} permission. Instrumented Loading @@ -3857,27 +3858,9 @@ public class WindowManagerService extends IWindowManager.Stub */ @Override // Binder call public void setInTouchMode(boolean inTouch, int displayId) { boolean perDisplayFocusEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_perDisplayFocusEnabled); setInTouchMode(inTouch, displayId, perDisplayFocusEnabled); } /** * Sets the touch mode state on all displays (disregarding the value of * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled}). * * @param inTouch the touch mode to set */ @Override // Binder call public void setInTouchModeOnAllDisplays(boolean inTouch) { setInTouchMode(inTouch, /* any display id */ DEFAULT_DISPLAY, /* perDisplayFocusEnabled= */ false); } private void setInTouchMode(boolean inTouch, int displayId, boolean perDisplayFocusEnabled) { synchronized (mGlobalLock) { final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (perDisplayFocusEnabled && (displayContent == null if (mPerDisplayFocusEnabled && (displayContent == null || displayContent.isInTouchMode() == inTouch)) { return; } Loading @@ -3888,15 +3871,12 @@ public class WindowManagerService extends IWindowManager.Stub } final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final boolean hasPermission = mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()", /* printlog= */ false); final boolean hasPermission = hasTouchModePermission(pid); final long token = Binder.clearCallingIdentity(); try { // If perDisplayFocusEnabled is set or the display maintains its own touch mode, // If mPerDisplayFocusEnabled is set or the display maintains its own touch mode, // then just update the display pointed by displayId if (perDisplayFocusEnabled || displayHasOwnTouchMode) { if (mPerDisplayFocusEnabled || displayHasOwnTouchMode) { if (mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, displayId)) { displayContent.setInTouchMode(inTouch); } Loading @@ -3919,6 +3899,41 @@ public class WindowManagerService extends IWindowManager.Stub } } /** * Sets the touch mode state forcibly on all displays (disregarding both the value of * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} and whether the display * maintains its own focus and touch mode). * * @param inTouch the touch mode to set */ @Override // Binder call public void setInTouchModeOnAllDisplays(boolean inTouch) { final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final boolean hasPermission = hasTouchModePermission(pid); final long token = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { for (int i = 0; i < mRoot.mChildren.size(); ++i) { DisplayContent dc = mRoot.mChildren.get(i); if (dc.isInTouchMode() != inTouch && mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, dc.mDisplayId)) { dc.setInTouchMode(inTouch); } } } } finally { Binder.restoreCallingIdentity(token); } } private boolean hasTouchModePermission(int pid) { return mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()", /* printlog= */ false); } /** * Returns the touch mode state for the display id passed as argument. */ Loading
services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +45 −0 Original line number Diff line number Diff line Loading @@ -500,6 +500,51 @@ public class WindowManagerServiceTests extends WindowTestsBase { virtualDisplay.getDisplay().getDisplayId()); } @Test public void testSetInTouchModeOnAllDisplays_perDisplayFocusDisabled() { testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ false); } @Test public void testSetInTouchModeOnAllDisplays_perDisplayFocusEnabled() { testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ true); } private void testSetInTouchModeOnAllDisplays(boolean perDisplayFocusEnabled) { // Create a couple of extra displays. // setInTouchModeOnAllDisplays should ignore the ownFocus setting. final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false); final VirtualDisplay virtualDisplayOwnFocus = createVirtualDisplay(/* ownFocus= */ true); // Enable or disable global touch mode (config_perDisplayFocusEnabled setting). // setInTouchModeOnAllDisplays should ignore this value. Resources mockResources = mock(Resources.class); spyOn(mContext); when(mContext.getResources()).thenReturn(mockResources); doReturn(perDisplayFocusEnabled).when(mockResources).getBoolean( com.android.internal.R.bool.config_perDisplayFocusEnabled); int callingPid = Binder.getCallingPid(); int callingUid = Binder.getCallingUid(); doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString(), anyBoolean()); when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid, android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true); for (boolean inTouchMode : new boolean[]{true, false}) { mWm.setInTouchModeOnAllDisplays(inTouchMode); for (int i = 0; i < mWm.mRoot.mChildren.size(); ++i) { DisplayContent dc = mWm.mRoot.mChildren.get(i); // All displays that are not already in the desired touch mode are requested to // change their touch mode. if (dc.isInTouchMode() != inTouchMode) { verify(mWm.mInputManager).setInTouchMode( true, callingPid, callingUid, /* hasPermission= */ true, dc.getDisplay().getDisplayId()); } } } } private VirtualDisplay createVirtualDisplay(boolean ownFocus) { // Create virtual display Point surfaceSize = new Point( Loading