summaryrefslogtreecommitdiffstats
path: root/policy/src
diff options
context:
space:
mode:
Diffstat (limited to 'policy/src')
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java58
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java13
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java11
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java1
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java67
-rw-r--r--policy/src/com/android/internal/policy/impl/LockScreen.java15
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java95
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java336
9 files changed, 478 insertions, 126 deletions
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 38c85bb..bcba3c2 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -16,16 +16,23 @@
package com.android.internal.policy.impl;
-import android.app.Activity;
+import com.android.internal.app.ShutdownThread;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.R;
+
+import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
@@ -39,13 +46,9 @@ import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.internal.R;
-import com.android.internal.app.ShutdownThread;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-import com.google.android.collect.Lists;
import java.util.ArrayList;
+import java.util.List;
/**
* Helper to show the global actions dialog. Each item is an {@link Action} that
@@ -101,9 +104,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
- if (mDialog == null) {
- mDialog = createDialog();
+ if (mDialog != null) {
+ mDialog.dismiss();
}
+ mDialog = createDialog();
prepareDialog();
mDialog.show();
@@ -187,6 +191,31 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mItems.add(mSilentModeAction);
}
+ List<UserInfo> users = mContext.getPackageManager().getUsers();
+ if (users.size() > 1) {
+ for (final UserInfo user : users) {
+ SinglePressAction switchToUser = new SinglePressAction(
+ com.android.internal.R.drawable.ic_menu_cc,
+ user.name != null ? user.name : "Primary") {
+ public void onPress() {
+ try {
+ ActivityManagerNative.getDefault().switchUser(user.id);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't switch user " + re);
+ }
+ }
+
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+ };
+ mItems.add(switchToUser);
+ }
+ }
mAdapter = new MyAdapter();
final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
@@ -341,12 +370,19 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private static abstract class SinglePressAction implements Action {
private final int mIconResId;
private final int mMessageResId;
+ private final CharSequence mMessage;
protected SinglePressAction(int iconResId, int messageResId) {
mIconResId = iconResId;
mMessageResId = messageResId;
+ mMessage = null;
}
+ protected SinglePressAction(int iconResId, CharSequence message) {
+ mIconResId = iconResId;
+ mMessageResId = 0;
+ mMessage = message;
+ }
public boolean isEnabled() {
return true;
}
@@ -363,7 +399,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
v.findViewById(R.id.status).setVisibility(View.GONE);
icon.setImageDrawable(context.getResources().getDrawable(mIconResId));
- messageView.setText(mMessageResId);
+ if (mMessage != null) {
+ messageView.setText(mMessage);
+ } else {
+ messageView.setText(mMessageResId);
+ }
return v;
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 76d3df0..9f3de69 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -19,6 +19,7 @@ package com.android.internal.policy.impl;
import com.android.internal.R;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCard.State;
+import com.android.internal.widget.DigitalClock;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.TransportControlView;
import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
@@ -105,6 +106,7 @@ class KeyguardStatusViewManager implements OnClickListener {
private CharSequence mPlmn;
private CharSequence mSpn;
protected int mPhoneState;
+ private DigitalClock mDigitalClock;
private class TransientTextManager {
private TextView mTextView;
@@ -181,6 +183,7 @@ class KeyguardStatusViewManager implements OnClickListener {
mTransportView = (TransportControlView) findViewById(R.id.transport);
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen;
+ mDigitalClock = (DigitalClock) findViewById(R.id.time);
// Hide transport control view until we know we need to show it.
if (mTransportView != null) {
@@ -290,9 +293,19 @@ class KeyguardStatusViewManager implements OnClickListener {
/** {@inheritDoc} */
public void onResume() {
if (DEBUG) Log.v(TAG, "onResume()");
+
+ // First update the clock, if present.
+ if (mDigitalClock != null) {
+ mDigitalClock.updateTime();
+ }
+
mUpdateMonitor.registerInfoCallback(mInfoCallback);
mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
resetStatusInfo();
+ //Issue the faceunlock failure message in a centralized place
+ if (mUpdateMonitor.getMaxFaceUnlockAttemptsReached()) {
+ setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures));
+ }
}
void resetStatusInfo() {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index d7041fc..91ab053 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -81,6 +81,8 @@ public class KeyguardUpdateMonitor {
private CharSequence mTelephonySpn;
private int mFailedAttempts = 0;
+ private int mFailedFaceUnlockAttempts = 0;
+ private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15;
private boolean mClockVisible;
@@ -629,6 +631,7 @@ public class KeyguardUpdateMonitor {
public void clearFailedAttempts() {
mFailedAttempts = 0;
+ mFailedFaceUnlockAttempts = 0;
}
public void reportFailedAttempt() {
@@ -642,4 +645,12 @@ public class KeyguardUpdateMonitor {
public int getPhoneState() {
return mPhoneState;
}
+
+ public void reportFailedFaceUnlockAttempt() {
+ mFailedFaceUnlockAttempts++;
+ }
+
+ public boolean getMaxFaceUnlockAttemptsReached() {
+ return mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index ff8d5ac..4bba71b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -118,6 +118,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
| WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
+ | WindowManager.LayoutParams.FLAG_SLIPPERY
/*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
if (!mNeedsInput) {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index d1d9e9a..1e9784c 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -52,6 +52,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.IBinder;
import android.os.Parcelable;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -101,8 +102,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private View mLockScreen;
private View mUnlockScreen;
- private volatile boolean mScreenOn = false;
- private volatile boolean mWindowFocused = false;
+ private boolean mScreenOn;
+ private boolean mWindowFocused = false;
private boolean mEnableFallback = false; // assume no fallback UI until we know better
private boolean mShowLockBeforeUnlock = false;
@@ -132,10 +133,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
// So the user has a consistent amount of time when brought to the backup method from FaceLock
private final int BACKUP_LOCK_TIMEOUT = 5000;
- // Needed to keep track of failed FaceUnlock attempts
- private int mFailedFaceUnlockAttempts = 0;
- private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15;
-
/**
* The current {@link KeyguardScreen} will use this to communicate back to us.
*/
@@ -147,6 +144,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
//Also true if we've activated a phone call, either emergency dialing or incoming
//This resets when the phone is turned off with no current call
private boolean mHasOverlay;
+ //True if a dialog is currently displaying on top of this window
+ //Unlike other overlays, this does not close with a power button cycle
+ private boolean mHasDialog = false;
+ //True if this device is currently plugged in
+ private boolean mPluggedIn;
/**
@@ -309,6 +311,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mLockPatternUtils = lockPatternUtils;
mWindowController = controller;
mHasOverlay = false;
+ mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
+ mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
mUpdateMonitor.registerInfoCallback(this);
@@ -370,7 +374,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
}
- // FaceLock must be stopped if it is running
+ // FaceLock must be stopped if it is running when emergency call is pressed
stopAndUnbindFromFaceLock();
pokeWakelock(EMERGENCY_CALL_TIMEOUT);
@@ -459,7 +463,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
}
public void reportSuccessfulUnlockAttempt() {
- mFailedFaceUnlockAttempts = 0;
mLockPatternUtils.reportSuccessfulPasswordAttempt();
}
};
@@ -557,7 +560,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
if (DEBUG) Log.d(TAG, "screen off");
mScreenOn = false;
mForgotPattern = false;
- mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
+ mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE ||
+ mHasDialog;
// Emulate activity life-cycle for both lock and unlock screen.
if (mLockScreen != null) {
@@ -577,8 +581,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
* FaceLock, but only if we're not dealing with a call
*/
private void activateFaceLockIfAble() {
- final boolean tooManyFaceUnlockTries =
- (mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP);
+ final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
final boolean backupIsTimedOut =
(failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
@@ -652,8 +655,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mHasOverlay = true;
stopAndUnbindFromFaceLock();
hideFaceLockArea();
- } else if (runFaceLock) {
- activateFaceLockIfAble();
+ } else {
+ mHasDialog = false;
+ if (runFaceLock) activateFaceLockIfAble();
}
}
@@ -723,10 +727,19 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
post(mRecreateRunnable);
}
- //Ignore these events; they are implemented only because they come from the same interface
+ /** When somebody plugs in or unplugs the device, we don't want to display faceunlock */
@Override
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel)
- {}
+ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
+ mHasOverlay |= mPluggedIn != pluggedIn;
+ mPluggedIn = pluggedIn;
+ //If it's already running, don't close it down: the unplug didn't start it
+ if (!mFaceLockServiceRunning) {
+ stopAndUnbindFromFaceLock();
+ hideFaceLockArea();
+ }
+ }
+
+ //Ignore these events; they are implemented only because they come from the same interface
@Override
public void onTimeChanged() {}
@Override
@@ -842,6 +855,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
case Password:
secure = mLockPatternUtils.isLockPasswordEnabled();
break;
+ case Unknown:
+ // This means no security is set up
+ break;
default:
throw new IllegalStateException("unknown unlock mode " + unlockMode);
}
@@ -864,8 +880,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
// Re-create the unlock screen if necessary. This is primarily required to properly handle
// SIM state changes. This typically happens when this method is called by reset()
- if (mode == Mode.UnlockScreen) {
- final UnlockMode unlockMode = getUnlockMode();
+ final UnlockMode unlockMode = getUnlockMode();
+ if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
boolean restartFaceLock = stopFaceLockIfRunning();
recreateUnlockScreen(unlockMode);
@@ -1039,11 +1055,15 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
break;
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
- // "forgot pattern" button is only available in the pattern mode...
- if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
- currentMode = UnlockMode.Account;
+ if (mLockPatternUtils.isLockPatternEnabled()) {
+ // "forgot pattern" button is only available in the pattern mode...
+ if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
+ currentMode = UnlockMode.Account;
+ } else {
+ currentMode = UnlockMode.Pattern;
+ }
} else {
- currentMode = UnlockMode.Pattern;
+ currentMode = UnlockMode.Unknown;
}
break;
default:
@@ -1054,6 +1074,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
}
private void showDialog(String title, String message) {
+ mHasDialog = true;
final AlertDialog dialog = new AlertDialog.Builder(mContext)
.setTitle(title)
.setMessage(message)
@@ -1389,7 +1410,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
@Override
public void reportFailedAttempt() {
if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
- mFailedFaceUnlockAttempts++;
+ mUpdateMonitor.reportFailedFaceUnlockAttempt();
hideFaceLockArea(); // Expose fallback
stopAndUnbindFromFaceLock();
mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 24a2420..3384661 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -23,6 +23,8 @@ import com.android.internal.widget.WaveView;
import com.android.internal.widget.multiwaveview.MultiWaveView;
import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -34,6 +36,7 @@ import android.view.ViewGroup;
import android.widget.*;
import android.util.Log;
import android.media.AudioManager;
+import android.os.RemoteException;
import android.provider.MediaStore;
import android.provider.Settings;
@@ -229,8 +232,16 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
// Start the Camera
Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- mCallback.goToUnlockScreen();
+ try {
+ ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+ } catch (RemoteException e) {
+ Log.w(TAG, "can't dismiss keyguard on launch");
+ }
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Camera application not found");
+ }
} else {
toggleRingMode();
mUnlockWidgetMethods.updateResources();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
index abed18f..83f7788 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
@@ -52,8 +52,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
}
public void preDispatchKeyEvent(KeyEvent event) {
- getAudioManager().preDispatchKeyEvent(event.getKeyCode(),
- AudioManager.USE_DEFAULT_STREAM_TYPE);
+ getAudioManager().preDispatchKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
}
public boolean dispatchKeyEvent(KeyEvent event) {
@@ -79,7 +78,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- getAudioManager().handleKeyDown(keyCode, AudioManager.USE_DEFAULT_STREAM_TYPE);
+ getAudioManager().handleKeyDown(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
return true;
}
@@ -197,8 +196,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
AudioManager audioManager = (AudioManager)mContext.getSystemService(
Context.AUDIO_SERVICE);
if (audioManager != null) {
- getAudioManager().handleKeyUp(keyCode,
- AudioManager.USE_DEFAULT_STREAM_TYPE);
+ getAudioManager().handleKeyUp(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
}
}
return true;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index f1fe43b..301dbf5 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -115,6 +115,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
final TypedValue mMinWidthMajor = new TypedValue();
final TypedValue mMinWidthMinor = new TypedValue();
+ TypedValue mFixedWidthMajor;
+ TypedValue mFixedWidthMinor;
+ TypedValue mFixedHeightMajor;
+ TypedValue mFixedHeightMinor;
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
@@ -1416,7 +1420,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// doesn't have one of these. In this case, we execute it here and
// eat the event instead, because we have mVolumeControlStreamType
// and they don't.
- getAudioManager().handleKeyDown(keyCode, mVolumeControlStreamType);
+ getAudioManager().handleKeyDown(event, mVolumeControlStreamType);
return true;
}
@@ -1478,7 +1482,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// doesn't have one of these. In this case, we execute it here and
// eat the event instead, because we have mVolumeControlStreamType
// and they don't.
- getAudioManager().handleKeyUp(keyCode, mVolumeControlStreamType);
+ getAudioManager().handleKeyUp(event, mVolumeControlStreamType);
return true;
}
@@ -2088,6 +2092,44 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
final int widthMode = getMode(widthMeasureSpec);
+ final int heightMode = getMode(heightMeasureSpec);
+
+ boolean fixedWidth = false;
+ if (widthMode == AT_MOST) {
+ final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor;
+ if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
+ fixedWidth = true;
+ final int w;
+ if (tvw.type == TypedValue.TYPE_DIMENSION) {
+ w = (int) tvw.getDimension(metrics);
+ } else if (tvw.type == TypedValue.TYPE_FRACTION) {
+ w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels);
+ } else {
+ w = 0;
+ }
+
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(w, widthSize), EXACTLY);
+ }
+ }
+
+ if (heightMode == AT_MOST) {
+ final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor;
+ if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
+ final int h;
+ if (tvh.type == TypedValue.TYPE_DIMENSION) {
+ h = (int) tvh.getDimension(metrics);
+ } else if (tvh.type == TypedValue.TYPE_FRACTION) {
+ h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels);
+ } else {
+ h = 0;
+ }
+
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ heightMeasureSpec =
+ MeasureSpec.makeMeasureSpec(Math.min(h, heightSize), EXACTLY);
+ }
+ }
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -2096,21 +2138,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
- final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor;
-
- if (widthMode == AT_MOST && tv.type != TypedValue.TYPE_NULL) {
- final int min;
- if (tv.type == TypedValue.TYPE_DIMENSION) {
- min = (int)tv.getDimension(metrics);
- } else if (tv.type == TypedValue.TYPE_FRACTION) {
- min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels);
- } else {
- min = 0;
- }
+ if (!fixedWidth && widthMode == AT_MOST) {
+ final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor;
+ if (tv.type != TypedValue.TYPE_NULL) {
+ final int min;
+ if (tv.type == TypedValue.TYPE_DIMENSION) {
+ min = (int)tv.getDimension(metrics);
+ } else if (tv.type == TypedValue.TYPE_FRACTION) {
+ min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels);
+ } else {
+ min = 0;
+ }
- if (width < min) {
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
- measure = true;
+ if (width < min) {
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
+ measure = true;
+ }
}
}
@@ -2571,6 +2614,26 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
a.getValue(com.android.internal.R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
a.getValue(com.android.internal.R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
+ if (a.hasValue(com.android.internal.R.styleable.Window_windowFixedWidthMajor)) {
+ if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
+ a.getValue(com.android.internal.R.styleable.Window_windowFixedWidthMajor,
+ mFixedWidthMajor);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Window_windowFixedWidthMinor)) {
+ if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
+ a.getValue(com.android.internal.R.styleable.Window_windowFixedWidthMinor,
+ mFixedWidthMinor);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Window_windowFixedHeightMajor)) {
+ if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
+ a.getValue(com.android.internal.R.styleable.Window_windowFixedHeightMajor,
+ mFixedHeightMajor);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Window_windowFixedHeightMinor)) {
+ if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
+ a.getValue(com.android.internal.R.styleable.Window_windowFixedHeightMinor,
+ mFixedHeightMinor);
+ }
final Context context = getContext();
final int targetSdk = context.getApplicationInfo().targetSdkVersion;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0de76a7..8f35afb 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -45,6 +45,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.LocalPowerManager;
+import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
@@ -61,7 +62,6 @@ import com.android.internal.app.ShutdownThread;
import com.android.internal.policy.PolicyManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.ITelephony;
-import com.android.internal.view.BaseInputHandler;
import com.android.internal.widget.PointerLocationView;
import android.util.DisplayMetrics;
@@ -75,8 +75,8 @@ import android.view.IApplicationToken;
import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
-import android.view.InputQueue;
-import android.view.InputHandler;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -164,6 +164,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
+ // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
+ static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
+
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -283,7 +286,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
boolean mEnableShiftMenuBugReports = false;
-
+
+ boolean mHeadless;
boolean mSafeMode;
WindowState mStatusBar = null;
boolean mStatusBarCanHide;
@@ -316,7 +320,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mSystemReady;
boolean mSystemBooted;
boolean mHdmiPlugged;
- int mUiMode = Configuration.UI_MODE_TYPE_NORMAL;
+ int mUiMode;
int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
int mLidOpenRotation;
int mCarDockRotation;
@@ -348,25 +352,32 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mFocusedWindow;
IApplicationToken mFocusedApp;
- private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
+ final class PointerLocationInputEventReceiver extends InputEventReceiver {
+ public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper) {
+ super(inputChannel, looper);
+ }
+
@Override
- public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
+ public void onInputEvent(InputEvent event) {
boolean handled = false;
try {
- if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ if (event instanceof MotionEvent
+ && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ final MotionEvent motionEvent = (MotionEvent)event;
synchronized (mLock) {
if (mPointerLocationView != null) {
- mPointerLocationView.addPointerEvent(event);
+ mPointerLocationView.addPointerEvent(motionEvent);
handled = true;
}
}
}
} finally {
- finishedCallback.finished(handled);
+ finishInputEvent(event, handled);
}
}
- };
-
+ }
+ PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
+
// The current size of the screen; really; (ir)regardless of whether the status
// bar can be hidden or not
int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
@@ -426,6 +437,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLockScreenTimeout;
boolean mLockScreenTimerActive;
+ // visual screen saver support
+ int mScreenSaverTimeout = 0;
+ boolean mScreenSaverEnabledByUser = false;
+ boolean mScreenSaverMayRun = true; // false if a wakelock is held
+ boolean mPluggedIn;
+
// Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
int mEndcallBehavior;
@@ -488,6 +505,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
resolver.registerContentObserver(Settings.System.getUriFor(
"fancy_rotation_anim"), false, this);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SCREENSAVER_ENABLED), false, this);
+ if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ "screensaver_timeout"), false, this);
+ } // otherwise SCREEN_OFF_TIMEOUT will do nicely
updateSettings();
}
@@ -664,7 +687,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext);
}
- final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
+ final boolean keyguardShowing = keyguardIsShowingTq();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
if (keyguardShowing) {
// since it took two seconds of long press to bring this up,
@@ -761,7 +784,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
mPowerManager = powerManager;
- mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+ mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
+ if (!mHeadless) {
+ // don't create KeyguardViewMediator if headless
+ mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+ }
mHandler = new Handler();
mOrientationListener = new MyOrientationListener(mContext);
try {
@@ -771,6 +798,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
settingsObserver.observe();
mShortcutManager = new ShortcutManager(context, mHandler);
mShortcutManager.observe();
+ mUiMode = context.getResources().getInteger(
+ com.android.internal.R.integer.config_defaultUiModeType);
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -816,6 +845,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
+ // watch the plug to know whether to trigger the screen saver
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ intent = context.registerReceiver(mPowerReceiver, filter);
+ if (intent != null) {
+ mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
+ }
+
mVibrator = new Vibrator();
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
@@ -964,6 +1001,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHasSoftInput = hasSoftInput;
updateRotation = true;
}
+
+ mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
+ Settings.Secure.SCREENSAVER_ENABLED, 1);
+
+ if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
+ mScreenSaverTimeout = Settings.Secure.getInt(resolver,
+ "screensaver_timeout", 0);
+ } else {
+ mScreenSaverTimeout = Settings.System.getInt(resolver,
+ Settings.System.SCREEN_OFF_TIMEOUT, 0);
+ if (mScreenSaverTimeout > 0) {
+ // We actually want to activate the screensaver just before the
+ // power manager's screen timeout
+ mScreenSaverTimeout -= 5000;
+ }
+ }
+ updateScreenSaverTimeoutLocked();
}
if (updateRotation) {
updateRotation(true);
@@ -987,9 +1041,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPointerLocationInputChannel == null) {
try {
mPointerLocationInputChannel =
- mWindowManager.monitorInput("PointerLocationView");
- InputQueue.registerInputChannel(mPointerLocationInputChannel,
- mPointerLocationInputHandler, mHandler.getLooper().getQueue());
+ mWindowManager.monitorInput("PointerLocationView");
+ mPointerLocationInputEventReceiver =
+ new PointerLocationInputEventReceiver(
+ mPointerLocationInputChannel, mHandler.getLooper());
} catch (RemoteException ex) {
Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.",
ex);
@@ -997,8 +1052,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
if (removeView != null) {
+ if (mPointerLocationInputEventReceiver != null) {
+ mPointerLocationInputEventReceiver.dispose();
+ mPointerLocationInputEventReceiver = null;
+ }
if (mPointerLocationInputChannel != null) {
- InputQueue.unregisterInputChannel(mPointerLocationInputChannel);
mPointerLocationInputChannel.dispose();
mPointerLocationInputChannel = null;
}
@@ -1458,12 +1516,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
static ITelephony getTelephonyService() {
- ITelephony telephonyService = ITelephony.Stub.asInterface(
+ return ITelephony.Stub.asInterface(
ServiceManager.checkService(Context.TELEPHONY_SERVICE));
- if (telephonyService == null) {
- Log.w(TAG, "Unable to find ITelephony interface.");
- }
- return telephonyService;
}
static IAudioService getAudioService() {
@@ -1786,7 +1840,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
- if (mKeyguardMediator.isShowingAndNotHidden()) {
+ if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
@@ -1829,13 +1883,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* to determine when the nav bar should be shown and prevent applications from
* receiving those touches.
*/
- final InputHandler mHideNavInputHandler = new BaseInputHandler() {
+ final class HideNavInputEventReceiver extends InputEventReceiver {
+ public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
+ super(inputChannel, looper);
+ }
+
@Override
- public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
+ public void onInputEvent(InputEvent event) {
boolean handled = false;
try {
- if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (event instanceof MotionEvent
+ && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ final MotionEvent motionEvent = (MotionEvent)event;
+ if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
// When the user taps down, we re-show the nav bar.
boolean changed = false;
synchronized (mLock) {
@@ -1872,9 +1932,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
} finally {
- finishedCallback.finished(handled);
+ finishInputEvent(event, handled);
}
}
+ }
+ final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
+ new InputEventReceiver.Factory() {
+ @Override
+ public InputEventReceiver createInputEventReceiver(
+ InputChannel inputChannel, Looper looper) {
+ return new HideNavInputEventReceiver(inputChannel, looper);
+ }
};
@Override
@@ -1938,7 +2006,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else if (mHideNavFakeWindow == null) {
mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
- mHandler.getLooper(), mHideNavInputHandler,
+ mHandler.getLooper(), mHideNavInputEventReceiverFactory,
"hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
0, false, false, true);
}
@@ -2330,8 +2398,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/** {@inheritDoc} */
- public int finishLayoutLw() {
- return 0;
+ @Override
+ public void finishLayoutLw() {
+ return;
}
/** {@inheritDoc} */
@@ -2520,6 +2589,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+ // do nothing if headless
+ if (mHeadless) return;
+
// lid changed state
mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
updateKeyboardVisibility();
@@ -2716,9 +2788,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the same as if it were open and in front.
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
- final boolean keyguardActive = (isScreenOn ?
- mKeyguardMediator.isShowingAndNotHidden() :
- mKeyguardMediator.isShowing());
+ final boolean keyguardActive = (mKeyguardMediator == null ? false :
+ (isScreenOn ?
+ mKeyguardMediator.isShowingAndNotHidden() :
+ mKeyguardMediator.isShowing()));
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
@@ -2735,6 +2808,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
+ if (keyCode == KeyEvent.KEYCODE_POWER) {
+ policyFlags |= WindowManagerPolicy.FLAG_WAKE;
+ }
+ final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
+ | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
+
// Basic policy based on screen state and keyguard.
// FIXME: This policy isn't quite correct. We shouldn't care whether the screen
// is on or off, really. We should care about whether the device is in an
@@ -2744,16 +2823,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the device some other way (which is why we have an exemption here for injected
// events).
int result;
- if (isScreenOn || isInjected) {
+ if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
// When the screen is on or if the key is injected pass the key to the application.
result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
result = 0;
-
- final boolean isWakeKey = (policyFlags
- & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
if (down && isWakeKey) {
if (keyguardActive) {
// If the keyguard is showing, let it decide what to do with the wake key.
@@ -2983,7 +3059,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean isWakeMotion = (policyFlags
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
if (isWakeMotion) {
- if (mKeyguardMediator.isShowing()) {
+ if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
// If the keyguard is showing, let it decide what to do with the wake motion.
mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
} else {
@@ -3035,6 +3111,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
+ BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+ mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
+ if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
+ }
+ }
+ };
+
/** {@inheritDoc} */
public void screenTurnedOff(int why) {
EventLog.writeEvent(70000, 0);
@@ -3042,10 +3127,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOnEarly = false;
mScreenOnFully = false;
}
- mKeyguardMediator.onScreenTurnedOff(why);
+ if (mKeyguardMediator != null) {
+ mKeyguardMediator.onScreenTurnedOff(why);
+ }
synchronized (mLock) {
updateOrientationListenerLp();
updateLockScreenTimeout();
+ updateScreenSaverTimeoutLocked();
}
}
@@ -3058,31 +3146,33 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Slog.i(TAG, "Screen turning on...", here);
}
if (screenOnListener != null) {
- mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
- @Override public void onShown(IBinder windowToken) {
- if (windowToken != null) {
- try {
- mWindowManager.waitForWindowDrawn(windowToken,
- new IRemoteCallback.Stub() {
- @Override public void sendResult(Bundle data) {
- Slog.i(TAG, "Lock screen displayed!");
- screenOnListener.onScreenOn();
- synchronized (mLock) {
- mScreenOnFully = true;
+ if (mKeyguardMediator != null) {
+ mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
+ @Override public void onShown(IBinder windowToken) {
+ if (windowToken != null) {
+ try {
+ mWindowManager.waitForWindowDrawn(windowToken,
+ new IRemoteCallback.Stub() {
+ @Override public void sendResult(Bundle data) {
+ Slog.i(TAG, "Lock screen displayed!");
+ screenOnListener.onScreenOn();
+ synchronized (mLock) {
+ mScreenOnFully = true;
+ }
}
- }
- });
- } catch (RemoteException e) {
- }
- } else {
- Slog.i(TAG, "No lock screen!");
- screenOnListener.onScreenOn();
- synchronized (mLock) {
- mScreenOnFully = true;
+ });
+ } catch (RemoteException e) {
+ }
+ } else {
+ Slog.i(TAG, "No lock screen!");
+ screenOnListener.onScreenOn();
+ synchronized (mLock) {
+ mScreenOnFully = true;
+ }
}
}
- }
- });
+ });
+ }
} else {
synchronized (mLock) {
mScreenOnFully = true;
@@ -3092,6 +3182,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOnEarly = true;
updateOrientationListenerLp();
updateLockScreenTimeout();
+ updateScreenSaverTimeoutLocked();
}
}
@@ -3107,15 +3198,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void enableKeyguard(boolean enabled) {
- mKeyguardMediator.setKeyguardEnabled(enabled);
+ if (mKeyguardMediator != null) {
+ mKeyguardMediator.setKeyguardEnabled(enabled);
+ }
}
/** {@inheritDoc} */
public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
- mKeyguardMediator.verifyUnlock(callback);
+ if (mKeyguardMediator != null) {
+ mKeyguardMediator.verifyUnlock(callback);
+ }
}
private boolean keyguardIsShowingTq() {
+ if (mKeyguardMediator == null) return false;
return mKeyguardMediator.isShowingAndNotHidden();
}
@@ -3127,11 +3223,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public boolean isKeyguardSecure() {
+ if (mKeyguardMediator == null) return false;
return mKeyguardMediator.isSecure();
}
/** {@inheritDoc} */
public boolean inKeyguardRestrictedKeyInputMode() {
+ if (mKeyguardMediator == null) return false;
return mKeyguardMediator.isInputRestricted();
}
@@ -3387,9 +3485,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void systemReady() {
- // tell the keyguard
- mKeyguardMediator.onSystemReady();
- android.os.SystemProperties.set("dev.bootcomplete", "1");
+ if (mKeyguardMediator != null) {
+ // tell the keyguard
+ mKeyguardMediator.onSystemReady();
+ }
synchronized (mLock) {
updateOrientationListenerLp();
mSystemReady = true;
@@ -3412,6 +3511,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void showBootMessage(final CharSequence msg, final boolean always) {
+ if (mHeadless) return;
mHandler.post(new Runnable() {
@Override public void run() {
if (mBootMsgDialog == null) {
@@ -3490,13 +3590,94 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
+
+ synchronized (mLock) {
+ // Only posts messages; holds no additional locks.
+ updateScreenSaverTimeoutLocked();
+ }
+ }
+
+ Runnable mScreenSaverActivator = new Runnable() {
+ public void run() {
+ if (!(mScreenSaverMayRun && mScreenOnEarly)) {
+ Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
+ return;
+ }
+ if (!mPluggedIn) {
+ if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in");
+ return;
+ }
+ // Quick fix for automation tests.
+ // The correct fix is to move this triggering logic to PowerManager, where more complete
+ // information about wakelocks (including StayOnWhilePluggedIn) is available.
+ if (Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ BatteryManager.BATTERY_PLUGGED_AC) != 0) {
+ Log.v(TAG, "mScreenSaverActivator: not running screen saver when STAY_ON_WHILE_PLUGGED_IN");
+ return;
+ }
+
+ if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
+
+ try {
+ String component = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
+ if (component == null) {
+ component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
+ }
+ if (component != null) {
+ // dismiss the notification shade, recents, etc.
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT));
+
+ ComponentName cn = ComponentName.unflattenFromString(component);
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .setComponent(cn)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_FROM_BACKGROUND
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
+ );
+ mContext.startActivity(intent);
+ } else {
+ Log.e(TAG, "Couldn't start screen saver: none selected");
+ }
+ } catch (android.content.ActivityNotFoundException exc) {
+ // no screensaver? give up
+ Log.e(TAG, "Couldn't start screen saver: none installed");
+ }
+ }
+ };
+
+ // Must call while holding mLock
+ private void updateScreenSaverTimeoutLocked() {
+ if (mScreenSaverActivator == null) return;
+
+ mHandler.removeCallbacks(mScreenSaverActivator);
+ if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) {
+ if (localLOGV)
+ Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
+ mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
+ } else {
+ if (localLOGV) {
+ if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0)
+ Log.v(TAG, "screen saver disabled by user");
+ else if (!mScreenOnEarly)
+ Log.v(TAG, "screen saver disabled while screen off");
+ else
+ Log.v(TAG, "screen saver disabled by wakelock");
+ }
+ }
}
Runnable mScreenLockTimeout = new Runnable() {
public void run() {
synchronized (this) {
if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
- mKeyguardMediator.doKeyguardTimeout();
+ if (mKeyguardMediator != null) {
+ mKeyguardMediator.doKeyguardTimeout();
+ }
mLockScreenTimerActive = false;
}
}
@@ -3510,7 +3691,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void updateLockScreenTimeout() {
synchronized (mScreenLockTimeout) {
- boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && mKeyguardMediator.isSecure());
+ boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
+ mKeyguardMediator != null && mKeyguardMediator.isSecure());
if (mLockScreenTimerActive != enable) {
if (enable) {
if (localLOGV) Log.v(TAG, "setting lockscreen timer");
@@ -3701,14 +3883,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
public void screenOnStartedLw() {
+ // The window manager has just grabbed a wake lock. This is our cue to disable the screen
+ // saver.
+ synchronized (mLock) {
+ mScreenSaverMayRun = false;
+ }
}
public void screenOnStoppedLw() {
if (mPowerManager.isScreenOn()) {
- if (!mKeyguardMediator.isShowingAndNotHidden()) {
+ if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
long curTime = SystemClock.uptimeMillis();
mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
}
+
+ synchronized (mLock) {
+ // even if the keyguard is up, now that all the wakelocks have been released, we
+ // should re-enable the screen saver
+ mScreenSaverMayRun = true;
+ updateScreenSaverTimeoutLocked();
+ }
}
}