Skip to content

Commit 9e316a1

Browse files
author
Jeff Brown
committed
Blank or unblank all displays as need.
Ensures that both the internal display and HDMI are blanked or unblanked in tandem. Bug: 7309812 Change-Id: Ie8b96d393e8bb20d23c92f3320142d9f7cf42aff
1 parent 2aac1a0 commit 9e316a1

File tree

10 files changed

+239
-62
lines changed

10 files changed

+239
-62
lines changed

core/java/android/view/Surface.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ private static native void nativeSetDisplayProjection(
266266
IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect);
267267
private static native boolean nativeGetDisplayInfo(
268268
IBinder displayToken, PhysicalDisplayInfo outInfo);
269+
private static native void nativeBlankDisplay(IBinder displayToken);
270+
private static native void nativeUnblankDisplay(IBinder displayToken);
269271

270272
private native void nativeCopyFrom(Surface other);
271273
private native void nativeTransferFrom(Surface other);
@@ -638,6 +640,22 @@ public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo o
638640
return nativeGetDisplayInfo(displayToken, outInfo);
639641
}
640642

643+
/** @hide */
644+
public static void blankDisplay(IBinder displayToken) {
645+
if (displayToken == null) {
646+
throw new IllegalArgumentException("displayToken must not be null");
647+
}
648+
nativeBlankDisplay(displayToken);
649+
}
650+
651+
/** @hide */
652+
public static void unblankDisplay(IBinder displayToken) {
653+
if (displayToken == null) {
654+
throw new IllegalArgumentException("displayToken must not be null");
655+
}
656+
nativeUnblankDisplay(displayToken);
657+
}
658+
641659
/**
642660
* Copy another surface to this one. This surface now holds a reference
643661
* to the same data as the original surface, and is -not- the owner.

core/jni/android_view_Surface.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <android_runtime/android_view_SurfaceSession.h>
4949
#include <android_runtime/android_graphics_SurfaceTexture.h>
5050
#include <utils/misc.h>
51+
#include <utils/Log.h>
5152

5253
#include <ScopedUtfChars.h>
5354

@@ -710,6 +711,22 @@ static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
710711
return JNI_TRUE;
711712
}
712713

714+
static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
715+
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
716+
if (token == NULL) return;
717+
718+
ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
719+
SurfaceComposerClient::blankDisplay(token);
720+
}
721+
722+
static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
723+
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
724+
if (token == NULL) return;
725+
726+
ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
727+
SurfaceComposerClient::unblankDisplay(token);
728+
}
729+
713730
// ----------------------------------------------------------------------------
714731

715732
static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
@@ -832,6 +849,10 @@ static JNINativeMethod gSurfaceMethods[] = {
832849
(void*)nativeSetDisplayProjection },
833850
{"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z",
834851
(void*)nativeGetDisplayInfo },
852+
{"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
853+
(void*)nativeBlankDisplay },
854+
{"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
855+
(void*)nativeUnblankDisplay },
835856
{"nativeCopyFrom", "(Landroid/view/Surface;)V",
836857
(void*)nativeCopyFrom },
837858
{"nativeTransferFrom", "(Landroid/view/Surface;)V",

services/java/com/android/server/display/DisplayDevice.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ public void applyPendingDisplayDeviceInfoChangesLocked() {
104104
public void performTraversalInTransactionLocked() {
105105
}
106106

107+
/**
108+
* Blanks the display, if supported.
109+
*/
110+
public void blankLocked() {
111+
}
112+
113+
/**
114+
* Unblanks the display, if supported.
115+
*/
116+
public void unblankLocked() {
117+
}
118+
107119
/**
108120
* Sets the display layer stack while in a transaction.
109121
*/

services/java/com/android/server/display/DisplayManagerService.java

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
103103
private static final int MSG_REQUEST_TRAVERSAL = 4;
104104
private static final int MSG_UPDATE_VIEWPORT = 5;
105105

106+
private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
107+
private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
108+
private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
109+
106110
private final Context mContext;
107111
private final boolean mHeadless;
108112
private final DisplayManagerHandler mHandler;
@@ -141,6 +145,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
141145
new SparseArray<LogicalDisplay>();
142146
private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
143147

