From 7f3994ec2a5dce1a037f04714b1f25cab85affb6 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 4 Dec 2012 14:04:28 -0800 Subject: Pin electron beam surface to natural orientation. If a rotation occurred while the electron beam surface was showing, the surface may have appeared in the wrong orientation. We fix this problem by adjusting the transformation matrix of the electron beam surface according to the display orientation whenever a display transaction occurs. The rotation itself is allowed to proceed but it is not visible to the user. We must let this happen so that the lock screen is correctly oriented when the screen is turned back on. Note that the electron beam surface serves two purposes. First, it is used to play the screen off animation. When the animation is finished, the surface remains visible but is solid black. Then we turn the screen off. Second, when we turn the screen back on we leave the electron beam surface showing until the window manager is ready to show the new content. This prevents the user from seeing a flash of the old content while the screen is being turned on. When everything is ready, we dismiss the electron beam. It's important for the electron beam to remain visible for the entire duration from just before the screen is turned off until after the screen is turned on and is ready to be seen. This is why we cannot fix the bug by deferring rotation or otherwise getting in the way of the window manager doing what it needs to do to get the screen ready when the screen is turned on again. Bug: 7479740 Change-Id: I2fcf35114ad9b2e00fdfc67793be6df62c8dc4c3 --- .../server/display/DisplayManagerService.java | 40 ++++++++++++++++++++++ .../server/display/DisplayTransactionListener.java | 26 ++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 services/java/com/android/server/display/DisplayTransactionListener.java (limited to 'services/java/com/android/server/display') diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index e58a0a5..e09970e 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -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(); private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; + // List of all display transaction listeners. + private final CopyOnWriteArrayList mDisplayTransactionListeners = + new CopyOnWriteArrayList(); + // Set to true if all displays have been blanked by the power manager. private int mAllDisplayBlankStateFromPowerManager; @@ -261,6 +266,36 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } /** + * 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 * of the default display. It is expected to apply the requested change @@ -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(); + } } /** diff --git a/services/java/com/android/server/display/DisplayTransactionListener.java b/services/java/com/android/server/display/DisplayTransactionListener.java new file mode 100644 index 0000000..34eb8f9 --- /dev/null +++ b/services/java/com/android/server/display/DisplayTransactionListener.java @@ -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(); +} -- cgit v1.1