blob: 71d6dfc9c598c5b5def6b8f10164df356d188391 [file] [log] [blame]
/*
* 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);
}
}