148+
// Set to true if all displays have been blanked by the power manager.
149+
private int mAllDisplayBlankStateFromPowerManager;
150+
144151
// Set to true when there are pending display changes that have yet to be applied
145152
// to the surface flinger state.
146153
private boolean mPendingTraversal;
@@ -285,6 +292,40 @@ public void performTraversalInTransactionFromWindowManager() {
285292
}
286293
}
287294

295+
/**
296+
* Called by the power manager to blank all displays.
297+
*/
298+
public void blankAllDisplaysFromPowerManager() {
299+
synchronized (mSyncRoot) {
300+
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
301+
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
302+
303+
final int count = mDisplayDevices.size();
304+
for (int i = 0; i < count; i++) {
305+
DisplayDevice device = mDisplayDevices.get(i);
306+
device.blankLocked();
307+
}
308+
}
309+
}
310+
}
311+
312+
/**
313+
* Called by the power manager to unblank all displays.
314+
*/
315+
public void unblankAllDisplaysFromPowerManager() {
316+
synchronized (mSyncRoot) {
317+
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
318+
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
319+
320+
final int count = mDisplayDevices.size();
321+
for (int i = 0; i < count; i++) {
322+
DisplayDevice device = mDisplayDevices.get(i);
323+
device.unblankLocked();
324+
}
325+
}
326+
}
327+
}
328+
288329
/**
289330
* Returns information about the specified logical display.
290331
*
@@ -528,6 +569,17 @@ private void handleDisplayDeviceAdded(DisplayDevice device) {
528569
mDisplayDevices.add(device);
529570
addLogicalDisplayLocked(device);
530571
scheduleTraversalLocked(false);
572+
573+
// Blank or unblank the display immediately to match the state requested
574+
// by the power manager (if known).
575+
switch (mAllDisplayBlankStateFromPowerManager) {
576+
case DISPLAY_BLANK_STATE_BLANKED:
577+
device.blankLocked();
578+
break;
579+
case DISPLAY_BLANK_STATE_UNBLANKED:
580+
device.unblankLocked();
581+
break;
582+
}
531583
}
532584
}
533585

@@ -788,9 +840,18 @@ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
788840
}
789841

790842
pw.println("DISPLAY MANAGER (dumpsys display)");
791-
pw.println(" mHeadless=" + mHeadless);
792843

793844
synchronized (mSyncRoot) {
845+
pw.println(" mHeadless=" + mHeadless);
846+
pw.println(" mOnlyCode=" + mOnlyCore);
847+
pw.println(" mSafeMode=" + mSafeMode);
848+
pw.println(" mPendingTraversal=" + mPendingTraversal);
849+
pw.println(" mAllDisplayBlankStateFromPowerManager="
850+
+ mAllDisplayBlankStateFromPowerManager);
851+
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
852+
pw.println(" mDefaultViewport=" + mDefaultViewport);
853+
pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
854+
794855
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
795856
ipw.increaseIndent();
796857

@@ -817,10 +878,6 @@ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
817878
pw.println(" Display " + displayId + ":");
818879
display.dumpLocked(ipw);
819880
}
820-
821-
pw.println();
822-
pw.println("Default viewport: " + mDefaultViewport);
823-
pw.println("External touch viewport: " + mExternalTouchViewport);
824881
}
825882
}
826883

services/java/com/android/server/display/LocalDisplayAdapter.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ private final class LocalDisplayDevice extends DisplayDevice {
9292

9393
private DisplayDeviceInfo mInfo;
9494
private boolean mHavePendingChanges;
95+
private boolean mBlanked;
9596

9697
public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
9798
PhysicalDisplayInfo phys) {
@@ -149,11 +150,24 @@ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
149150
return mInfo;
150151
}
151152

153+
@Override
154+
public void blankLocked() {
155+
mBlanked = true;
156+
Surface.blankDisplay(getDisplayTokenLocked());
157+
}
158+
159+
@Override
160+
public void unblankLocked() {
161+
mBlanked = false;
162+
Surface.unblankDisplay(getDisplayTokenLocked());
163+
}
164+
152165
@Override
153166
public void dumpLocked(PrintWriter pw) {
154167
super.dumpLocked(pw);
155168
pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
156169
pw.println("mPhys=" + mPhys);
170+
pw.println("mBlanked=" + mBlanked);
157171
}
158172
}
159173

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.server.power;
18+
19+
/**
20+
* Blanks or unblanks all displays.
21+
*/
22+
interface DisplayBlanker {
23+
public void blankAllDisplays();
24+
public void unblankAllDisplays();
25+
}

