summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/WindowManager.java10
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java229
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java23
-rw-r--r--services/java/com/android/server/PowerManagerService.java30
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java133
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java4
11 files changed, 328 insertions, 120 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c7bf8e3..0dc781f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -218,4 +218,9 @@ interface IWindowManager
* Called by the settings application to temporarily set the pointer speed.
*/
void setPointerSpeed(int speed);
+
+ /**
+ * Block until all windows the window manager knows about have been drawn.
+ */
+ void waitForAllDrawn();
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6b09049..fdd9b2c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -177,7 +177,8 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
@ViewDebug.IntToString(from = TYPE_INPUT_METHOD, to = "TYPE_INPUT_METHOD"),
@ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, to = "TYPE_INPUT_METHOD_DIALOG"),
- @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY")
+ @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY"),
+ @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS")
})
public int type;
@@ -401,6 +402,13 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
/**
+ * Window type: The boot progress dialog, goes on top of everything
+ * in the world.
+ * @hide
+ */
+ public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
index d3baa2b..aa9fa45 100644
--- a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
+++ b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
@@ -25,6 +25,8 @@ import android.util.Log;
public class TargetDrawable {
private static final String TAG = "TargetDrawable";
+ private static final boolean DEBUG = false;
+
public static final int[] STATE_ACTIVE =
{ android.R.attr.state_enabled, android.R.attr.state_active };
public static final int[] STATE_INACTIVE =
@@ -139,11 +141,13 @@ public class TargetDrawable {
maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
}
- Log.v(TAG, "union of childDrawable rects " + d + " to: " + maxWidth + "x" + maxHeight);
+ if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
+ + maxWidth + "x" + maxHeight);
d.setBounds(0, 0, maxWidth, maxHeight);
for (int i = 0; i < d.getStateCount(); i++) {
Drawable childDrawable = d.getStateDrawable(i);
- Log.v(TAG, "sizing drawable " + childDrawable + " to: " + maxWidth + "x" + maxHeight);
+ if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
+ + maxWidth + "x" + maxHeight);
childDrawable.setBounds(0, 0, maxWidth, maxHeight);
}
} else if (mDrawable != null) {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index afa92f1..9629702 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -43,7 +43,7 @@ import android.widget.TextView;
*
*/
class KeyguardStatusViewManager implements OnClickListener {
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final String TAG = "KeyguardStatusView";
public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 431f8e0..5661116 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -116,6 +116,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
private static final int SET_HIDDEN = 12;
private static final int KEYGUARD_TIMEOUT = 13;
+ private static final int REPORT_SHOW_DONE = 14;
/**
* The default amount of time we stay awake (used for all key input)
@@ -238,6 +239,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
private boolean mScreenOn = false;
+ private boolean mShowPending = false;
+
// last known state of the cellular connection
private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
@@ -306,7 +309,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
- doKeyguard();
+ doKeyguardLocked();
}
}
@@ -363,7 +366,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
if (timeout <= 0) {
// Lock now
mSuppressNextLockSound = true;
- doKeyguard();
+ doKeyguardLocked();
} else {
// Lock in the future
long when = SystemClock.elapsedRealtime() + timeout;
@@ -379,7 +382,19 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
// Do not enable the keyguard if the prox sensor forced the screen off.
} else {
- doKeyguard();
+ if (!doKeyguardLocked() && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
+ // The user has explicitly turned off the screen, causing it
+ // to lock. We want to block here until the keyguard window
+ // has shown, so the power manager won't complete the screen
+ // off flow until that point, so we know it won't turn *on*
+ // the screen until this is done.
+ while (mShowPending) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
}
}
}
@@ -553,56 +568,58 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
}
/**
- * Enable the keyguard if the settings are appropriate.
+ * Enable the keyguard if the settings are appropriate. Return true if all
+ * work that will happen is done; returns false if the caller can wait for
+ * the keyguard to be shown.
*/
- private void doKeyguard() {
- synchronized (this) {
- // if another app is disabling us, don't show
- if (!mExternallyEnabled) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
-
- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
- // for an occasional ugly flicker in this situation:
- // 1) receive a call with the screen on (no keyguard) or make a call
- // 2) screen times out
- // 3) user hits key to turn screen back on
- // instead, we reenable the keyguard when we know the screen is off and the call
- // ends (see the broadcast receiver below)
- // TODO: clean this up when we have better support at the window manager level
- // for apps that wish to be on top of the keyguard
- return;
- }
-
- // if the keyguard is already showing, don't bother
- if (mKeyguardViewManager.isShowing()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
- return;
- }
+ private boolean doKeyguardLocked() {
+ // if another app is disabling us, don't show
+ if (!mExternallyEnabled) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
+
+ // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
+ // for an occasional ugly flicker in this situation:
+ // 1) receive a call with the screen on (no keyguard) or make a call
+ // 2) screen times out
+ // 3) user hits key to turn screen back on
+ // instead, we reenable the keyguard when we know the screen is off and the call
+ // ends (see the broadcast receiver below)
+ // TODO: clean this up when we have better support at the window manager level
+ // for apps that wish to be on top of the keyguard
+ return true;
+ }
- // if the setup wizard hasn't run yet, don't show
- final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
- false);
- final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
- final IccCard.State state = mUpdateMonitor.getSimState();
- final boolean lockedOrMissing = state.isPinLocked()
- || ((state == IccCard.State.ABSENT
- || state == IccCard.State.PERM_DISABLED)
- && requireSim);
-
- if (!lockedOrMissing && !provisioned) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
- + " and the sim is not locked or missing");
- return;
- }
+ // if the keyguard is already showing, don't bother
+ if (mKeyguardViewManager.isShowing()) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+ return true;
+ }
- if (mLockPatternUtils.isLockScreenDisabled()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
- return;
- }
+ // if the setup wizard hasn't run yet, don't show
+ final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
+ false);
+ final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
+ final IccCard.State state = mUpdateMonitor.getSimState();
+ final boolean lockedOrMissing = state.isPinLocked()
+ || ((state == IccCard.State.ABSENT
+ || state == IccCard.State.PERM_DISABLED)
+ && requireSim);
+
+ if (!lockedOrMissing && !provisioned) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ + " and the sim is not locked or missing");
+ return true;
+ }
- if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
- showLocked();
+ if (mLockPatternUtils.isLockScreenDisabled()) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+ return true;
}
+
+ if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
+ mShowPending = true;
+ showLocked();
+ return false;
}
/**
@@ -696,41 +713,49 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
case ABSENT:
// only force lock screen in case of missing sim if user hasn't
// gone through setup wizard
- if (!mUpdateMonitor.isDeviceProvisioned()) {
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
- + " we need to show the keyguard since the "
- + "device isn't provisioned yet.");
- doKeyguard();
- } else {
- resetStateLocked();
+ synchronized (this) {
+ if (!mUpdateMonitor.isDeviceProvisioned()) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+ + " we need to show the keyguard since the "
+ + "device isn't provisioned yet.");
+ doKeyguardLocked();
+ } else {
+ resetStateLocked();
+ }
}
}
break;
case PIN_REQUIRED:
case PUK_REQUIRED:
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need "
- + "to show the keyguard so the user can enter their sim pin");
- doKeyguard();
- } else {
- resetStateLocked();
+ synchronized (this) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need "
+ + "to show the keyguard so the user can enter their sim pin");
+ doKeyguardLocked();
+ } else {
+ resetStateLocked();
+ }
}
break;
case PERM_DISABLED:
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
- + "keygaurd isn't showing.");
- doKeyguard();
- } else {
- if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
- + "show permanently disabled message in lockscreen.");
- resetStateLocked();
+ synchronized (this) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+ + "keygaurd isn't showing.");
+ doKeyguardLocked();
+ } else {
+ if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+ + "show permanently disabled message in lockscreen.");
+ resetStateLocked();
+ }
}
break;
case READY:
- if (isShowing()) {
- resetStateLocked();
+ synchronized (this) {
+ if (isShowing()) {
+ resetStateLocked();
+ }
}
break;
}
@@ -751,27 +776,31 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
+ sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
- if (mDelayedShowingSequence == sequence) {
- // Don't play lockscreen SFX if the screen went off due to
- // timeout.
- mSuppressNextLockSound = true;
-
- doKeyguard();
+ synchronized (KeyguardViewMediator.this) {
+ if (mDelayedShowingSequence == sequence) {
+ // Don't play lockscreen SFX if the screen went off due to
+ // timeout.
+ mSuppressNextLockSound = true;
+
+ doKeyguardLocked();
+ }
}
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
- if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending
- && !mScreenOn // screen off
- && mExternallyEnabled) { // not disabled by any app
-
- // note: this is a way to gracefully reenable the keyguard when the call
- // ends and the screen is off without always reenabling the keyguard
- // each time the screen turns off while in call (and having an occasional ugly
- // flicker while turning back on the screen and disabling the keyguard again).
- if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
- + "keyguard is showing");
- doKeyguard();
+ synchronized (KeyguardViewMediator.this) {
+ if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending
+ && !mScreenOn // screen off
+ && mExternallyEnabled) { // not disabled by any app
+
+ // note: this is a way to gracefully reenable the keyguard when the call
+ // ends and the screen is off without always reenabling the keyguard
+ // each time the screen turns off while in call (and having an occasional ugly
+ // flicker while turning back on the screen and disabling the keyguard again).
+ if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
+ + "keyguard is showing");
+ doKeyguardLocked();
+ }
}
}
}
@@ -962,7 +991,15 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
handleSetHidden(msg.arg1 != 0);
break;
case KEYGUARD_TIMEOUT:
- doKeyguard();
+ synchronized (KeyguardViewMediator.this) {
+ doKeyguardLocked();
+ }
+ break;
+ case REPORT_SHOW_DONE:
+ synchronized (KeyguardViewMediator.this) {
+ mShowPending = false;
+ KeyguardViewMediator.this.notifyAll();
+ }
break;
}
}
@@ -1062,8 +1099,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
if (DEBUG) Log.d(TAG, "handleShow");
if (!mSystemReady) return;
- playSounds(true);
-
mKeyguardViewManager.show();
mShowing = true;
adjustUserActivityLocked();
@@ -1072,7 +1107,17 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
ActivityManagerNative.getDefault().closeSystemDialogs("lock");
} catch (RemoteException e) {
}
+
+ // Do this at the end to not slow down display of the keyguard.
+ playSounds(true);
+
mShowKeyguardWakeLock.release();
+
+ // We won't say the show is done yet because the view hierarchy
+ // still needs to do the traversal. Posting this message allows
+ // us to hold off until that is done.
+ Message msg = mHandler.obtainMessage(REPORT_SHOW_DONE);
+ mHandler.sendMessage(msg);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1d5fbc0a..be129a8 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -120,6 +120,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
@@ -197,8 +198,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// things in here CAN NOT take focus, but are shown on top of everything else.
static final int SYSTEM_OVERLAY_LAYER = 20;
static final int SECURE_SYSTEM_OVERLAY_LAYER = 21;
+ static final int BOOT_PROGRESS_LAYER = 22;
// the (mouse) pointer layer
- static final int POINTER_LAYER = 22;
+ static final int POINTER_LAYER = 23;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -1095,6 +1097,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return POINTER_LAYER;
case TYPE_NAVIGATION_BAR:
return NAVIGATION_BAR_LAYER;
+ case TYPE_BOOT_PROGRESS:
+ return BOOT_PROGRESS_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
@@ -2797,13 +2801,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void screenTurnedOff(int why) {
EventLog.writeEvent(70000, 0);
- mKeyguardMediator.onScreenTurnedOff(why);
synchronized (mLock) {
mScreenOn = false;
+ }
+ mKeyguardMediator.onScreenTurnedOff(why);
+ synchronized (mLock) {
updateOrientationListenerLp();
updateLockScreenTimeout();
updateScreenSaverTimeoutLocked();
}
+ try {
+ mWindowManager.waitForAllDrawn();
+ } catch (RemoteException e) {
+ }
+ // Wait for one frame to give surface flinger time to do its
+ // compositing. Yes this is a hack, but I am really not up right now for
+ // implementing some mechanism to block until SF is done. :p
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ }
}
/** {@inheritDoc} */
@@ -3092,7 +3109,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mBootMsgDialog.setIndeterminate(true);
mBootMsgDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY);
+ WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
mBootMsgDialog.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index d80a2cd..cbd986f 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -161,6 +161,7 @@ public class PowerManagerService extends IPowerManager.Stub
private int mStayOnConditions = 0;
private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
private final int[] mBroadcastWhy = new int[3];
+ private boolean mBroadcastingScreenOff = false;
private int mPartialCount = 0;
private int mPowerState;
// mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
@@ -1342,6 +1343,10 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastWakeLock.release();
}
+ // The broadcast queue has changed; make sure the screen is on if it
+ // is now possible for it to be.
+ updateNativePowerStateLocked();
+
// Now send the message.
if (index >= 0) {
// Acquire the broadcast wake lock before changing the power
@@ -1370,6 +1375,9 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastWhy[i] = mBroadcastWhy[i+1];
}
policy = getPolicyLocked();
+ if (value == 0) {
+ mBroadcastingScreenOff = true;
+ }
}
if (value == 1) {
mScreenOnStart = SystemClock.uptimeMillis();
@@ -1412,6 +1420,8 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
mBroadcastWakeLock.mCount);
+ mBroadcastingScreenOff = false;
+ updateNativePowerStateLocked();
mBroadcastWakeLock.release();
}
}
@@ -1442,6 +1452,10 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
+ synchronized (mLocks) {
+ mBroadcastingScreenOff = false;
+ updateNativePowerStateLocked();
+ }
mBroadcastWakeLock.release();
}
}
@@ -1768,6 +1782,22 @@ public class PowerManagerService extends IPowerManager.Stub
}
private void updateNativePowerStateLocked() {
+ if ((mPowerState & SCREEN_ON_BIT) != 0) {
+ // Don't turn screen on if we are currently reporting a screen off.
+ // This is to avoid letting the screen go on before things like the
+ // lock screen have been displayed due to it going off.
+ if (mBroadcastingScreenOff) {
+ // Currently broadcasting that the screen is off. Don't
+ // allow screen to go on until that is done.
+ return;
+ }
+ for (int i=0; i<mBroadcastQueue.length; i++) {
+ if (mBroadcastQueue[i] == 0) {
+ // A screen off is currently enqueued.
+ return;
+ }
+ }
+ }
nativeSetPowerState(
(mPowerState & SCREEN_ON_BIT) != 0,
(mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b817598..c935733 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6564,7 +6564,7 @@ public final class ActivityManagerService extends ActivityManagerNative
i--;
}
}
-
+
for (int i=0; i<ris.size(); i++) {
ActivityInfo ai = ris.get(i).activityInfo;
ComponentName comp = new ComponentName(ai.packageName, ai.name);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 6f0779f..4ad0f45 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3163,7 +3163,7 @@ final class ActivityStack {
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (mMainStack) {
- if (!mService.mBooted && !fromTimeout) {
+ if (!mService.mBooted) {
mService.mBooted = true;
enableScreen = true;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index dc5555e..3df94a6 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -50,11 +50,9 @@ import com.android.server.am.BatteryStatsService;
import android.Manifest;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
-import android.app.ProgressDialog;
import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -164,6 +162,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_DRAG = false;
+ static final boolean DEBUG_SCREEN_ON = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean HIDE_STACK_CRAWLS = true;
@@ -408,6 +407,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mSafeMode;
boolean mDisplayEnabled = false;
boolean mSystemBooted = false;
+ boolean mForceDisplayEnabled = false;
boolean mShowingBootMessages = false;
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
@@ -2189,7 +2189,7 @@ public class WindowManagerService extends IWindowManager.Stub
// to hold off on removing the window until the animation is done.
// If the display is frozen, just remove immediately, since the
// animation wouldn't be seen.
- if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
+ if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
// If we are not currently running the exit animation, we
// need to see about starting one.
if (wasVisible=win.isWinVisibleLw()) {
@@ -2536,6 +2536,12 @@ public class WindowManagerService extends IWindowManager.Stub
win.mRelayoutCalled = true;
final int oldVisibility = win.mViewVisibility;
win.mViewVisibility = viewVisibility;
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException stack = new RuntimeException();
+ stack.fillInStackTrace();
+ Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
+ + " newVis=" + viewVisibility, stack);
+ }
if (viewVisibility == View.VISIBLE &&
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
displayed = !win.isVisibleLw();
@@ -2556,7 +2562,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (displayed) {
if (win.mSurface != null && !win.mDrawPending
&& !win.mCommitDrawPending && !mDisplayFrozen
- && mPolicy.isScreenOn()) {
+ && mDisplayEnabled && mPolicy.isScreenOn()) {
applyEnterAnimationLocked(win);
}
if ((win.mAttrs.flags
@@ -2849,7 +2855,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
- if (!mDisplayFrozen && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
int anim = mPolicy.selectAnimationLw(win, transit);
int attr = -1;
Animation a = null;
@@ -2935,7 +2941,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
- if (!mDisplayFrozen && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
Animation a;
if (mNextAppTransitionPackage != null) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -3501,7 +3507,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Prepare app transition: transit=" + transit
+ " mNextAppTransition=" + mNextAppTransition);
- if (!mDisplayFrozen && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
|| mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
mNextAppTransition = transit;
@@ -3585,7 +3591,7 @@ public class WindowManagerService extends IWindowManager.Stub
// If the display is frozen, we won't do anything until the
// actual window is displayed so there is no reason to put in
// the starting window.
- if (mDisplayFrozen || !mPolicy.isScreenOn()) {
+ if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn()) {
return;
}
@@ -3867,7 +3873,7 @@ public class WindowManagerService extends IWindowManager.Stub
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
- if (!mDisplayFrozen && mPolicy.isScreenOn()
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()
&& mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
// Already in requested state, don't do anything more.
if (wtoken.hiddenRequested != visible) {
@@ -4688,6 +4694,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
mSystemBooted = true;
hideBootMessagesLocked();
+ // If the screen still doesn't come up after 30 seconds, give
+ // up and turn it on.
+ Message msg = mH.obtainMessage(H.BOOT_TIMEOUT);
+ mH.sendMessageDelayed(msg, 30*1000);
}
performEnableScreen();
@@ -4703,6 +4713,17 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
}
+ public void performBootTimeout() {
+ synchronized(mWindowMap) {
+ if (mDisplayEnabled) {
+ return;
+ }
+ Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
+ mForceDisplayEnabled = true;
+ }
+ performEnableScreen();
+ }
+
public void performEnableScreen() {
synchronized(mWindowMap) {
if (mDisplayEnabled) {
@@ -4712,19 +4733,55 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- // Don't enable the screen until all existing windows
- // have been drawn.
- final int N = mWindows.size();
- for (int i=0; i<N; i++) {
- WindowState w = mWindows.get(i);
- if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
+ if (!mForceDisplayEnabled) {
+ // Don't enable the screen until all existing windows
+ // have been drawn.
+ boolean haveBootMsg = false;
+ boolean haveApp = false;
+ boolean haveWallpaper = false;
+ boolean haveKeyguard = false;
+ final int N = mWindows.size();
+ for (int i=0; i<N; i++) {
+ WindowState w = mWindows.get(i);
+ if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
+ return;
+ }
+ if (w.isDrawnLw()) {
+ if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
+ haveBootMsg = true;
+ } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) {
+ haveApp = true;
+ } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) {
+ haveWallpaper = true;
+ } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
+ haveKeyguard = true;
+ }
+ }
+ }
+
+ if (DEBUG_SCREEN_ON) {
+ Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
+ + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
+ + " haveWall=" + haveWallpaper + " haveKeyguard=" + haveKeyguard);
+ }
+
+ // If we are turning on the screen to show the boot message,
+ // don't do it until the boot message is actually displayed.
+ if (!mSystemBooted && !haveBootMsg) {
+ return;
+ }
+
+ // If we are turning on the screen after the boot is completed
+ // normally, don't do so until we have the application and
+ // wallpaper.
+ if (mSystemBooted && ((!haveApp && !haveKeyguard) || !haveWallpaper)) {
return;
}
}
mDisplayEnabled = true;
+ if (DEBUG_SCREEN_ON) Slog.i(TAG, "******************** ENABLING SCREEN!");
if (false) {
- Slog.i(TAG, "ENABLING SCREEN!");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
this.dump(null, pw, null);
@@ -6239,6 +6296,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int DRAG_START_TIMEOUT = 20;
public static final int DRAG_END_TIMEOUT = 21;
public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
+ public static final int BOOT_TIMEOUT = 23;
private Session mLastReportedHold;
@@ -6549,6 +6607,11 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
+ case BOOT_TIMEOUT: {
+ performBootTimeout();
+ break;
+ }
+
case APP_FREEZE_TIMEOUT: {
synchronized (mWindowMap) {
Slog.w(TAG, "App freeze timeout expired.");
@@ -8300,7 +8363,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mDimAnimator != null && mDimAnimator.mDimShown) {
animating |= mDimAnimator.updateSurface(dimming, currentTime,
- mDisplayFrozen || !mPolicy.isScreenOn());
+ mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn());
}
if (!blurring && mBlurShown) {
@@ -8498,12 +8561,44 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
-
+
+ mWindowMap.notifyAll();
+
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
enableScreenIfNeededLocked();
}
-
+
+ public void waitForAllDrawn() {
+ synchronized (mWindowMap) {
+ while (true) {
+ final int N = mWindows.size();
+ boolean okay = true;
+ for (int i=0; i<N && okay; i++) {
+ WindowState w = mWindows.get(i);
+ if (DEBUG_SCREEN_ON) {
+ Slog.i(TAG, "Window " + w + " vis=" + w.isVisibleLw()
+ + " obscured=" + w.mObscured + " drawn=" + w.isDrawnLw());
+ }
+ if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
+ if (DEBUG_SCREEN_ON) {
+ Slog.i(TAG, "Window not yet drawn: " + w);
+ }
+ okay = false;
+ break;
+ }
+ }
+ if (okay) {
+ return;
+ }
+ try {
+ mWindowMap.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
/**
* Must be called with the main window manager lock held.
*/
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 7d83a9f..ed29a78 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -451,6 +451,10 @@ public class BridgeWindowManager implements IWindowManager {
return 0;
}
+ public void waitForAllDrawn() {
+ // TODO Auto-generated method stub
+ }
+
public IBinder asBinder() {
// TODO Auto-generated method stub
return null;