summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/BurnInProtectionHelper.java201
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java25
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java96
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java13
5 files changed, 321 insertions, 20 deletions
diff --git a/policy/src/com/android/internal/policy/impl/BurnInProtectionHelper.java b/policy/src/com/android/internal/policy/impl/BurnInProtectionHelper.java
new file mode 100644
index 0000000..ed9a16f
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/BurnInProtectionHelper.java
@@ -0,0 +1,201 @@
+package com.android.internal.policy.impl;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.Build;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.Display;
+
+import com.android.server.LocalServices;
+
+import java.io.PrintWriter;
+import java.util.concurrent.TimeUnit;
+
+public class BurnInProtectionHelper implements DisplayManager.DisplayListener {
+ private static final String TAG = "BurnInProtection";
+
+ // Default value when max burnin radius is not set.
+ public static final int BURN_IN_MAX_RADIUS_DEFAULT = -1;
+
+ private static final long BURNIN_PROTECTION_WAKEUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
+ private static final long BURNIN_PROTECTION_MINIMAL_INTERVAL_MS = TimeUnit.SECONDS.toMillis(10);
+
+ private static final String ACTION_BURN_IN_PROTECTION =
+ "android.internal.policy.action.BURN_IN_PROTECTION";
+
+ private static final int BURN_IN_SHIFT_STEP = 2;
+
+ private boolean mBurnInProtectionActive;
+
+ private final int mMinHorizontalBurnInOffset;
+ private final int mMaxHorizontalBurnInOffset;
+ private final int mMinVerticalBurnInOffset;
+ private final int mMaxVerticalBurnInOffset;
+
+ private final int mBurnInRadiusMaxSquared;
+
+ private int mLastBurnInXOffset = 0;
+ /* 1 means increasing, -1 means decreasing */
+ private int mXOffsetDirection = 1;
+ private int mLastBurnInYOffset = 0;
+ /* 1 means increasing, -1 means decreasing */
+ private int mYOffsetDirection = 1;
+
+ private final AlarmManager mAlarmManager;
+ private final PendingIntent mBurnInProtectionIntent;
+ private final DisplayManagerInternal mDisplayManagerInternal;
+ private final Display mDisplay;
+
+ private BroadcastReceiver mBurnInProtectionReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateBurnInProtection();
+ }
+ };
+
+ public BurnInProtectionHelper(Context context, int minHorizontalOffset,
+ int maxHorizontalOffset, int minVerticalOffset, int maxVerticalOffset,
+ int maxOffsetRadius) {
+ final Resources resources = context.getResources();
+ mMinHorizontalBurnInOffset = minHorizontalOffset;
+ mMaxHorizontalBurnInOffset = maxHorizontalOffset;
+ mMinVerticalBurnInOffset = minVerticalOffset;
+ mMaxVerticalBurnInOffset = maxHorizontalOffset;
+ if (maxOffsetRadius != BURN_IN_MAX_RADIUS_DEFAULT) {
+ mBurnInRadiusMaxSquared = maxOffsetRadius * maxOffsetRadius;
+ } else {
+ mBurnInRadiusMaxSquared = BURN_IN_MAX_RADIUS_DEFAULT;
+ }
+
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ context.registerReceiver(mBurnInProtectionReceiver,
+ new IntentFilter(ACTION_BURN_IN_PROTECTION));
+ Intent intent = new Intent(ACTION_BURN_IN_PROTECTION);
+ intent.setPackage(context.getPackageName());
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mBurnInProtectionIntent = PendingIntent.getBroadcast(context, 0,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ DisplayManager displayManager =
+ (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ displayManager.registerDisplayListener(this, null /* handler */);
+ }
+
+ public void startBurnInProtection() {
+ if (!mBurnInProtectionActive) {
+ mBurnInProtectionActive = true;
+ updateBurnInProtection();
+ }
+ }
+
+ private void updateBurnInProtection() {
+ if (mBurnInProtectionActive) {
+ adjustOffsets();
+ mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(),
+ mLastBurnInXOffset, mLastBurnInYOffset);
+ // Next adjustment at least ten seconds in the future.
+ long next = SystemClock.elapsedRealtime() + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
+ // And aligned to the minute.
+ next = next - next % BURNIN_PROTECTION_WAKEUP_INTERVAL_MS
+ + BURNIN_PROTECTION_WAKEUP_INTERVAL_MS;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mBurnInProtectionIntent);
+ } else {
+ mAlarmManager.cancel(mBurnInProtectionIntent);
+ mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), 0, 0);
+ }
+ }
+
+ public void cancelBurnInProtection() {
+ if (mBurnInProtectionActive) {
+ mBurnInProtectionActive = false;
+ updateBurnInProtection();
+ }
+ }
+
+ /**
+ * Gently shifts current burn-in offsets, minimizing the change for the user.
+ *
+ * Shifts are applied in following fashion:
+ * 1) shift horizontally from minimum to the maximum;
+ * 2) shift vertically by one from minimum to the maximum;
+ * 3) shift horizontally from maximum to the minimum;
+ * 4) shift vertically by one from minimum to the maximum.
+ * 5) if you reach the maximum vertically, start shifting back by one from maximum to minimum.
+ *
+ * On top of that, stay within specified radius. If the shift distance from the center is
+ * higher than the radius, skip these values and go the next position that is within the radius.
+ */
+ private void adjustOffsets() {
+ do {
+ // By default, let's just shift the X offset.
+ final int xChange = mXOffsetDirection * BURN_IN_SHIFT_STEP;
+ mLastBurnInXOffset += xChange;
+ if (mLastBurnInXOffset > mMaxHorizontalBurnInOffset
+ || mLastBurnInXOffset < mMinHorizontalBurnInOffset) {
+ // Whoops, we went too far horizontally. Let's retract..
+ mLastBurnInXOffset -= xChange;
+ // change horizontal direction..
+ mXOffsetDirection *= -1;
+ // and let's shift the Y offset.
+ final int yChange = mYOffsetDirection * BURN_IN_SHIFT_STEP;
+ mLastBurnInYOffset += yChange;
+ if (mLastBurnInYOffset > mMaxVerticalBurnInOffset
+ || mLastBurnInYOffset < mMinVerticalBurnInOffset) {
+ // Whoops, we went to far vertically. Let's retract..
+ mLastBurnInYOffset -= yChange;
+ // and change vertical direction.
+ mYOffsetDirection *= -1;
+ }
+ }
+ // If we are outside of the radius, let's try again.
+ } while (mBurnInRadiusMaxSquared != BURN_IN_MAX_RADIUS_DEFAULT
+ && mLastBurnInXOffset * mLastBurnInXOffset + mLastBurnInYOffset * mLastBurnInYOffset
+ > mBurnInRadiusMaxSquared);
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + TAG);
+ prefix += " ";
+ pw.println(prefix + "mBurnInProtectionActive=" + mBurnInProtectionActive);
+ pw.println(prefix + "mHorizontalBurnInOffsetsBounds=(" + mMinHorizontalBurnInOffset + ", "
+ + mMaxHorizontalBurnInOffset + ")");
+ pw.println(prefix + "mVerticalBurnInOffsetsBounds=(" + mMinVerticalBurnInOffset + ", "
+ + mMaxVerticalBurnInOffset + ")");
+ pw.println(prefix + "mBurnInRadiusMaxSquared=" + mBurnInRadiusMaxSquared);
+ pw.println(prefix + "mLastBurnInOffset=(" + mLastBurnInXOffset + ", "
+ + mLastBurnInYOffset + ")");
+ pw.println(prefix + "mOfsetChangeDirections=(" + mXOffsetDirection + ", "
+ + mYOffsetDirection + ")");
+ }
+
+ @Override
+ public void onDisplayAdded(int i) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int i) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == mDisplay.getDisplayId()) {
+ if (mDisplay.getState() == Display.STATE_DOZE
+ || mDisplay.getState() == Display.STATE_DOZE_SUSPEND) {
+ startBurnInProtection();
+ } else {
+ cancelBurnInProtection();
+ }
+ }
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index b0b2886..20a2c9f 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -100,6 +100,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private static final String GLOBAL_ACTION_KEY_USERS = "users";
private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
+ private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
private final Context mContext;
private final WindowManagerFuncs mWindowManagerFuncs;
@@ -291,6 +292,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
mItems.add(getLockdownAction());
+ } else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
+ mItems.add(getVoiceAssistAction());
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -436,6 +439,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
};
}
+ private Action getVoiceAssistAction() {
+ return new SinglePressAction(com.android.internal.R.drawable.ic_voice_search,
+ R.string.global_action_voice_assist) {
+ @Override
+ public void onPress() {
+ Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mContext.startActivity(intent);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+ };
+ }
+
private Action getLockdownAction() {
return new SinglePressAction(com.android.internal.R.drawable.ic_lock_lock,
R.string.global_action_lockdown) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index b4811da..cd26c31 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -4159,12 +4159,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return mMediaController;
}
- private boolean isTranslucent() {
- TypedArray a = getWindowStyle();
- return a.getBoolean(a.getResourceId(
- R.styleable.Window_windowIsTranslucent, 0), false);
- }
-
@Override
public void setEnterTransition(Transition enterTransition) {
mEnterTransition = enterTransition;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 345520a..f2578a5 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -47,6 +47,7 @@ import android.media.IAudioService;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.session.MediaSessionLegacyHelper;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.FactoryTest;
@@ -91,6 +92,7 @@ import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewRootImpl;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -153,6 +155,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
+ static final int SHORT_PRESS_POWER_GO_HOME = 4;
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
@@ -251,6 +254,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
SearchManager mSearchManager;
AccessibilityManager mAccessibilityManager;
+ BurnInProtectionHelper mBurnInProtectionHelper;
// Vibrator pattern for haptic feedback of a long press.
long[] mLongPressVibePattern;
@@ -534,6 +538,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mAllowTheaterModeWakeFromLidSwitch;
private boolean mAllowTheaterModeWakeFromWakeGesture;
+ // Whether to support long press from power button in non-interactive mode
+ private boolean mSupportLongPressPowerWhenNonInteractive;
+
// Whether to go to sleep entering theater mode from power button
private boolean mGoToSleepOnButtonPressTheaterMode;
@@ -885,12 +892,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else {
wakeUpFromPowerKey(event.getDownTime());
- final int maxCount = getMaxMultiPressPowerCount();
- if (maxCount <= 1) {
- mPowerKeyHandled = true;
- } else {
+ if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
+ Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
mBeganFromNonInteractive = true;
+ } else {
+ final int maxCount = getMaxMultiPressPowerCount();
+
+ if (maxCount <= 1) {
+ mPowerKeyHandled = true;
+ } else {
+ mBeganFromNonInteractive = true;
+ }
}
}
}
@@ -971,6 +987,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
launchHomeFromHotKey();
break;
+ case SHORT_PRESS_POWER_GO_HOME:
+ launchHomeFromHotKey();
+ break;
}
}
}
@@ -1170,6 +1189,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
+ private boolean isRoundWindow() {
+ return mContext.getResources().getBoolean(com.android.internal.R.bool.config_windowIsRound)
+ || (Build.HARDWARE.contains("goldfish")
+ && SystemProperties.getBoolean(ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false));
+ }
+
/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
@@ -1180,6 +1205,41 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
+ // Init display burn-in protection
+ boolean burnInProtectionEnabled = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableBurnInProtection);
+ // Allow a system property to override this. Used by developer settings.
+ boolean burnInProtectionDevMode =
+ SystemProperties.getBoolean("persist.debug.force_burn_in", false);
+ if (burnInProtectionEnabled || burnInProtectionDevMode) {
+ final int minHorizontal;
+ final int maxHorizontal;
+ final int minVertical;
+ final int maxVertical;
+ final int maxRadius;
+ if (burnInProtectionDevMode) {
+ minHorizontal = -8;
+ maxHorizontal = 8;
+ minVertical = -8;
+ maxVertical = -4;
+ maxRadius = (isRoundWindow()) ? 6 : -1;
+ } else {
+ Resources resources = context.getResources();
+ minHorizontal = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
+ maxHorizontal = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
+ minVertical = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
+ maxVertical = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
+ maxRadius = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxRadius);
+ }
+ mBurnInProtectionHelper = new BurnInProtectionHelper(
+ context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
+ }
+
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
mOrientationListener = new MyOrientationListener(mContext, mHandler);
@@ -1253,6 +1313,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
+ mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
+
mShortPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnPowerBehavior);
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
@@ -2991,7 +3054,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
- startDockOrHome();
+ startDockOrHome(true /*fromHomeKey*/);
}
}
});
@@ -3009,7 +3072,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
// Otherwise, just launch Home
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
- startDockOrHome();
+ startDockOrHome(true /*fromHomeKey*/);
}
}
}
@@ -5821,19 +5884,31 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return null;
}
- void startDockOrHome() {
+ void startDockOrHome(boolean fromHomeKey) {
awakenDreams();
Intent dock = createHomeDockIntent();
if (dock != null) {
try {
+ if (fromHomeKey) {
+ dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
+ }
mContext.startActivityAsUser(dock, UserHandle.CURRENT);
return;
} catch (ActivityNotFoundException e) {
}
}
- mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
+ Intent intent;
+
+ if (fromHomeKey) {
+ intent = new Intent(mHomeIntent);
+ intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
+ } else {
+ intent = mHomeIntent;
+ }
+
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
/**
@@ -5848,7 +5923,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {
}
sendCloseSystemWindows();
- startDockOrHome();
+ startDockOrHome(false /*fromHomeKey*/);
} else {
// This code brings home to the front or, if it is already
// at the front, puts the device to sleep.
@@ -6382,5 +6457,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mOrientationListener != null) {
mOrientationListener.dump(pw, prefix);
}
+ if (mBurnInProtectionHelper != null) {
+ mBurnInProtectionHelper.dump(prefix, pw);
+ }
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 6e8f550..6c98e50 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.IBinder;
@@ -27,9 +28,6 @@ import com.android.internal.policy.IKeyguardShowCallback;
* local or remote instances of keyguard.
*/
public class KeyguardServiceDelegate {
- public static final String KEYGUARD_PACKAGE = "com.android.systemui";
- public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
-
private static final String TAG = "KeyguardServiceDelegate";
private static final boolean DEBUG = true;
@@ -111,10 +109,15 @@ public class KeyguardServiceDelegate {
public void bindService(Context context) {
Intent intent = new Intent();
- intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
+ final Resources resources = context.getApplicationContext().getResources();
+
+ final ComponentName keyguardComponent = ComponentName.unflattenFromString(
+ resources.getString(com.android.internal.R.string.config_keyguardComponent));
+ intent.setComponent(keyguardComponent);
+
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
- Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
+ Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;