Loading core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -861,6 +861,11 @@ The default is false. --> <bool name="config_lidControlsSleep">false</bool> <!-- Indicate whether closing the lid causes the device to enter the folded state which means to get a smaller screen and opening the lid causes the device to enter the unfolded state which means to get a larger screen. --> <bool name="config_lidControlsDisplayFold">false</bool> <!-- Desk dock behavior --> <!-- The number of degrees to rotate the display when the device is in a desk dock. Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3532,6 +3532,7 @@ <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" /> <java-symbol type="bool" name="config_lidControlsDisplayFold" /> <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> Loading services/core/java/com/android/server/display/LogicalDisplay.java +9 −4 Original line number Diff line number Diff line Loading @@ -418,10 +418,15 @@ final class LogicalDisplay { // Now add back the offset for the masked area. mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); mTempDisplayRect.left += mDisplayOffsetX; mTempDisplayRect.right += mDisplayOffsetX; mTempDisplayRect.top += mDisplayOffsetY; mTempDisplayRect.bottom += mDisplayOffsetY; if (orientation == Surface.ROTATION_0) { mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY); } else if (orientation == Surface.ROTATION_90) { mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX); } else if (orientation == Surface.ROTATION_180) { mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY); } else { // Surface.ROTATION_270 mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX); } device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); } Loading services/core/java/com/android/server/policy/DisplayFoldController.java 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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.policy; import android.content.Context; import android.graphics.Rect; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManagerInternal; import android.view.DisplayInfo; import com.android.server.LocalServices; import com.android.server.wm.WindowManagerInternal; /** * Controls the behavior of foldable devices whose screen can literally bend and fold. */ class DisplayFoldController { private static final String TAG = "DisplayFoldController"; private final WindowManagerInternal mWindowManagerInternal; private final DisplayManagerInternal mDisplayManagerInternal; private final int mDisplayId; /** The display area while device is folded. */ private final Rect mFoldedArea; private final DisplayInfo mNonOverrideDisplayInfo = new DisplayInfo(); private Boolean mFolded; DisplayFoldController(WindowManagerInternal windowManagerInternal, DisplayManagerInternal displayManagerInternal, int displayId, Rect foldedArea) { mWindowManagerInternal = windowManagerInternal; mDisplayManagerInternal = displayManagerInternal; mDisplayId = displayId; mFoldedArea = new Rect(foldedArea); } void setDeviceFolded(boolean folded) { if (mFolded != null && mFolded == folded) { return; } if (folded) { mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo); final int dx = (mNonOverrideDisplayInfo.logicalWidth - mFoldedArea.width()) / 2 - mFoldedArea.left; final int dy = (mNonOverrideDisplayInfo.logicalHeight - mFoldedArea.height()) / 2 - mFoldedArea.top; mWindowManagerInternal.setForcedDisplaySize(mDisplayId, mFoldedArea.width(), mFoldedArea.height()); mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy); } else { mWindowManagerInternal.clearForcedDisplaySize(mDisplayId); mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0); } mFolded = folded; } /** * Only used for the case that persist.debug.force_foldable is set. * This is using proximity sensor to simulate the fold state switch. */ static DisplayFoldController createWithProxSensor(Context context, int displayId) { final SensorManager sensorManager = context.getSystemService(SensorManager.class); final Sensor proxSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (proxSensor == null) { return null; } final DisplayFoldController result = create(displayId); sensorManager.registerListener(new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { result.setDeviceFolded(event.values[0] < 1f); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Ignore. } }, proxSensor, SensorManager.SENSOR_DELAY_NORMAL); return result; } static DisplayFoldController create(int displayId) { final DisplayManagerInternal displayService = LocalServices.getService(DisplayManagerInternal.class); final DisplayInfo displayInfo = new DisplayInfo(); displayService.getNonOverrideDisplayInfo(displayId, displayInfo); final Rect foldedArea = new Rect(0, displayInfo.logicalHeight / 2, displayInfo.logicalWidth, displayInfo.logicalHeight); return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class), displayService, displayId, foldedArea); } } services/core/java/com/android/server/policy/PhoneWindowManager.java +14 −1 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { SearchManager mSearchManager; AccessibilityManager mAccessibilityManager; BurnInProtectionHelper mBurnInProtectionHelper; private DisplayFoldController mDisplayFoldController; AppOpsManager mAppOpsManager; private ScreenshotHelper mScreenshotHelper; private boolean mHasFeatureWatch; Loading Loading @@ -471,6 +472,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidNavigationAccessibility; boolean mLidControlsScreenLock; boolean mLidControlsSleep; private boolean mLidControlsDisplayFold; int mShortPressOnPowerBehavior; int mLongPressOnPowerBehavior; int mVeryLongPressOnPowerBehavior; Loading Loading @@ -1794,6 +1796,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.bool.config_lidControlsScreenLock); mLidControlsSleep = mContext.getResources().getBoolean( com.android.internal.R.bool.config_lidControlsSleep); mLidControlsDisplayFold = mContext.getResources().getBoolean( com.android.internal.R.bool.config_lidControlsDisplayFold); mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); Loading Loading @@ -1850,6 +1854,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { readConfigurationDependentBehaviors(); if (mLidControlsDisplayFold) { mDisplayFoldController = DisplayFoldController.create(DEFAULT_DISPLAY); } else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) { mDisplayFoldController = DisplayFoldController.createWithProxSensor(context, DEFAULT_DISPLAY); } mAccessibilityManager = (AccessibilityManager) context.getSystemService( Context.ACCESSIBILITY_SERVICE); Loading Loading @@ -4972,7 +4983,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void applyLidSwitchState() { final int lidState = mDefaultDisplayPolicy.getLidState(); if (lidState == LID_CLOSED && mLidControlsSleep) { if (mLidControlsDisplayFold && mDisplayFoldController != null) { mDisplayFoldController.setDeviceFolded(lidState == LID_CLOSED); } else if (lidState == LID_CLOSED && mLidControlsSleep) { goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); } else if (lidState == LID_CLOSED && mLidControlsScreenLock) { Loading Loading
core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -861,6 +861,11 @@ The default is false. --> <bool name="config_lidControlsSleep">false</bool> <!-- Indicate whether closing the lid causes the device to enter the folded state which means to get a smaller screen and opening the lid causes the device to enter the unfolded state which means to get a larger screen. --> <bool name="config_lidControlsDisplayFold">false</bool> <!-- Desk dock behavior --> <!-- The number of degrees to rotate the display when the device is in a desk dock. Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3532,6 +3532,7 @@ <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" /> <java-symbol type="bool" name="config_lidControlsDisplayFold" /> <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> Loading
services/core/java/com/android/server/display/LogicalDisplay.java +9 −4 Original line number Diff line number Diff line Loading @@ -418,10 +418,15 @@ final class LogicalDisplay { // Now add back the offset for the masked area. mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); mTempDisplayRect.left += mDisplayOffsetX; mTempDisplayRect.right += mDisplayOffsetX; mTempDisplayRect.top += mDisplayOffsetY; mTempDisplayRect.bottom += mDisplayOffsetY; if (orientation == Surface.ROTATION_0) { mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY); } else if (orientation == Surface.ROTATION_90) { mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX); } else if (orientation == Surface.ROTATION_180) { mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY); } else { // Surface.ROTATION_270 mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX); } device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); } Loading
services/core/java/com/android/server/policy/DisplayFoldController.java 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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.policy; import android.content.Context; import android.graphics.Rect; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManagerInternal; import android.view.DisplayInfo; import com.android.server.LocalServices; import com.android.server.wm.WindowManagerInternal; /** * Controls the behavior of foldable devices whose screen can literally bend and fold. */ class DisplayFoldController { private static final String TAG = "DisplayFoldController"; private final WindowManagerInternal mWindowManagerInternal; private final DisplayManagerInternal mDisplayManagerInternal; private final int mDisplayId; /** The display area while device is folded. */ private final Rect mFoldedArea; private final DisplayInfo mNonOverrideDisplayInfo = new DisplayInfo(); private Boolean mFolded; DisplayFoldController(WindowManagerInternal windowManagerInternal, DisplayManagerInternal displayManagerInternal, int displayId, Rect foldedArea) { mWindowManagerInternal = windowManagerInternal; mDisplayManagerInternal = displayManagerInternal; mDisplayId = displayId; mFoldedArea = new Rect(foldedArea); } void setDeviceFolded(boolean folded) { if (mFolded != null && mFolded == folded) { return; } if (folded) { mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo); final int dx = (mNonOverrideDisplayInfo.logicalWidth - mFoldedArea.width()) / 2 - mFoldedArea.left; final int dy = (mNonOverrideDisplayInfo.logicalHeight - mFoldedArea.height()) / 2 - mFoldedArea.top; mWindowManagerInternal.setForcedDisplaySize(mDisplayId, mFoldedArea.width(), mFoldedArea.height()); mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy); } else { mWindowManagerInternal.clearForcedDisplaySize(mDisplayId); mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0); } mFolded = folded; } /** * Only used for the case that persist.debug.force_foldable is set. * This is using proximity sensor to simulate the fold state switch. */ static DisplayFoldController createWithProxSensor(Context context, int displayId) { final SensorManager sensorManager = context.getSystemService(SensorManager.class); final Sensor proxSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (proxSensor == null) { return null; } final DisplayFoldController result = create(displayId); sensorManager.registerListener(new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { result.setDeviceFolded(event.values[0] < 1f); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Ignore. } }, proxSensor, SensorManager.SENSOR_DELAY_NORMAL); return result; } static DisplayFoldController create(int displayId) { final DisplayManagerInternal displayService = LocalServices.getService(DisplayManagerInternal.class); final DisplayInfo displayInfo = new DisplayInfo(); displayService.getNonOverrideDisplayInfo(displayId, displayInfo); final Rect foldedArea = new Rect(0, displayInfo.logicalHeight / 2, displayInfo.logicalWidth, displayInfo.logicalHeight); return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class), displayService, displayId, foldedArea); } }
services/core/java/com/android/server/policy/PhoneWindowManager.java +14 −1 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { SearchManager mSearchManager; AccessibilityManager mAccessibilityManager; BurnInProtectionHelper mBurnInProtectionHelper; private DisplayFoldController mDisplayFoldController; AppOpsManager mAppOpsManager; private ScreenshotHelper mScreenshotHelper; private boolean mHasFeatureWatch; Loading Loading @@ -471,6 +472,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidNavigationAccessibility; boolean mLidControlsScreenLock; boolean mLidControlsSleep; private boolean mLidControlsDisplayFold; int mShortPressOnPowerBehavior; int mLongPressOnPowerBehavior; int mVeryLongPressOnPowerBehavior; Loading Loading @@ -1794,6 +1796,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.bool.config_lidControlsScreenLock); mLidControlsSleep = mContext.getResources().getBoolean( com.android.internal.R.bool.config_lidControlsSleep); mLidControlsDisplayFold = mContext.getResources().getBoolean( com.android.internal.R.bool.config_lidControlsDisplayFold); mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); Loading Loading @@ -1850,6 +1854,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { readConfigurationDependentBehaviors(); if (mLidControlsDisplayFold) { mDisplayFoldController = DisplayFoldController.create(DEFAULT_DISPLAY); } else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) { mDisplayFoldController = DisplayFoldController.createWithProxSensor(context, DEFAULT_DISPLAY); } mAccessibilityManager = (AccessibilityManager) context.getSystemService( Context.ACCESSIBILITY_SERVICE); Loading Loading @@ -4972,7 +4983,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void applyLidSwitchState() { final int lidState = mDefaultDisplayPolicy.getLidState(); if (lidState == LID_CLOSED && mLidControlsSleep) { if (mLidControlsDisplayFold && mDisplayFoldController != null) { mDisplayFoldController.setDeviceFolded(lidState == LID_CLOSED); } else if (lidState == LID_CLOSED && mLidControlsSleep) { goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); } else if (lidState == LID_CLOSED && mLidControlsScreenLock) { Loading