Merge "Pin electron beam surface to natural orientation." into jb-mr1.1-dev

This commit is contained in:
Jeff Brown
2012-12-04 17:14:59 -08:00
committed by Android (Google) Code Review
6 changed files with 153 additions and 43 deletions

View File

@ -285,6 +285,16 @@ public final class DisplayInfo implements Parcelable {
getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
}
public int getNaturalWidth() {
return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
logicalWidth : logicalHeight;
}
public int getNaturalHeight() {
return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
logicalHeight : logicalWidth;
}
private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
int width, int height) {
outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;

View File

@ -41,6 +41,7 @@ import android.view.DisplayInfo;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages attached displays.
@ -152,6 +153,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
new SparseArray<LogicalDisplay>();
private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
// List of all display transaction listeners.
private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
new CopyOnWriteArrayList<DisplayTransactionListener>();
// Set to true if all displays have been blanked by the power manager.
private int mAllDisplayBlankStateFromPowerManager;
@ -260,6 +265,36 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
return mHeadless;
}
/**
* Registers a display transaction listener to provide the client a chance to
* update its surfaces within the same transaction as any display layout updates.
*
* @param listener The listener to register.
*/
public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
// List is self-synchronized copy-on-write.
mDisplayTransactionListeners.add(listener);
}
/**
* Unregisters a display transaction listener to provide the client a chance to
* update its surfaces within the same transaction as any display layout updates.
*
* @param listener The listener to unregister.
*/
public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
// List is self-synchronized copy-on-write.
mDisplayTransactionListeners.remove(listener);
}
/**
* Overrides the display information of a particular logical display.
* This is used by the window manager to control the size and characteristics
@ -298,6 +333,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
performTraversalInTransactionLocked();
}
// List is self-synchronized copy-on-write.
for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
listener.onDisplayTransaction();
}
}
/**

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2012 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.display;
/**
* Called within a Surface transaction whenever the size or orientation of a
* display may have changed. Provides an opportunity for the client to
* update the position of its surfaces as part of the same transaction.
*/
public interface DisplayTransactionListener {
void onDisplayTransaction();
}

View File