services/java/com/android/server/power/DisplayPowerController.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ final class DisplayPowerController {
159159
// A suspend blocker.
160160
private final SuspendBlocker mSuspendBlocker;
161161

162+
// The display blanker.
163+
private final DisplayBlanker mDisplayBlanker;
164+
162165
// Our handler.
163166
private final DisplayControllerHandler mHandler;
164167

@@ -343,10 +346,12 @@ final class DisplayPowerController {
343346
*/
344347
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
345348
LightsService lights, TwilightService twilight, SuspendBlocker suspendBlocker,
349+
DisplayBlanker displayBlanker,
346350
Callbacks callbacks, Handler callbackHandler) {
347351
mHandler = new DisplayControllerHandler(looper);
348352
mNotifier = notifier;
349353
mSuspendBlocker = suspendBlocker;
354+
mDisplayBlanker = displayBlanker;
350355
mCallbacks = callbacks;
351356
mCallbackHandler = callbackHandler;
352357

@@ -520,7 +525,8 @@ private void initialize() {
520525
new ElectronBeam(display),
521526
new PhotonicModulator(executor,
522527
mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
523-
mSuspendBlocker));
528+
mSuspendBlocker),
529+
mDisplayBlanker);
524530

525531
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
526532
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);

services/java/com/android/server/power/DisplayPowerState.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ final class DisplayPowerState {
5151

5252
private final Choreographer mChoreographer;
5353
private final ElectronBeam mElectronBeam;
54-
private final PhotonicModulator mScreenBrightnessModulator;
54+
private final PhotonicModulator mPhotonicModulator;
55+
private final DisplayBlanker mDisplayBlanker;
5556

5657
private int mDirty;
5758
private boolean mScreenOn;
@@ -61,10 +62,11 @@ final class DisplayPowerState {
6162
private Runnable mCleanListener;
6263

6364
public DisplayPowerState(ElectronBeam electronBean,
64-
PhotonicModulator screenBrightnessModulator) {
65+
PhotonicModulator photonicModulator, DisplayBlanker displayBlanker) {
6566
mChoreographer = Choreographer.getInstance();
6667
mElectronBeam = electronBean;
67-
mScreenBrightnessModulator = screenBrightnessModulator;
68+
mPhotonicModulator = photonicModulator;
69+
mDisplayBlanker = displayBlanker;
6870

6971
// At boot time, we know that the screen is on and the electron beam
7072
// animation is not playing. We don't know the screen's brightness though,
@@ -238,21 +240,21 @@ private void invalidate(int dirty) {
238240
private void apply() {
239241
if (mDirty != 0) {
240242
if ((mDirty & DIRTY_SCREEN_ON) != 0 && !mScreenOn) {
241-
mScreenBrightnessModulator.setBrightness(0, true /*sync*/);
242-
PowerManagerService.nativeSetScreenState(false);
243+
mPhotonicModulator.setBrightness(0, true /*sync*/);
244+
mDisplayBlanker.blankAllDisplays();
243245
}
244246

245247
if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
246248
mElectronBeam.draw(mElectronBeamLevel);
247249
}
248250

249251
if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
250-
PowerManagerService.nativeSetScreenState(true);
252+
mDisplayBlanker.unblankAllDisplays();
251253
}
252254

253255
if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0
254256
&& mScreenOn) {
255-
mScreenBrightnessModulator.setBrightness(
257+
mPhotonicModulator.setBrightness(
256258
(int)(mScreenBrightness * mElectronBeamLevel), false /*sync*/);
257259
}
258260

0 commit comments

Comments
 (0)