@ -19,6 +19,7 @@ package com.android.server.power;
import com.android.server.LightsService;
import com.android.server.TwilightService;
import com.android.server.TwilightService.TwilightState;
import com.android.server.display.DisplayManagerService;
import android.animation.Animator;
import android.animation.ObjectAnimator;
@ -29,7 +30,6 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@ -40,7 +40,6 @@ import android.util.FloatMath;
import android.util.Slog;
import android.util.Spline;
import android.util.TimeUtils;
import android.view.Display;
import java.io.PrintWriter;
@ -183,7 +182,7 @@ final class DisplayPowerController {
private final TwilightService mTwilight;
// The display manager.
private final DisplayManager mDisplayManager;
private final DisplayManagerService mDisplayManager;
// The sensor manager.
private final SensorManager mSensorManager;
@ -346,6 +345,7 @@ final class DisplayPowerController {
*/
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
LightsService lights, TwilightService twilight,
DisplayManagerService displayManager,
DisplayBlanker displayBlanker,
Callbacks callbacks, Handler callbackHandler) {
mHandler = new DisplayControllerHandler(looper);
@ -357,7 +357,7 @@ final class DisplayPowerController {
mLights = lights;
mTwilight = twilight;
mSensorManager = new SystemSensorManager(mHandler.getLooper());
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager = displayManager;
final Resources resources = context.getResources();
@ -518,9 +518,8 @@ final class DisplayPowerController {
}
private void initialize() {
Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
mPowerState = new DisplayPowerState(
new ElectronBeam(display), mDisplayBlanker,
new ElectronBeam(mDisplayManager), mDisplayBlanker,
mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(

View File

@ -16,6 +16,9 @@
package com.android.server.power;
import com.android.server.display.DisplayManagerService;
import com.android.server.display.DisplayTransactionListener;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.opengl.EGL14;
@ -72,14 +75,13 @@ final class ElectronBeam {
private boolean mPrepared;
private int mMode;
private final Display mDisplay;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final DisplayManagerService mDisplayManager;
private int mDisplayLayerStack; // layer stack associated with primary display
private int mDisplayRotation;
private int mDisplayWidth; // real width, not rotated
private int mDisplayHeight; // real height, not rotated
private SurfaceSession mSurfaceSession;
private Surface mSurface;
private NaturalSurfaceLayout mSurfaceLayout;
private EGLDisplay mEglDisplay;
private EGLConfig mEglConfig;
private EGLContext mEglContext;
@ -111,8 +113,8 @@ final class ElectronBeam {
*/
public static final int MODE_FADE = 2;
public ElectronBeam(Display display) {
mDisplay = display;
public ElectronBeam(DisplayManagerService displayManager) {
mDisplayManager = displayManager;
}
/**
@ -129,18 +131,12 @@ final class ElectronBeam {
mMode = mode;
// Get the display size and adjust it for rotation.
mDisplay.getDisplayInfo(mDisplayInfo);
mDisplayLayerStack = mDisplay.getLayerStack();
mDisplayRotation = mDisplayInfo.rotation;
if (mDisplayRotation == Surface.ROTATION_90
|| mDisplayRotation == Surface.ROTATION_270) {
mDisplayWidth = mDisplayInfo.logicalHeight;
mDisplayHeight = mDisplayInfo.logicalWidth;
} else {
mDisplayWidth = mDisplayInfo.logicalWidth;
mDisplayHeight = mDisplayInfo.logicalHeight;
}
// Get the display size and layer stack.
// This is not expected to change while the electron beam surface is showing.
DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
mDisplayLayerStack = displayInfo.layerStack;
mDisplayWidth = displayInfo.getNaturalWidth();
mDisplayHeight = displayInfo.getNaturalHeight();
// Prepare the surface for drawing.
if (!tryPrepare()) {
@ -551,24 +547,8 @@ final class ElectronBeam {
mSurface.setLayerStack(mDisplayLayerStack);
mSurface.setSize(mDisplayWidth, mDisplayHeight);
switch (mDisplayRotation) {
case Surface.ROTATION_0:
mSurface.setPosition(0, 0);
mSurface.setMatrix(1, 0, 0, 1);
break;
case Surface.ROTATION_90:
mSurface.setPosition(0, mDisplayWidth);
mSurface.setMatrix(0, -1, 1, 0);
break;
case Surface.ROTATION_180:
mSurface.setPosition(mDisplayWidth, mDisplayHeight);
mSurface.setMatrix(-1, 0, 0, -1);
break;
case Surface.ROTATION_270:
mSurface.setPosition(mDisplayHeight, 0);
mSurface.setMatrix(0, 1, -1, 0);
break;
}
mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurface);
mSurfaceLayout.onDisplayTransaction();
} finally {
Surface.closeTransaction();
}
@ -601,6 +581,8 @@ final class ElectronBeam {
private void destroySurface() {
if (mSurface != null) {
mSurfaceLayout.dispose();
mSurfaceLayout = null;
Surface.openTransaction();
try {
mSurface.destroy();
@ -711,10 +693,63 @@ final class ElectronBeam {
pw.println(" mPrepared=" + mPrepared);
pw.println(" mMode=" + mMode);
pw.println(" mDisplayLayerStack=" + mDisplayLayerStack);
pw.println(" mDisplayRotation=" + mDisplayRotation);
pw.println(" mDisplayWidth=" + mDisplayWidth);
pw.println(" mDisplayHeight=" + mDisplayHeight);
pw.println(" mSurfaceVisible=" + mSurfaceVisible);
pw.println(" mSurfaceAlpha=" + mSurfaceAlpha);
}
/**
* Keeps a surface aligned with the natural orientation of the device.
* Updates the position and transformation of the matrix whenever the display
* is rotated. This is a little tricky because the display transaction
* callback can be invoked on any thread, not necessarily the thread that
* owns the electron beam.
*/
private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
private final DisplayManagerService mDisplayManager;
private Surface mSurface;
public NaturalSurfaceLayout(DisplayManagerService displayManager, Surface surface) {
mDisplayManager = displayManager;
mSurface = surface;
mDisplayManager.registerDisplayTransactionListener(this);
}
public void dispose() {
synchronized (this) {
mSurface = null;
}
mDisplayManager.unregisterDisplayTransactionListener(this);
}
@Override
public void onDisplayTransaction() {
synchronized (this) {
if (mSurface == null) {
return;
}
DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
switch (displayInfo.rotation) {
case Surface.ROTATION_0:
mSurface.setPosition(0, 0);
mSurface.setMatrix(1, 0, 0, 1);
break;
case Surface.ROTATION_90:
mSurface.setPosition(0, displayInfo.logicalHeight);
mSurface.setMatrix(0, -1, 1, 0);
break;
case Surface.ROTATION_180:
mSurface.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight);
mSurface.setMatrix(-1, 0, 0, -1);
break;
case Surface.ROTATION_270:
mSurface.setPosition(displayInfo.logicalWidth, 0);
mSurface.setMatrix(0, 1, -1, 0);
break;
}
}
}
}
}

View File

@ -432,7 +432,7 @@ public final class PowerManagerService extends IPowerManager.Stub
// The display power controller runs on the power manager service's
// own handler thread.
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
mContext, mNotifier, mLightsService, twilight,
mContext, mNotifier, mLightsService, twilight, mDisplayManagerService,
mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);