summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/statusbar
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/statusbar')
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java1
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java151
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java298
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java290
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java284
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java127
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java4
33 files changed, 1301 insertions, 624 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 16301fc..dba74de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -360,6 +360,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
} else {
updateBackground();
}
+ setOutlineAlpha(dark ? 0f : 1f);
}
public void setShowingLegacyBackground(boolean showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 614a603..564fbb5 100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -97,6 +97,7 @@ import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DejankUtils;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
@@ -181,13 +182,7 @@ public abstract class BaseStatusBar extends SystemUI implements
// on-screen navigation buttons
protected NavigationBarView mNavigationBarView = null;
- protected Boolean mScreenOn;
-
- // The second field is a bit different from the first one because it only listens to screen on/
- // screen of events from Keyguard. We need this so we don't have a race condition with the
- // broadcast. In the future, we should remove the first field altogether and rename the second
- // field.
- protected boolean mScreenOnFromKeyguard;
+ protected boolean mDeviceInteractive;
protected boolean mVisible;
@@ -1532,6 +1527,15 @@ public abstract class BaseStatusBar extends SystemUI implements
final PendingIntent intent = sbn.getNotification().contentIntent;
final String notificationKey = sbn.getKey();
+ // Mark notification for one frame.
+ row.setJustClicked(true);
+ DejankUtils.postAfterTraversal(new Runnable() {
+ @Override
+ public void run() {
+ row.setJustClicked(false);
+ }
+ });
+
if (NOTIFICATION_CLICK_DEBUG) {
Log.d(TAG, "Clicked on content of " + notificationKey);
}
@@ -1639,7 +1643,7 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void updateVisibleToUser() {
boolean oldVisibleToUser = mVisibleToUser;
- mVisibleToUser = mVisible && mScreenOnFromKeyguard;
+ mVisibleToUser = mVisible && mDeviceInteractive;
if (oldVisibleToUser != mVisibleToUser) {
handleVisibleToUserChanged(mVisibleToUser);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 454b9a9..83b2fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -64,6 +64,7 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
private static final int MSG_ASSIST_DISCLOSURE = 22 << MSG_SHIFT;
private static final int MSG_START_ASSIST = 23 << MSG_SHIFT;
+ private static final int MSG_CAMERA_LAUNCH_GESTURE = 24 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -110,6 +111,7 @@ public class CommandQueue extends IStatusBar.Stub {
public void appTransitionStarting(long startTime, long duration);
public void showAssistDisclosure();
public void startAssist(Bundle args);
+ public void onCameraLaunchGestureDetected(int source);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -302,6 +304,14 @@ public class CommandQueue extends IStatusBar.Stub {
mPaused = false;
}
+ @Override
+ public void onCameraLaunchGestureDetected(int source) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
+ mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
if (mPaused) {
@@ -404,6 +414,9 @@ public class CommandQueue extends IStatusBar.Stub {
case MSG_START_ASSIST:
mCallbacks.startAssist((Bundle) msg.obj);
break;
+ case MSG_CAMERA_LAUNCH_GESTURE:
+ mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 36296b4..b7fe261 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -24,6 +24,7 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -110,6 +111,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
};
+ private boolean mJustClicked;
+
public NotificationContentView getPrivateLayout() {
return mPrivateLayout;
}
@@ -301,6 +304,21 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
return mHeadsUpHeight;
}
+ /**
+ * Mark whether this notification was just clicked, i.e. the user has just clicked this
+ * notification in this frame.
+ */
+ public void setJustClicked(boolean justClicked) {
+ mJustClicked = justClicked;
+ }
+
+ /**
+ * @return true if this notification has been clicked in this frame, false otherwise
+ */
+ public boolean wasJustClicked() {
+ return mJustClicked;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index 87a85ae..cc50e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -35,6 +35,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
protected final int mRoundedRectCornerRadius;
private boolean mCustomOutline;
private float mRoundCornerRadius = 0;
+ private float mOutlineAlpha = 1f;
public ExpandableOutlineView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -51,6 +52,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
} else {
outline.setRoundRect(mOutlineRect, mRoundCornerRadius);
}
+ outline.setAlpha(mOutlineAlpha);
}
});
}
@@ -67,6 +69,11 @@ public abstract class ExpandableOutlineView extends ExpandableView {
invalidateOutline();
}
+ protected void setOutlineAlpha(float alpha) {
+ mOutlineAlpha = alpha;
+ invalidateOutline();
+ }
+
protected void setOutlineRect(RectF rect) {
if (rect != null) {
setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 164c496..8058933 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -36,6 +36,7 @@ import android.view.ViewAnimationUtils;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ImageView;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -79,6 +80,7 @@ public class KeyguardAffordanceView extends ImageView {
private float mRestingAlpha = KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT;
private boolean mSupportHardware;
private boolean mFinishing;
+ private boolean mLaunchingAffordance;
private CanvasProperty<Float> mHwCircleRadius;
private CanvasProperty<Float> mHwCenterX;
@@ -152,7 +154,7 @@ public class KeyguardAffordanceView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
- mSupportHardware = canvas.isHardwareAccelerated();
+ mSupportHardware = false;//canvas.isHardwareAccelerated();
drawBackgroundCircle(canvas);
canvas.save();
canvas.scale(mImageScale, mImageScale, getWidth() / 2, getHeight() / 2);
@@ -161,9 +163,11 @@ public class KeyguardAffordanceView extends ImageView {
}
public void setPreviewView(View v) {
+ View oldPreviewView = mPreviewView;
mPreviewView = v;
if (mPreviewView != null) {
- mPreviewView.setVisibility(INVISIBLE);
+ mPreviewView.setVisibility(mLaunchingAffordance
+ ? oldPreviewView.getVisibility() : INVISIBLE);
}
}
@@ -176,7 +180,7 @@ public class KeyguardAffordanceView extends ImageView {
}
private void drawBackgroundCircle(Canvas canvas) {
- if (mCircleRadius > 0) {
+ if (mCircleRadius > 0 || mFinishing) {
if (mFinishing && mSupportHardware) {
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
@@ -207,11 +211,12 @@ public class KeyguardAffordanceView extends ImageView {
cancelAnimator(mPreviewClipper);
mFinishing = true;
mCircleStartRadius = mCircleRadius;
- float maxCircleSize = getMaxCircleSize();
+ final float maxCircleSize = getMaxCircleSize();
Animator animatorToRadius;
if (mSupportHardware) {
initHwProperties();
animatorToRadius = getRtAnimatorToRadius(maxCircleSize);
+ startRtAlphaFadeIn();
} else {
animatorToRadius = getAnimatorToRadius(maxCircleSize);
}
@@ -222,6 +227,8 @@ public class KeyguardAffordanceView extends ImageView {
public void onAnimationEnd(Animator animation) {
mAnimationEndRunnable.run();
mFinishing = false;
+ mCircleRadius = maxCircleSize;
+ invalidate();
}
});
animatorToRadius.start();
@@ -241,6 +248,36 @@ public class KeyguardAffordanceView extends ImageView {
}
}
+ /**
+ * Fades in the Circle on the RenderThread. It's used when finishing the circle when it had
+ * alpha 0 in the beginning.
+ */
+ private void startRtAlphaFadeIn() {
+ if (mCircleRadius == 0 && mPreviewView == null) {
+ Paint modifiedPaint = new Paint(mCirclePaint);
+ modifiedPaint.setColor(mCircleColor);
+ modifiedPaint.setAlpha(0);
+ mHwCirclePaint = CanvasProperty.createPaint(modifiedPaint);
+ RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
+ RenderNodeAnimator.PAINT_ALPHA, 255);
+ animator.setTarget(this);
+ animator.setInterpolator(PhoneStatusBar.ALPHA_IN);
+ animator.setDuration(250);
+ animator.start();
+ }
+ }
+
+ public void instantFinishAnimation() {
+ cancelAnimator(mPreviewClipper);
+ if (mPreviewView != null) {
+ mPreviewView.setClipBounds(null);
+ mPreviewView.setVisibility(View.VISIBLE);
+ }
+ mCircleRadius = getMaxCircleSize();
+ setImageAlpha(0, false);
+ invalidate();
+ }
+
private void startRtCircleFadeOut(long duration) {
RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
RenderNodeAnimator.PAINT_ALPHA, 0);
@@ -443,6 +480,7 @@ public class KeyguardAffordanceView extends ImageView {
public void setImageAlpha(float alpha, boolean animate, long duration,
Interpolator interpolator, Runnable runnable) {
cancelAnimator(mAlphaAnimator);
+ alpha = mLaunchingAffordance ? 0 : alpha;
int endAlpha = (int) (alpha * 255);
final Drawable background = getBackground();
if (!animate) {
@@ -509,4 +547,8 @@ public class KeyguardAffordanceView extends ImageView {
return false;
}
}
+
+ public void setLaunchingAffordance(boolean launchingAffordance) {
+ mLaunchingAffordance = launchingAffordance;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 07a055c..50d274d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -16,17 +16,13 @@
package com.android.systemui.statusbar;
-import com.android.internal.app.IBatteryStats;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.graphics.Color;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Handler;
@@ -39,19 +35,35 @@ import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
+import com.android.internal.app.IBatteryStats;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
+import com.android.systemui.statusbar.phone.LockIcon;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+
/**
- * Controls the little text indicator on the keyguard.
+ * Controls the indications and error messages shown on the Keyguard
*/
public class KeyguardIndicationController {
private static final String TAG = "KeyguardIndicationController";
+ private static final boolean DEBUG_CHARGING_CURRENT = false;
private static final int MSG_HIDE_TRANSIENT = 1;
+ private static final int MSG_CLEAR_FP_MSG = 2;
+ private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private final Context mContext;
private final KeyguardIndicationTextView mTextView;
private final IBatteryStats mBatteryInfo;
+ private final int mSlowThreshold;
+ private final int mFastThreshold;
+ private final LockIcon mLockIcon;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
private String mRestingIndication;
private String mTransientIndication;
private int mTransientTextColor;
@@ -59,10 +71,20 @@ public class KeyguardIndicationController {
private boolean mPowerPluggedIn;
private boolean mPowerCharged;
+ private int mChargingSpeed;
+ private int mChargingCurrent;
+ private String mMessageToShowOnScreenOn;
- public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView) {
+ public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView,
+ LockIcon lockIcon) {
mContext = context;
mTextView = textView;
+ mLockIcon = lockIcon;
+
+ Resources res = context.getResources();
+ mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
+ mFastThreshold = res.getInteger(R.integer.config_chargingFastThreshold);
+
mBatteryInfo = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
@@ -150,7 +172,11 @@ public class KeyguardIndicationController {
return mTransientIndication;
}
if (mPowerPluggedIn) {
- return computePowerIndication();
+ String indication = computePowerIndication();
+ if (DEBUG_CHARGING_CURRENT) {
+ indication += ", " + (mChargingCurrent / 1000) + " mA";
+ }
+ return indication;
}
return mRestingIndication;
}
@@ -161,20 +187,41 @@ public class KeyguardIndicationController {
}
// Try fetching charging time from battery stats.
+ long chargingTimeRemaining = 0;
try {
- long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
- if (chargingTimeRemaining > 0) {
- String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
- mContext, chargingTimeRemaining);
- return mContext.getResources().getString(
- R.string.keyguard_indication_charging_time, chargingTimeFormatted);
- }
+ chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
+
} catch (RemoteException e) {
Log.e(TAG, "Error calling IBatteryStats: ", e);
}
+ final boolean hasChargingTime = chargingTimeRemaining > 0;
- // Fall back to simple charging label.
- return mContext.getResources().getString(R.string.keyguard_plugged_in);
+ int chargingId;
+ switch (mChargingSpeed) {
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_fast_if_translated
+ : R.string.keyguard_plugged_in_charging_fast;
+ break;
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_slowly_if_translated
+ : R.string.keyguard_plugged_in_charging_slowly;
+ break;
+ default:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time
+ : R.string.keyguard_plugged_in;
+ break;
+ }
+
+ if (hasChargingTime) {
+ String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ mContext, chargingTimeRemaining);
+ return mContext.getResources().getString(chargingId, chargingTimeFormatted);
+ } else {
+ return mContext.getResources().getString(chargingId);
+ }
}
KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() {
@@ -184,8 +231,68 @@ public class KeyguardIndicationController {
|| status.status == BatteryManager.BATTERY_STATUS_FULL;
mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
mPowerCharged = status.isCharged();
+ mChargingCurrent = status.maxChargingCurrent;
+ mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
updateIndication();
}
+
+ @Override
+ public void onFingerprintHelp(int msgId, String helpString) {
+ KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
+ return;
+ }
+ int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
+ } else if (updateMonitor.isDeviceInteractive()) {
+ mLockIcon.setTransientFpError(true);
+ showTransientIndication(helpString, errorColor);
+ mHandler.removeMessages(MSG_CLEAR_FP_MSG);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG),
+ TRANSIENT_FP_ERROR_TIMEOUT);
+ }
+ }
+
+ @Override
+ public void onFingerprintError(int msgId, String errString) {
+ KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ if (!updateMonitor.isUnlockingWithFingerprintAllowed()
+ || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ return;
+ }
+ int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor);
+ } else if (updateMonitor.isDeviceInteractive()) {
+ showTransientIndication(errString, errorColor);
+ // We want to keep this message around in case the screen was off
+ mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+ hideTransientIndicationDelayed(5000);
+ } else {
+ mMessageToShowOnScreenOn = errString;
+ }
+ }
+
+ @Override
+ public void onScreenTurnedOn() {
+ if (mMessageToShowOnScreenOn != null) {
+ int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
+ null);
+ showTransientIndication(mMessageToShowOnScreenOn, errorColor);
+ // We want to keep this message around in case the screen was off
+ mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+ hideTransientIndicationDelayed(5000);
+ mMessageToShowOnScreenOn = null;
+ }
+ }
+
+ @Override
+ public void onFingerprintRunningStateChanged(boolean running) {
+ if (running) {
+ mMessageToShowOnScreenOn = null;
+ }
+ }
};
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -203,7 +310,15 @@ public class KeyguardIndicationController {
if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
mTransientIndication = null;
updateIndication();
+ } else if (msg.what == MSG_CLEAR_FP_MSG) {
+ mLockIcon.setTransientFpError(false);
+ hideTransientIndication();
}
}
};
+
+ public void setStatusBarKeyguardViewManager(
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 01aa8d1..8688c28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -86,6 +86,9 @@ public class NotificationBackgroundView extends View {
if (mBackground != null) {
mBackground.setCallback(this);
}
+ if (mBackground instanceof RippleDrawable) {
+ ((RippleDrawable) mBackground).setForceSoftware(true);
+ }
invalidate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index ef3ad10..9897098 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -34,7 +34,7 @@ public class DozeParameters {
private static final String TAG = "DozeParameters";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final int MAX_DURATION = 10 * 1000;
+ private static final int MAX_DURATION = 60 * 1000;
private final Context mContext;
@@ -53,9 +53,6 @@ public class DozeParameters {
pw.print(" getPulseInDuration(notification): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_NOTIFICATION));
pw.print(" getPulseInDuration(pickup): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_SENSOR_PICKUP));
pw.print(" getPulseInDuration(intent): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_INTENT));
- pw.print(" getPulseInDelay(notification): "); pw.println(getPulseInDelay(DozeLog.PULSE_REASON_NOTIFICATION));
- pw.print(" getPulseInDelay(pickup): "); pw.println(getPulseInDelay(DozeLog.PULSE_REASON_SENSOR_PICKUP));
- pw.print(" getPulseInDelay(intent): "); pw.println(getPulseInDelay(DozeLog.PULSE_REASON_INTENT));
pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
@@ -90,17 +87,6 @@ public class DozeParameters {
}
}
- public int getPulseInDelay(int reason) {
- switch(reason) {
- case DozeLog.PULSE_REASON_SENSOR_PICKUP:
- return getInt("doze.pulse.delay.in.pickup", R.integer.doze_pulse_delay_in_pickup);
- case DozeLog.PULSE_REASON_INTENT:
- return getInt("doze.pulse.delay.in.intent", R.integer.doze_pulse_delay_in_intent);
- default:
- return getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in);
- }
- }
-
public int getPulseVisibleDuration() {
return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 1ac57a6..b3e0104 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -100,10 +100,35 @@ public class DozeScrimController {
mHandler.post(mPulseIn);
}
+ /**
+ * Aborts pulsing immediately.
+ */
+ public void abortPulsing() {
+ cancelPulsing();
+ if (mDozing) {
+ mScrimController.setDozeBehindAlpha(1f);
+ mScrimController.setDozeInFrontAlpha(1f);
+ }
+ }
+
+ public void onScreenTurnedOn() {
+ if (isPulsing()) {
+ final boolean pickup = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
+ startScrimAnimation(true /* inFront */, 0f,
+ mDozeParameters.getPulseInDuration(mPulseReason),
+ pickup ? mPulseInInterpolatorPickup : mPulseInInterpolator,
+ mPulseInFinished);
+ }
+ }
+
public boolean isPulsing() {
return mPulseCallback != null;
}
+ public boolean isDozing() {
+ return mDozing;
+ }
+
private void cancelPulsing() {
if (DEBUG) Log.d(TAG, "Cancel pulsing");
@@ -138,12 +163,11 @@ public class DozeScrimController {
private void startScrimAnimation(final boolean inFront, float target, long duration,
Interpolator interpolator) {
- startScrimAnimation(inFront, target, duration, interpolator, 0 /* delay */,
- null /* endRunnable */);
+ startScrimAnimation(inFront, target, duration, interpolator, null /* endRunnable */);
}
private void startScrimAnimation(final boolean inFront, float target, long duration,
- Interpolator interpolator, long delay, final Runnable endRunnable) {
+ Interpolator interpolator, final Runnable endRunnable) {
Animator current = getCurrentAnimator(inFront);
if (current != null) {
float currentTarget = getCurrentTarget(inFront);
@@ -162,7 +186,6 @@ public class DozeScrimController {
});
anim.setInterpolator(interpolator);
anim.setDuration(duration);
- anim.setStartDelay(delay);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -222,12 +245,6 @@ public class DozeScrimController {
+ DozeLog.pulseReasonToString(mPulseReason));
if (!mDozing) return;
DozeLog.tracePulseStart(mPulseReason);
- final boolean pickup = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
- startScrimAnimation(true /* inFront */, 0f,
- mDozeParameters.getPulseInDuration(mPulseReason),
- pickup ? mPulseInInterpolatorPickup : mPulseInInterpolator,
- mDozeParameters.getPulseInDelay(mPulseReason),
- mPulseInFinished);
// Signal that the pulse is ready to turn the screen on and draw.
pulseStarted();
@@ -249,7 +266,7 @@ public class DozeScrimController {
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
startScrimAnimation(true /* inFront */, 1f, mDozeParameters.getPulseOutDuration(),
- mPulseOutInterpolator, 0 /* delay */, mPulseOutFinished);
+ mPulseOutInterpolator, mPulseOutFinished);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
new file mode 100644
index 0000000..2912963
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.keyguard.KeyguardConstants;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * Controller which coordinates all the fingerprint unlocking actions with the UI.
+ */
+public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
+
+ private static final String TAG = "FingerprintController";
+ private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
+ private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
+ private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
+
+ /**
+ * Mode in which we don't need to wake up the device when we get a fingerprint.
+ */
+ public static final int MODE_NONE = 0;
+
+ /**
+ * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
+ * a fingerprint while the screen is off and the device was sleeping.
+ */
+ public static final int MODE_WAKE_AND_UNLOCK = 1;
+
+ /**
+ * Mode in which we wake the device up, and fade out the Keyguard contents because they were
+ * already visible while pulsing in doze mode.
+ */
+ public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
+
+ /**
+ * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
+ * acquire a fingerprint pulsing in doze mode.
+ */
+ public static final int MODE_SHOW_BOUNCER = 3;
+
+ /**
+ * Mode in which we only wake up the device, and keyguard was not showing when we acquired a
+ * fingerprint.
+ * */
+ public static final int MODE_ONLY_WAKE = 4;
+
+ /**
+ * Mode in which fingerprint unlocks the device.
+ */
+ public static final int MODE_UNLOCK = 5;
+
+ /**
+ * Mode in which fingerprint brings up the bouncer because fingerprint unlocking is currently
+ * not allowed.
+ */
+ public static final int MODE_DISMISS_BOUNCER = 6;
+
+ /**
+ * How much faster we collapse the lockscreen when authenticating with fingerprint.
+ */
+ private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.3f;
+
+ private PowerManager mPowerManager;
+ private Handler mHandler = new Handler();
+ private PowerManager.WakeLock mWakeLock;
+ private KeyguardUpdateMonitor mUpdateMonitor;
+ private int mMode;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private StatusBarWindowManager mStatusBarWindowManager;
+ private DozeScrimController mDozeScrimController;
+ private KeyguardViewMediator mKeyguardViewMediator;
+ private ScrimController mScrimController;
+ private PhoneStatusBar mPhoneStatusBar;
+ private boolean mGoingToSleep;
+ private int mPendingAuthenticatedUserId = -1;
+
+ public FingerprintUnlockController(Context context,
+ StatusBarWindowManager statusBarWindowManager,
+ DozeScrimController dozeScrimController,
+ KeyguardViewMediator keyguardViewMediator,
+ ScrimController scrimController,
+ PhoneStatusBar phoneStatusBar) {
+ mPowerManager = context.getSystemService(PowerManager.class);
+ mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+ mUpdateMonitor.registerCallback(this);
+ mStatusBarWindowManager = statusBarWindowManager;
+ mDozeScrimController = dozeScrimController;
+ mKeyguardViewMediator = keyguardViewMediator;
+ mScrimController = scrimController;
+ mPhoneStatusBar = phoneStatusBar;
+ }
+
+ public void setStatusBarKeyguardViewManager(
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ }
+
+ private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG_FP_WAKELOCK) {
+ Log.i(TAG, "fp wakelock: TIMEOUT!!");
+ }
+ releaseFingerprintWakeLock();
+ }
+ };
+
+ private void releaseFingerprintWakeLock() {
+ if (mWakeLock != null) {
+ mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable);
+ if (DEBUG_FP_WAKELOCK) {
+ Log.i(TAG, "releasing fp wakelock");
+ }
+ mWakeLock.release();
+ mWakeLock = null;
+ }
+ }
+
+ @Override
+ public void onFingerprintAcquired() {
+ releaseFingerprintWakeLock();
+ if (!mUpdateMonitor.isDeviceInteractive()) {
+ mWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
+ mWakeLock.acquire();
+ if (DEBUG_FP_WAKELOCK) {
+ Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
+ }
+ mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
+ FINGERPRINT_WAKELOCK_TIMEOUT_MS);
+ if (mDozeScrimController.isPulsing()) {
+
+ // If we are waking the device up while we are pulsing the clock and the
+ // notifications would light up first, creating an unpleasant animation.
+ // Defer changing the screen brightness by forcing doze brightness on our window
+ // until the clock and the notifications are faded out.
+ mStatusBarWindowManager.setForceDozeBrightness(true);
+ }
+ }
+ }
+
+ @Override
+ public void onFingerprintAuthenticated(int userId) {
+ if (mUpdateMonitor.isGoingToSleep()) {
+ mPendingAuthenticatedUserId = userId;
+ return;
+ }
+ boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
+ mMode = calculateMode();
+ if (!wasDeviceInteractive) {
+ if (DEBUG_FP_WAKELOCK) {
+ Log.i(TAG, "fp wakelock: Authenticated, waking up...");
+ }
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ }
+ releaseFingerprintWakeLock();
+ switch (mMode) {
+ case MODE_DISMISS_BOUNCER:
+ mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
+ false /* strongAuth */);
+ break;
+ case MODE_UNLOCK:
+ case MODE_SHOW_BOUNCER:
+ if (!wasDeviceInteractive) {
+ mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+ }
+ mStatusBarKeyguardViewManager.animateCollapsePanels(
+ FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
+ break;
+ case MODE_WAKE_AND_UNLOCK_PULSING:
+ mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */);
+ // Fall through.
+ case MODE_WAKE_AND_UNLOCK:
+ mStatusBarWindowManager.setStatusBarFocusable(false);
+ mDozeScrimController.abortPulsing();
+ mKeyguardViewMediator.onWakeAndUnlocking();
+ mScrimController.setWakeAndUnlocking();
+ if (mPhoneStatusBar.getNavigationBarView() != null) {
+ mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
+ }
+ break;
+ case MODE_ONLY_WAKE:
+ case MODE_NONE:
+ break;
+ }
+ if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
+ mStatusBarWindowManager.setForceDozeBrightness(false);
+ }
+ mPhoneStatusBar.notifyFpAuthModeChanged();
+ }
+
+ @Override
+ public void onStartedGoingToSleep(int why) {
+ mPendingAuthenticatedUserId = -1;
+ }
+
+ @Override
+ public void onFinishedGoingToSleep(int why) {
+ if (mPendingAuthenticatedUserId != -1) {
+
+ // Post this to make sure it's executed after the device is fully locked.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onFingerprintAuthenticated(mPendingAuthenticatedUserId);
+ }
+ });
+ }
+ mPendingAuthenticatedUserId = -1;
+ }
+
+ public int getMode() {
+ return mMode;
+ }
+
+ private int calculateMode() {
+ boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
+ if (!mUpdateMonitor.isDeviceInteractive()) {
+ if (!mStatusBarKeyguardViewManager.isShowing()) {
+ return MODE_ONLY_WAKE;
+ } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
+ return MODE_WAKE_AND_UNLOCK_PULSING;
+ } else if (unlockingAllowed) {
+ return MODE_WAKE_AND_UNLOCK;
+ } else {
+ return MODE_SHOW_BOUNCER;
+ }
+ }
+ if (mStatusBarKeyguardViewManager.isShowing()) {
+ if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
+ return MODE_DISMISS_BOUNCER;
+ } else if (unlockingAllowed) {
+ return MODE_UNLOCK;
+ } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ return MODE_SHOW_BOUNCER;
+ }
+ }
+ return MODE_NONE;
+ }
+
+ @Override
+ public void onFingerprintAuthFailed() {
+ cleanup();
+ }
+
+ @Override
+ public void onFingerprintError(int msgId, String errString) {
+ cleanup();
+ }
+
+ private void cleanup() {
+ mMode = MODE_NONE;
+ releaseFingerprintWakeLock();
+ mStatusBarWindowManager.setForceDozeBrightness(false);
+ mPhoneStatusBar.notifyFpAuthModeChanged();
+ }
+
+ public void startKeyguardFadingAway() {
+
+ // Disable brightness override when the ambient contents are fully invisible.
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mStatusBarWindowManager.setForceDozeBrightness(false);
+ }
+ }, PhoneStatusBar.FADE_KEYGUARD_DURATION_PULSING);
+ }
+
+ public void finishKeyguardFadingAway() {
+ mMode = MODE_NONE;
+ if (mPhoneStatusBar.getNavigationBarView() != null) {
+ mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
+ }
+ mPhoneStatusBar.notifyFpAuthModeChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 10019f9..60ebfdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -86,9 +86,9 @@ public class KeyguardAffordanceHelper {
mContext = context;
mCallback = callback;
initIcons();
- updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true);
- updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true);
- updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true);
+ updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
+ updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true, false);
+ updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
initDimens();
}
@@ -144,9 +144,7 @@ public class KeyguardAffordanceHelper {
} else {
mTouchSlopExeeded = false;
}
- mCallback.onSwipingStarted(targetView == mRightIcon);
- mSwipingInProgress = true;
- mTargetedView = targetView;
+ startSwiping(targetView);
mInitialTouchX = x;
mInitialTouchY = y;
mTranslationOnDown = mTranslation;
@@ -192,6 +190,12 @@ public class KeyguardAffordanceHelper {
return true;
}
+ private void startSwiping(View targetView) {
+ mCallback.onSwipingStarted(targetView == mRightIcon);
+ mSwipingInProgress = true;
+ mTargetedView = targetView;
+ }
+
private View getIconAtPosition(float x, float y) {
if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) {
return mLeftIcon;
@@ -324,7 +328,7 @@ public class KeyguardAffordanceHelper {
boolean velIsInWrongDirection = vel * mTranslation < 0;
snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection;
vel = snapBack ^ velIsInWrongDirection ? 0 : vel;
- fling(vel, snapBack || forceSnapBack);
+ fling(vel, snapBack || forceSnapBack, mTranslation < 0);
}
private boolean isBelowFalsingThreshold() {
@@ -336,9 +340,8 @@ public class KeyguardAffordanceHelper {
return (int) (mMinTranslationAmount * factor);
}
- private void fling(float vel, final boolean snapBack) {
- float target = mTranslation < 0
- ? -mCallback.getMaxTranslationDistance()
+ private void fling(float vel, final boolean snapBack, boolean right) {
+ float target = right ? -mCallback.getMaxTranslationDistance()
: mCallback.getMaxTranslationDistance();
target = snapBack ? 0 : target;
@@ -352,8 +355,8 @@ public class KeyguardAffordanceHelper {
});
animator.addListener(mFlingEndListener);
if (!snapBack) {
- startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable);
- mCallback.onAnimationToSideStarted(mTranslation < 0, mTranslation, vel);
+ startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right);
+ mCallback.onAnimationToSideStarted(right, mTranslation, vel);
} else {
reset(true);
}
@@ -364,8 +367,9 @@ public class KeyguardAffordanceHelper {
}
}
- private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable) {
- KeyguardAffordanceView targetView = mTranslation > 0 ? mLeftIcon : mRightIcon;
+ private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable,
+ boolean right) {
+ KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
targetView.finishAnimation(velocity, mAnimationEndRunnable);
}
@@ -383,19 +387,20 @@ public class KeyguardAffordanceHelper {
fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f);
boolean animateIcons = isReset && animateReset;
+ boolean forceNoCircleAnimation = isReset && !animateReset;
float radius = getRadiusFromTranslation(absTranslation);
boolean slowAnimation = isReset && isBelowFalsingThreshold();
if (!isReset) {
updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
- false, false, false);
+ false, false, false, false);
} else {
updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
}
updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
mTranslation = translation;
}
@@ -431,16 +436,21 @@ public class KeyguardAffordanceHelper {
public void animateHideLeftRightIcon() {
cancelAnimation();
- updateIcon(mRightIcon, 0f, 0f, true, false, false);
- updateIcon(mLeftIcon, 0f, 0f, true, false, false);
+ updateIcon(mRightIcon, 0f, 0f, true, false, false, false);
+ updateIcon(mLeftIcon, 0f, 0f, true, false, false, false);
}
private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
- boolean animate, boolean slowRadiusAnimation, boolean force) {
+ boolean animate, boolean slowRadiusAnimation, boolean force,
+ boolean forceNoCircleAnimation) {
if (view.getVisibility() != View.VISIBLE && !force) {
return;
}
- view.setCircleRadius(circleRadius, slowRadiusAnimation);
+ if (forceNoCircleAnimation) {
+ view.setCircleRadiusWithoutAnimation(circleRadius);
+ } else {
+ view.setCircleRadius(circleRadius, slowRadiusAnimation);
+ }
updateIconAlpha(view, alpha, animate);
}
@@ -503,8 +513,36 @@ public class KeyguardAffordanceHelper {
mMotionCancelled = true;
if (mSwipingInProgress) {
mCallback.onSwipingAborted();
+ mSwipingInProgress = false;
+ }
+ }
+
+ public boolean isSwipingInProgress() {
+ return mSwipingInProgress;
+ }
+
+ public void launchAffordance(boolean animate, boolean left) {
+ if (mSwipingInProgress) {
+ // We don't want to mess with the state if the user is actually swiping already.
+ return;
+ }
+ KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
+ KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
+ startSwiping(targetView);
+ if (animate) {
+ fling(0, false, !left);
+ updateIcon(otherView, 0.0f, 0, true, false, true, false);
+ updateIcon(mCenterIcon, 0.0f, 0, true, false, true, false);
+ } else {
+ mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
+ mTranslation = left ? mCallback.getMaxTranslationDistance()
+ : mCallback.getMaxTranslationDistance();
+ updateIcon(mCenterIcon, 0.0f, 0.0f, false, false, true, false);
+ updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
+ targetView.instantFinishAnimation();
+ mFlingEndListener.onAnimationEnd(null);
+ mAnimationEndRunnable.run();
}
- mSwipingInProgress = false;
}
public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index a7648bf..63660a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,7 +29,6 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
-import android.hardware.fingerprint.FingerprintManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
@@ -80,15 +79,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
+ public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
+ public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
+ public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
+
+ public static final String EXTRA_CAMERA_LAUNCH_SOURCE
+ = "com.android.systemui.camera_launch_source";
+
private static final Intent SECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- private static final Intent INSECURE_CAMERA_INTENT =
+ public static final Intent INSECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
- private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private EmergencyButton mEmergencyButton;
private KeyguardAffordanceView mCameraImageView;
@@ -175,7 +180,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
return true;
} else if (host == mCameraImageView) {
- launchCamera();
+ launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
return true;
} else if (host == mLeftAffordanceView) {
launchLeftAffordance();
@@ -270,14 +275,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
+ /**
+ * Resolves the intent to launch the camera application.
+ */
+ public ResolveInfo resolveCameraIntent() {
+ return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
+ PackageManager.MATCH_DEFAULT_ONLY,
+ KeyguardUpdateMonitor.getCurrentUser());
+ }
+
private void updateCameraVisibility() {
if (mCameraImageView == null) {
// Things are not set up yet; reply hazy, ask again later
return;
}
- ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
- PackageManager.MATCH_DEFAULT_ONLY,
- KeyguardUpdateMonitor.getCurrentUser());
+ ResolveInfo resolved = resolveCameraIntent();
boolean visible = !isCameraDisabledByDpm() && resolved != null
&& getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
&& mUserSetupComplete;
@@ -350,7 +362,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public void onClick(View v) {
if (v == mCameraImageView) {
- launchCamera();
+ launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
} else if (v == mLeftAffordanceView) {
launchLeftAffordance();
} if (v == mLockIcon) {
@@ -391,7 +403,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
try {
if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
- Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT))) {
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ new UserHandle(UserHandle.USER_CURRENT))) {
mPrewarmBound = true;
}
} catch (SecurityException e) {
@@ -417,8 +430,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
- public void launchCamera() {
+ public void launchCamera(String source) {
final Intent intent = getCameraIntent();
+ intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
@@ -534,7 +548,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return mCameraPreview;
}
- public KeyguardAffordanceView getLockIcon() {
+ public LockIcon getLockIcon() {
return mLockIcon;
}
@@ -619,21 +633,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
};
- private final Runnable mTransientFpErrorClearRunnable = new Runnable() {
- @Override
- public void run() {
- mLockIcon.setTransientFpError(false);
- mIndicationController.hideTransientIndication();
- }
- };
-
- private final Runnable mHideTransientIndicationRunnable = new Runnable() {
- @Override
- public void run() {
- mIndicationController.hideTransientIndication();
- }
- };
-
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -652,42 +651,28 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
@Override
- public void onKeyguardVisibilityChanged(boolean showing) {
- mLockIcon.update();
+ public void onScreenTurnedOn() {
+ mLockIcon.setScreenOn(true);
}
@Override
- public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
+ public void onScreenTurnedOff() {
+ mLockIcon.setScreenOn(false);
}
@Override
- public void onFingerprintRunningStateChanged(boolean running) {
+ public void onKeyguardVisibilityChanged(boolean showing) {
mLockIcon.update();
}
@Override
- public void onFingerprintHelp(int msgId, String helpString) {
- if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()) {
- return;
- }
- mLockIcon.setTransientFpError(true);
- mIndicationController.showTransientIndication(helpString,
- getResources().getColor(R.color.system_warning_color, null));
- removeCallbacks(mTransientFpErrorClearRunnable);
- postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT);
+ public void onFingerprintRunningStateChanged(boolean running) {
+ mLockIcon.update();
}
@Override
- public void onFingerprintError(int msgId, String errString) {
- if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()
- || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
- return;
- }
- // TODO: Go to bouncer if this is "too many attempts" (lockout) error.
- mIndicationController.showTransientIndication(errString,
- getResources().getColor(R.color.system_warning_color, null));
- removeCallbacks(mHideTransientIndicationRunnable);
- postDelayed(mHideTransientIndicationRunnable, 5000);
+ public void onStrongAuthStateChanged(int userId) {
+ mLockIcon.update();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index d6be80e..395f350 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.view.Choreographer;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,6 +26,8 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView;
import com.android.keyguard.KeyguardSecurityView;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
@@ -48,6 +49,13 @@ public class KeyguardBouncer {
private ViewGroup mRoot;
private boolean mShowingSoon;
private int mBouncerPromptReason;
+ private KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ mBouncerPromptReason = mCallback.getBouncerPromptReason();
+ }
+ };
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
@@ -57,6 +65,7 @@ public class KeyguardBouncer {
mLockPatternUtils = lockPatternUtils;
mContainer = container;
mWindowManager = windowManager;
+ KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
}
public void show(boolean resetSecuritySelection) {
@@ -103,6 +112,10 @@ public class KeyguardBouncer {
mKeyguardView.showPromptReason(reason);
}
+ public void showMessage(String message, int color) {
+ mKeyguardView.showMessage(message, color);
+ }
+
private void cancelShowRunnable() {
DejankUtils.removeCallbacks(mShowRunnable);
mShowingSoon = false;
@@ -244,8 +257,8 @@ public class KeyguardBouncer {
return mKeyguardView.interceptMediaKey(event);
}
- public void notifyKeyguardAuthenticated() {
+ public void notifyKeyguardAuthenticated(boolean strongAuth) {
ensureView();
- mKeyguardView.finish();
+ mKeyguardView.finish(strongAuth);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 06d2fca..8e58d14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -34,12 +34,6 @@ import com.android.systemui.statusbar.policy.AccessibilityController;
*/
public class LockIcon extends KeyguardAffordanceView {
- /**
- * Delay animations a bit when the screen just turned on as a heuristic to start them after
- * the screen has actually turned on.
- */
- private static final long ANIM_DELAY_AFTER_SCREEN_ON = 250;
-
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
private static final int STATE_FACE_UNLOCK = 2;
@@ -50,6 +44,8 @@ public class LockIcon extends KeyguardAffordanceView {
private boolean mLastDeviceInteractive;
private boolean mTransientFpError;
private boolean mDeviceInteractive;
+ private boolean mScreenOn;
+ private boolean mLastScreenOn;
private final TrustDrawable mTrustDrawable;
private final UnlockMethodCache mUnlockMethodCache;
private AccessibilityController mAccessibilityController;
@@ -88,6 +84,11 @@ public class LockIcon extends KeyguardAffordanceView {
update();
}
+ public void setScreenOn(boolean screenOn) {
+ mScreenOn = screenOn;
+ update();
+ }
+
public void update() {
boolean visible = isShown()
&& KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
@@ -96,20 +97,32 @@ public class LockIcon extends KeyguardAffordanceView {
} else {
mTrustDrawable.stop();
}
- if (!visible) {
- return;
- }
// TODO: Real icon for facelock.
int state = getState();
boolean anyFingerprintIcon = state == STATE_FINGERPRINT || state == STATE_FINGERPRINT_ERROR;
- if (state != mLastState || mDeviceInteractive != mLastDeviceInteractive) {
+ boolean useAdditionalPadding = anyFingerprintIcon;
+ boolean trustHidden = anyFingerprintIcon;
+ if (state != mLastState || mDeviceInteractive != mLastDeviceInteractive
+ || mScreenOn != mLastScreenOn) {
+ boolean isAnim = true;
int iconRes = getAnimationResForTransition(mLastState, state, mLastDeviceInteractive,
- mDeviceInteractive);
+ mDeviceInteractive, mLastScreenOn, mScreenOn);
if (iconRes == R.drawable.lockscreen_fingerprint_draw_off_animation) {
anyFingerprintIcon = true;
+ useAdditionalPadding = true;
+ trustHidden = true;
+ } else if (iconRes == R.drawable.trusted_state_to_error_animation) {
+ anyFingerprintIcon = true;
+ useAdditionalPadding = false;
+ trustHidden = true;
+ } else if (iconRes == R.drawable.error_to_trustedstate_animation) {
+ anyFingerprintIcon = true;
+ useAdditionalPadding = false;
+ trustHidden = false;
}
if (iconRes == -1) {
- iconRes = getIconForState(state);
+ iconRes = getIconForState(state, mScreenOn, mDeviceInteractive);
+ isAnim = false;
}
Drawable icon = mContext.getDrawable(iconRes);
final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
@@ -123,7 +136,7 @@ public class LockIcon extends KeyguardAffordanceView {
|| icon.getIntrinsicWidth() != iconWidth)) {
icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight);
}
- setPaddingRelative(0, 0, 0, anyFingerprintIcon
+ setPaddingRelative(0, 0, 0, useAdditionalPadding
? getResources().getDimensionPixelSize(
R.dimen.fingerprint_icon_additional_padding)
: 0);
@@ -135,27 +148,16 @@ public class LockIcon extends KeyguardAffordanceView {
: R.string.accessibility_unlock_button);
setContentDescription(contentDescription);
mHasFingerPrintIcon = anyFingerprintIcon;
- if (animation != null) {
-
- // If we play the draw on animation, delay it by one frame when the screen is
- // actually turned on.
- if (iconRes == R.drawable.lockscreen_fingerprint_draw_on_animation) {
- postOnAnimationDelayed(new Runnable() {
- @Override
- public void run() {
- animation.start();
- }
- }, ANIM_DELAY_AFTER_SCREEN_ON);
- } else {
- animation.start();
- }
+ if (animation != null && isAnim) {
+ animation.start();
}
mLastState = state;
mLastDeviceInteractive = mDeviceInteractive;
+ mLastScreenOn = mScreenOn;
}
// Hide trust circle when fingerprint is running.
- boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon;
+ boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !trustHidden;
mTrustDrawable.setTrustManaged(trustManaged);
updateClickability();
}
@@ -192,7 +194,7 @@ public class LockIcon extends KeyguardAffordanceView {
mAccessibilityController = accessibilityController;
}
- private int getIconForState(int state) {
+ private int getIconForState(int state, boolean screenOn, boolean deviceInteractive) {
switch (state) {
case STATE_LOCKED:
return R.drawable.ic_lock_24dp;
@@ -201,7 +203,11 @@ public class LockIcon extends KeyguardAffordanceView {
case STATE_FACE_UNLOCK:
return com.android.internal.R.drawable.ic_account_circle;
case STATE_FINGERPRINT:
- return R.drawable.ic_fingerprint;
+ // If screen is off and device asleep, use the draw on animation so the first frame
+ // gets drawn.
+ return screenOn && deviceInteractive
+ ? R.drawable.ic_fingerprint
+ : R.drawable.lockscreen_fingerprint_draw_on_animation;
case STATE_FINGERPRINT_ERROR:
return R.drawable.ic_fingerprint_error;
default:
@@ -209,16 +215,22 @@ public class LockIcon extends KeyguardAffordanceView {
}
}
- private int getAnimationResForTransition(int oldState, int newState, boolean oldScreenOn,
- boolean screenOn) {
+ private int getAnimationResForTransition(int oldState, int newState,
+ boolean oldDeviceInteractive, boolean deviceInteractive,
+ boolean oldScreenOn, boolean screenOn) {
if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
return R.drawable.lockscreen_fingerprint_fp_to_error_state_animation;
+ } else if (oldState == STATE_LOCK_OPEN && newState == STATE_FINGERPRINT_ERROR) {
+ return R.drawable.trusted_state_to_error_animation;
+ } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_LOCK_OPEN) {
+ return R.drawable.error_to_trustedstate_animation;
} else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
return R.drawable.lockscreen_fingerprint_error_state_to_fp_animation;
} else if (oldState == STATE_FINGERPRINT && newState == STATE_LOCK_OPEN
&& !mUnlockMethodCache.isTrusted()) {
return R.drawable.lockscreen_fingerprint_draw_off_animation;
- } else if (newState == STATE_FINGERPRINT && !oldScreenOn && screenOn) {
+ } else if (newState == STATE_FINGERPRINT && (!oldScreenOn && screenOn && deviceInteractive
+ || screenOn && !oldDeviceInteractive && deviceInteractive)) {
return R.drawable.lockscreen_fingerprint_draw_on_animation;
} else {
return -1;
@@ -229,14 +241,14 @@ public class LockIcon extends KeyguardAffordanceView {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
boolean fingerprintRunning = updateMonitor.isFingerprintDetectionRunning();
boolean unlockingAllowed = updateMonitor.isUnlockingWithFingerprintAllowed();
- if (mUnlockMethodCache.canSkipBouncer()) {
- return STATE_LOCK_OPEN;
- } else if (mTransientFpError) {
+ if (mTransientFpError) {
return STATE_FINGERPRINT_ERROR;
- } else if (fingerprintRunning && unlockingAllowed) {
- return STATE_FINGERPRINT;
+ } else if (mUnlockMethodCache.canSkipBouncer()) {
+ return STATE_LOCK_OPEN;
} else if (mUnlockMethodCache.isFaceUnlockRunning()) {
return STATE_FACE_UNLOCK;
+ } else if (fingerprintRunning && unlockingAllowed) {
+ return STATE_FINGERPRINT;
} else {
return STATE_LOCKED;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c6aac02..1acfe57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -96,7 +96,8 @@ public class NavigationBarView extends LinearLayout {
private OnVerticalChangedListener mOnVerticalChangedListener;
private boolean mIsLayoutRtl;
- private boolean mLayoutTransitionsEnabled;
+ private boolean mLayoutTransitionsEnabled = true;
+ private boolean mWakeAndUnlocking;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -261,11 +262,11 @@ public class NavigationBarView extends LinearLayout {
private void getIcons(Resources res) {
mBackIcon = new BackButtonDrawable(res.getDrawable(R.drawable.ic_sysbar_back));
- mBackLandIcon = new BackButtonDrawable(res.getDrawable(R.drawable.ic_sysbar_back_land));
+ mBackLandIcon = mBackIcon;
mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent);
- mRecentLandIcon = res.getDrawable(R.drawable.ic_sysbar_recent_land);
+ mRecentLandIcon = mRecentIcon;
mHomeIcon = res.getDrawable(R.drawable.ic_sysbar_home);
- mHomeLandIcon = res.getDrawable(R.drawable.ic_sysbar_home_land);
+ mHomeLandIcon = mHomeIcon;
}
public void updateResources(Resources res) {
@@ -398,13 +399,19 @@ public class NavigationBarView extends LinearLayout {
}
}
+ public void setLayoutTransitionsEnabled(boolean enabled) {
+ mLayoutTransitionsEnabled = enabled;
+ updateLayoutTransitionsEnabled();
+ }
+
public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
setUseFadingAnimations(wakeAndUnlocking);
- setLayoutTransitionsEnabled(!wakeAndUnlocking);
+ mWakeAndUnlocking = wakeAndUnlocking;
+ updateLayoutTransitionsEnabled();
}
- private void setLayoutTransitionsEnabled(boolean enabled) {
- mLayoutTransitionsEnabled = enabled;
+ private void updateLayoutTransitionsEnabled() {
+ boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
ViewGroup navButtons = (ViewGroup) mCurrentView.findViewById(R.id.nav_buttons);
LayoutTransition lt = navButtons.getLayoutTransition();
if (lt != null) {
@@ -501,7 +508,7 @@ public class NavigationBarView extends LinearLayout {
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
- setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);
+ updateLayoutTransitionsEnabled();
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 81d9bf4..9c817fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,7 +22,10 @@ import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.ContentResolver;
+import android.app.ActivityManager;
+import android.app.StatusBarManager;
import android.content.Context;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Canvas;
@@ -68,6 +71,8 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
+import java.util.List;
+
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
@@ -113,12 +118,6 @@ public class NotificationPanelView extends PanelView implements
private boolean mQsTracking;
/**
- * Handles launching the secure camera properly even when other applications may be using the
- * camera hardware.
- */
- private SecureCameraLaunchManager mSecureCameraLaunchManager;
-
- /**
* If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
* the expansion for quick settings.
*/
@@ -210,6 +209,8 @@ public class NotificationPanelView extends PanelView implements
private int mLastOrientation = -1;
private boolean mClosingWithAlphaFadeOut;
private boolean mHeadsUpAnimatingAway;
+ private boolean mLaunchingAffordance;
+ private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@Override
@@ -282,8 +283,6 @@ public class NotificationPanelView extends PanelView implements
mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
- mSecureCameraLaunchManager =
- new SecureCameraLaunchManager(getContext(), mKeyguardBottomArea);
mLastOrientation = getResources().getConfiguration().orientation;
// recompute internal state when qspanel height changes
@@ -389,19 +388,6 @@ public class NotificationPanelView extends PanelView implements
updateMaxHeadsUpTranslation();
}
- @Override
- public void onAttachedToWindow() {
- mSecureCameraLaunchManager.create();
- mSettingsObserver.observe();
-
- }
-
- @Override
- public void onDetachedFromWindow() {
- mSecureCameraLaunchManager.destroy();
- mSettingsObserver.unobserve();
- }
-
private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
if (mQsSizeChangeAnimator != null) {
oldHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
@@ -518,7 +504,10 @@ public class NotificationPanelView extends PanelView implements
mIsLaunchTransitionFinished = false;
mBlockTouches = false;
mUnlockIconActive = false;
- mAfforanceHelper.reset(true);
+ if (!mLaunchingAffordance) {
+ mAfforanceHelper.reset(false);
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ }
closeQs();
mStatusBar.dismissPopups();
mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
@@ -959,7 +948,7 @@ public class NotificationPanelView extends PanelView implements
}
private int getFalsingThreshold() {
- float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+ float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
return (int) (mQsFalsingThreshold * factor);
}
@@ -2006,9 +1995,13 @@ public class NotificationPanelView extends PanelView implements
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
mKeyguardBottomArea.launchLeftAffordance();
} else {
- EventLogTags.writeSysuiLockscreenGesture(
- EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
- mSecureCameraLaunchManager.startSecureCameraLaunch();
+ if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals(
+ mLastCameraLaunchSource)) {
+ EventLogTags.writeSysuiLockscreenGesture(
+ EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA,
+ lengthDp, velocityDp);
+ }
+ mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
}
mStatusBar.startLaunchTransitionTimeout();
mBlockTouches = true;
@@ -2055,7 +2048,6 @@ public class NotificationPanelView extends PanelView implements
boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
: rightIcon;
if (camera) {
- mSecureCameraLaunchManager.onSwipingStarted();
mKeyguardBottomArea.bindCameraPrewarmService();
}
requestDisallowInterceptTouchEvent(true);
@@ -2128,7 +2120,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public float getAffordanceFalsingFactor() {
- return mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+ return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
}
@Override
@@ -2484,4 +2476,72 @@ public class NotificationPanelView extends PanelView implements
resolver, Settings.System.DOUBLE_TAP_SLEEP_GESTURE, 1) == 1;
}
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return !mDozing;
+ }
+
+ public void launchCamera(boolean animate, int source) {
+ if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
+ } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
+ } else {
+
+ // Default.
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ }
+
+ // If we are launching it when we are occluded already we don't want it to animate,
+ // nor setting these flags, since the occluded state doesn't change anymore, hence it's
+ // never reset.
+ if (!isFullyCollapsed()) {
+ mLaunchingAffordance = true;
+ setLaunchingAffordance(true);
+ } else {
+ animate = false;
+ }
+ mAfforanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ }
+
+ public void onAffordanceLaunchEnded() {
+ mLaunchingAffordance = false;
+ setLaunchingAffordance(false);
+ }
+
+ /**
+ * Set whether we are currently launching an affordance. This is currently only set when
+ * launched via a camera gesture.
+ */
+ private void setLaunchingAffordance(boolean launchingAffordance) {
+ getLeftIcon().setLaunchingAffordance(launchingAffordance);
+ getRightIcon().setLaunchingAffordance(launchingAffordance);
+ getCenterIcon().setLaunchingAffordance(launchingAffordance);
+ }
+
+ /**
+ * Whether the camera application can be launched for the camera launch gesture.
+ *
+ * @param keyguardIsShowing whether keyguard is being shown
+ */
+ public boolean canCameraGestureBeLaunched(boolean keyguardIsShowing) {
+ ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
+ String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
+ ? null : resolveInfo.activityInfo.packageName;
+ return packageToLaunch != null &&
+ (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
+ !mAfforanceHelper.isSwipingInProgress();
+ }
+
+ /**
+ * Return true if the applications with the package name is running in foreground.
+ *
+ * @param pkgName application package name.
+ */
+ private boolean isForegroundApp(String pkgName) {
+ ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+ return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 4a1e641..7cd23dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -400,7 +400,7 @@ public abstract class PanelView extends FrameLayout {
|| forceCancel;
DozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
mStatusBar.isFalsingThresholdNeeded(),
- mStatusBar.isScreenOnComingFromTouch());
+ mStatusBar.isWakeUpComingFromTouch());
// Log collapse gesture if on lock screen.
if (!expand && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
float displayDensity = mStatusBar.getDisplayDensity();
@@ -429,7 +429,7 @@ public abstract class PanelView extends FrameLayout {
}
private int getFalsingThreshold() {
- float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+ float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
return (int) (mUnlockFalsingThreshold * factor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 8fb63d1..5c85977 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -78,6 +78,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -119,6 +120,7 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.cm.ActionUtils;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.BatteryLevelTextView;
@@ -179,6 +181,7 @@ import com.android.systemui.statusbar.policy.WeatherControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.StackViewState;
import com.android.systemui.volume.VolumeComponent;
@@ -261,6 +264,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public static final int FADE_KEYGUARD_START_DELAY = 100;
public static final int FADE_KEYGUARD_DURATION = 300;
+ public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -303,6 +307,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
AccessibilityController mAccessibilityController;
WeatherControllerImpl mWeatherController;
SuControllerImpl mSuController;
+ FingerprintUnlockController mFingerprintUnlockController;
int mNaturalBarHeight = -1;
@@ -316,8 +321,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private StatusBarWindowManager mStatusBarWindowManager;
private UnlockMethodCache mUnlockMethodCache;
private DozeServiceHost mDozeServiceHost;
- private boolean mScreenOnComingFromTouch;
- private PointF mScreenOnTouchLocation;
+ private boolean mWakeUpComingFromTouch;
+ private PointF mWakeUpTouchLocation;
+ private boolean mScreenTurningOn;
private BatteryMeterView mBatteryView;
private BatteryLevelTextView mBatteryTextView;
@@ -343,6 +349,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
boolean mLeaveOpenOnKeyguardHide;
KeyguardIndicationController mKeyguardIndicationController;
+ // Keyguard is going away soon.
+ private boolean mKeyguardGoingAway;
+ // Keyguard is actually fading away now.
private boolean mKeyguardFadingAway;
private boolean mKeyguardShowingMedia;
private long mKeyguardFadingAwayDelay;
@@ -649,10 +658,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private Runnable mLaunchTransitionEndRunnable;
private boolean mLaunchTransitionFadingAway;
private ExpandableNotificationRow mDraggedDownRow;
+ private boolean mLaunchCameraOnScreenTurningOn;
+ private boolean mLaunchCameraOnFinishedGoingToSleep;
+ private int mLastCameraLaunchSource;
+ private PowerManager.WakeLock mGestureWakeLock;
+ private Vibrator mVibrator;
// Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
private int mLastLoggedStateFingerprint;
+ /**
+ * If set, the device has started going to sleep but isn't fully non-interactive yet.
+ */
+ protected boolean mStartedGoingToSleep;
+
private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_CARD
| StackViewState.LOCATION_MAIN_AREA;
@@ -821,6 +840,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
startKeyguard();
mDozeServiceHost = new DozeServiceHost();
+ KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
putComponent(DozeHost.class, mDozeServiceHost);
putComponent(PhoneStatusBar.class, this);
@@ -987,7 +1007,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindowContent.findViewById(
- R.id.keyguard_indication_text));
+ R.id.keyguard_indication_text),
+ mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
// set the inital view visibility
@@ -1116,7 +1137,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
-
+ mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+ "GestureWakeLock");
+ mVibrator = mContext.getSystemService(Vibrator.class);
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -1238,8 +1261,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void startKeyguard() {
KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
+ mFingerprintUnlockController = new FingerprintUnlockController(mContext,
+ mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
+ mScrimController, this);
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
- mStatusBarWindow, mStatusBarWindowManager, mScrimController);
+ mStatusBarWindow, mStatusBarWindowManager, mScrimController,
+ mFingerprintUnlockController);
+ mKeyguardIndicationController.setStatusBarKeyguardViewManager(
+ mStatusBarKeyguardViewManager);
+ mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
}
@@ -1952,7 +1982,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardShowingMedia = hasBackdrop;
if ((hasBackdrop || DEBUG_MEDIA_FAKE_ARTWORK)
- && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
+ && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+ && mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
// time to show some art!
if (mBackdrop.getVisibility() != View.VISIBLE) {
mBackdrop.setVisibility(View.VISIBLE);
@@ -2007,31 +2039,40 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
- mBackdrop.animate()
- // Never let the alpha become zero - otherwise the RenderNode
- // won't draw anything and uninitialized memory will show through
- // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in libhwui.
- .alpha(0.002f)
- .setInterpolator(mBackdropInterpolator)
- .setDuration(300)
- .setStartDelay(0)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mBackdrop.setVisibility(View.GONE);
- mBackdropFront.animate().cancel();
- mBackdropBack.animate().cancel();
- mHandler.post(mHideBackdropFront);
- }
- });
- if (mKeyguardFadingAway) {
- mBackdrop.animate()
+ if (mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
- // Make it disappear faster, as the focus should be on the activity behind.
- .setDuration(mKeyguardFadingAwayDuration / 2)
- .setStartDelay(mKeyguardFadingAwayDelay)
- .setInterpolator(mLinearInterpolator)
- .start();
+ // We are unlocking directly - no animation!
+ mBackdrop.setVisibility(View.GONE);
+ } else {
+ mBackdrop.animate()
+ // Never let the alpha become zero - otherwise the RenderNode
+ // won't draw anything and uninitialized memory will show through
+ // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
+ // libhwui.
+ .alpha(0.002f)
+ .setInterpolator(mBackdropInterpolator)
+ .setDuration(300)
+ .setStartDelay(0)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mBackdrop.setVisibility(View.GONE);
+ mBackdropFront.animate().cancel();
+ mBackdropBack.animate().cancel();
+ mHandler.post(mHideBackdropFront);
+ }
+ });
+ if (mKeyguardFadingAway) {
+ mBackdrop.animate()
+
+ // Make it disappear faster, as the focus should be on the activity
+ // behind.
+ .setDuration(mKeyguardFadingAwayDuration / 2)
+ .setStartDelay(mKeyguardFadingAwayDelay)
+ .setInterpolator(mLinearInterpolator)
+ .start();
+ }
}
}
}
@@ -2185,8 +2226,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mNotificationPanel.isQsExpanded();
}
- public boolean isScreenOnComingFromTouch() {
- return mScreenOnComingFromTouch;
+ public boolean isWakeUpComingFromTouch() {
+ return mWakeUpComingFromTouch;
}
public boolean isFalsingThresholdNeeded() {
@@ -2806,8 +2847,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|| mStatusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
-
- mIconController.setIconsDark(allowLight && light);
+ boolean animate = mFingerprintUnlockController == null
+ || (mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ && mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
+ mIconController.setIconsDark(allowLight && light, animate);
}
// restore the recents bit
if (wasRecentsVisible) {
@@ -2854,7 +2899,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void checkBarMode(int mode, int windowState, BarTransitions transitions,
boolean noAnimation) {
final boolean powerSave = mBatteryController.isPowerSave();
- final boolean anim = !noAnimation && (mScreenOn == null || mScreenOn)
+ final boolean anim = !noAnimation && mDeviceInteractive
&& windowState != WINDOW_STATE_HIDDEN && !powerSave;
if (powerSave && getBarState() == StatusBarState.SHADE) {
mode = MODE_WARNING;
@@ -3263,14 +3308,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mScreenOn = false;
notifyNavigationBarScreenOn(false);
notifyHeadsUpScreenOff();
finishBarAnimations();
resetUserExpandedStates();
}
else if (Intent.ACTION_SCREEN_ON.equals(action)) {
- mScreenOn = true;
notifyNavigationBarScreenOn(true);
}
}
@@ -3908,7 +3951,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
setBarState(StatusBarState.KEYGUARD);
updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
- if (!mScreenOnFromKeyguard) {
+ if (!mDeviceInteractive) {
// If the screen is off already, we need to disable touch events because these might
// collapse the panel after we expanded it, and thus we would end up with a blank
@@ -3927,6 +3970,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void onLaunchTransitionFadingEnded() {
mNotificationPanel.setAlpha(1.0f);
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mLaunchTransitionFadingAway = false;
mScrimController.forceHideScrims(false /* hide */);
@@ -3990,6 +4035,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
/**
+ * Fades the content of the Keyguard while we are dozing and makes it invisible when finished
+ * fading.
+ */
+ public void fadeKeyguardWhilePulsing() {
+ mNotificationPanel.animate()
+ .alpha(0f)
+ .setStartDelay(0)
+ .setDuration(FADE_KEYGUARD_DURATION_PULSING)
+ .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
+ .start();
+ }
+
+ /**
* Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
* Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
* because the launched app crashed or something else went wrong.
@@ -4001,6 +4059,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void onLaunchTransitionTimeout() {
Log.w(TAG, "Launch transition: Timeout!");
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
mNotificationPanel.resetViews();
}
@@ -4023,11 +4083,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setBarState(StatusBarState.SHADE);
if (mLeaveOpenOnKeyguardHide) {
mLeaveOpenOnKeyguardHide = false;
- mNotificationPanel.animateToFullShade(calculateGoingToFullShadeDelay());
+ long delay = calculateGoingToFullShadeDelay();
+ mNotificationPanel.animateToFullShade(delay);
if (mDraggedDownRow != null) {
mDraggedDownRow.setUserLocked(false);
mDraggedDownRow = null;
}
+
+ // Disable layout transitions in navbar for this transition because the load is just
+ // too heavy for the CPU and GPU on any device.
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setLayoutTransitionsEnabled(false);
+ mNavigationBarView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mNavigationBarView.setLayoutTransitionsEnabled(true);
+ }
+ }, delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+ }
} else {
instantCollapseNotificationPanel();
}
@@ -4039,9 +4112,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mQSPanel.refreshAllTiles();
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+ releaseGestureWakeLock();
+ mNotificationPanel.onAffordanceLaunchEnded();
+ mNotificationPanel.animate().cancel();
+ mNotificationPanel.setAlpha(1f);
return staying;
}
+ private void releaseGestureWakeLock() {
+ if (mGestureWakeLock.isHeld()) {
+ mGestureWakeLock.release();
+ }
+ }
+
public long calculateGoingToFullShadeDelay() {
return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
}
@@ -4053,6 +4136,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
+ mKeyguardGoingAway = true;
mIconController.appTransitionPending();
}
@@ -4084,6 +4168,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
*/
public void finishKeyguardFadingAway() {
mKeyguardFadingAway = false;
+ mKeyguardGoingAway = false;
}
public void stopWaitingForKeyguardExit() {
@@ -4128,9 +4213,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void updateDozingState() {
boolean animate = !mDozing && mDozeScrimController.isPulsing();
mNotificationPanel.setDozing(mDozing, animate);
- mStackScroller.setDark(mDozing, animate, mScreenOnTouchLocation);
+ mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
mScrimController.setDozing(mDozing);
- mDozeScrimController.setDozing(mDozing, animate);
+
+ // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
+ // for pulsing so the Keyguard fade-out animation scrim can take over.
+ mDozeScrimController.setDozing(mDozing &&
+ mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate);
}
public void updateStackScrollerState(boolean goingToFullShade) {
@@ -4161,6 +4251,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed();
}
+ public void endAffordanceLaunch() {
+ releaseGestureWakeLock();
+ mNotificationPanel.onAffordanceLaunchEnded();
+ }
+
public boolean onBackPressed() {
if (mStatusBarKeyguardViewManager.onBackPressed()) {
return true;
@@ -4181,7 +4276,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
public boolean onSpacePressed() {
- if (mScreenOn != null && mScreenOn
+ if (mDeviceInteractive
&& (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
@@ -4389,23 +4484,58 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
}
- public void onScreenTurnedOff() {
- mScreenOnFromKeyguard = false;
- mScreenOnComingFromTouch = false;
- mScreenOnTouchLocation = null;
+ public void onStartedGoingToSleep() {
+ mStartedGoingToSleep = true;
+ }
+
+ public void onFinishedGoingToSleep() {
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
+ mLaunchCameraOnScreenTurningOn = false;
+ mStartedGoingToSleep = false;
+ mDeviceInteractive = false;
+ mWakeUpComingFromTouch = false;
+ mWakeUpTouchLocation = null;
mStackScroller.setAnimationsEnabled(false);
updateVisibleToUser();
+ if (mLaunchCameraOnFinishedGoingToSleep) {
+ mLaunchCameraOnFinishedGoingToSleep = false;
+
+ // This gets executed before we will show Keyguard, so post it in order that the state
+ // is correct.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onCameraLaunchGestureDetected(mLastCameraLaunchSource);
+ }
+ });
+ }
}
- public void onScreenTurnedOn() {
- mScreenOnFromKeyguard = true;
+ public void onStartedWakingUp() {
+ mDeviceInteractive = true;
mStackScroller.setAnimationsEnabled(true);
mNotificationPanel.setTouchDisabled(false);
updateVisibleToUser();
}
public void onScreenTurningOn() {
+ mScreenTurningOn = true;
mNotificationPanel.onScreenTurningOn();
+ if (mLaunchCameraOnScreenTurningOn) {
+ mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
+ mLaunchCameraOnScreenTurningOn = false;
+ }
+ }
+
+ private void vibrateForCameraGesture() {
+ // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
+ mVibrator.vibrate(new long[] { 0, 750L }, -1 /* repeat */);
+ }
+
+ public void onScreenTurnedOn() {
+ mScreenTurningOn = false;
+ mDozeScrimController.onScreenTurnedOn();
}
/**
@@ -4716,8 +4846,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mDozing && mDozeScrimController.isPulsing()) {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
pm.wakeUp(time, "com.android.systemui:NODOZE");
- mScreenOnComingFromTouch = true;
- mScreenOnTouchLocation = new PointF(event.getX(), event.getY());
+ mWakeUpComingFromTouch = true;
+ mWakeUpTouchLocation = new PointF(event.getX(), event.getY());
mNotificationPanel.setTouchDisabled(false);
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
@@ -4742,8 +4872,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void appTransitionStarting(long startTime, long duration) {
// Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway
- if (!mKeyguardFadingAway) {
+ // setKeyguardFadingAway.
+ if (!mKeyguardGoingAway) {
mIconController.appTransitionStarting(startTime, duration);
}
if (mIconPolicy != null) {
@@ -4751,8 +4881,54 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ @Override
+ public void onCameraLaunchGestureDetected(int source) {
+ mLastCameraLaunchSource = source;
+ if (mStartedGoingToSleep) {
+ mLaunchCameraOnFinishedGoingToSleep = true;
+ return;
+ }
+ if (!mNotificationPanel.canCameraGestureBeLaunched(
+ mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
+ return;
+ }
+ if (!mDeviceInteractive) {
+ PowerManager pm = mContext.getSystemService(PowerManager.class);
+ pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE");
+ mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+ }
+ vibrateForCameraGesture();
+ if (!mStatusBarKeyguardViewManager.isShowing()) {
+ startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
+ true /* dismissShade */);
+ } else {
+ if (!mDeviceInteractive) {
+ // Avoid flickering of the scrim when we instant launch the camera and the bouncer
+ // comes on.
+ mScrimController.dontAnimateBouncerChangesUntilNextFrame();
+ mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
+ }
+ if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
+ mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
+ } else {
+ // We need to defer the camera launch until the screen comes on, since otherwise
+ // we will dismiss us too early since we are waiting on an activity to be drawn and
+ // incorrectly get notified because of the screen on event (which resumes and pauses
+ // some activities)
+ mLaunchCameraOnScreenTurningOn = true;
+ }
+ }
+ }
+
+ public void notifyFpAuthModeChanged() {
+ updateDozing();
+ }
+
private void updateDozing() {
- mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD;
+ // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
+ mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
+ || mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
updateDozingState();
}
@@ -4782,7 +4958,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
- private final class DozeServiceHost implements DozeHost {
+ private final class DozeServiceHost extends KeyguardUpdateMonitorCallback implements DozeHost {
// Amount of time to allow to update the time shown on the screen before releasing
// the wakelock. This timeout is design to compensate for the fact that we don't
// currently have a way to know when time display contents have actually been
@@ -4856,6 +5032,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
+ public boolean isPulsingBlocked() {
+ return mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+ }
+
+ @Override
public boolean isNotificationLightOn() {
return mNotificationLightOn;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1a35500..b9e9292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -22,7 +22,6 @@ import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
-import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
@@ -44,12 +43,15 @@ import com.android.systemui.statusbar.stack.StackStateAnimator;
public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
HeadsUpManager.OnHeadsUpChangedListener {
public static final long ANIMATION_DURATION = 220;
+ public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
+ = new PathInterpolator(0f, 0, 0.7f, 1f);
private static final float SCRIM_BEHIND_ALPHA = 0.62f;
private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
private static final int TAG_KEY_ANIM = R.id.scrim;
+ private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
private static final int TAG_HUN_START_ALPHA = R.id.hun_scrim_alpha_start;
private static final int TAG_HUN_END_ALPHA = R.id.hun_scrim_alpha_end;
@@ -71,9 +73,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private long mDurationOverride = -1;
private long mAnimationDelay;
private Runnable mOnAnimationFinished;
- private boolean mAnimationStarted;
private final Interpolator mInterpolator = new DecelerateInterpolator();
- private final Interpolator mKeyguardFadeOutInterpolator = new PathInterpolator(0f, 0, 0.7f, 1f);
private BackDropView mBackDropView;
private boolean mScrimSrcEnabled;
private boolean mDozing;
@@ -86,6 +86,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private float mTopHeadsUpDragAmount;
private View mDraggedHeadsUpView;
private boolean mForceHideScrims;
+ private boolean mSkipFirstFrame;
+ private boolean mDontAnimateBouncerChanges;
public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
boolean scrimSrcEnabled) {
@@ -124,7 +126,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void setBouncerShowing(boolean showing) {
mBouncerShowing = showing;
- mAnimateChange = !mExpanding;
+ mAnimateChange = !mExpanding && !mDontAnimateBouncerChanges;
scheduleUpdate();
}
@@ -133,19 +135,25 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
scheduleUpdate();
}
- public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
+ public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished,
+ boolean skipFirstFrame) {
mWakeAndUnlocking = false;
mAnimateKeyguardFadingOut = true;
mDurationOverride = duration;
mAnimationDelay = delay;
mAnimateChange = true;
+ mSkipFirstFrame = skipFirstFrame;
mOnAnimationFinished = onAnimationFinished;
scheduleUpdate();
+
+ // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
+ // the changes we just scheduled.
+ onPreDraw();
}
public void abortKeyguardFadingOut() {
if (mAnimateKeyguardFadingOut) {
- endAnimateKeyguardFadingOut();
+ endAnimateKeyguardFadingOut(true /* force */);
}
}
@@ -198,8 +206,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
// During wake and unlock, we first hide everything behind a black scrim, which then
// gets faded out from animateKeyguardFadingOut.
- setScrimInFrontColor(1f);
- setScrimBehindColor(0f);
+ if (mDozing) {
+ setScrimInFrontColor(0f);
+ setScrimBehindColor(1f);
+ } else {
+ setScrimInFrontColor(1f);
+ setScrimBehindColor(0f);
+ }
} else if (!mKeyguardShowing && !mBouncerShowing) {
updateScrimNormal();
setScrimInFrontColor(0);
@@ -258,10 +271,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
private void setScrimColor(View scrim, float alpha) {
- Object runningAnim = scrim.getTag(TAG_KEY_ANIM);
- if (runningAnim instanceof ValueAnimator) {
- ((ValueAnimator) runningAnim).cancel();
- scrim.setTag(TAG_KEY_ANIM, null);
+ ValueAnimator runningAnim = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM);
+ Float target = (Float) scrim.getTag(TAG_KEY_ANIM_TARGET);
+ if (runningAnim != null && target != null) {
+ if (alpha != target) {
+ runningAnim.cancel();
+ } else {
+ return;
+ }
}
if (mAnimateChange) {
startScrimAnimation(scrim, alpha);
@@ -325,39 +342,51 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mOnAnimationFinished = null;
}
scrim.setTag(TAG_KEY_ANIM, null);
+ scrim.setTag(TAG_KEY_ANIM_TARGET, null);
}
});
anim.start();
+ if (mSkipFirstFrame) {
+ anim.setCurrentPlayTime(16);
+ }
scrim.setTag(TAG_KEY_ANIM, anim);
- mAnimationStarted = true;
+ scrim.setTag(TAG_KEY_ANIM_TARGET, target);
}
private Interpolator getInterpolator() {
- return mAnimateKeyguardFadingOut ? mKeyguardFadeOutInterpolator : mInterpolator;
+ return mAnimateKeyguardFadingOut ? KEYGUARD_FADE_OUT_INTERPOLATOR : mInterpolator;
}
@Override
public boolean onPreDraw() {
mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
mUpdatePending = false;
+ if (mDontAnimateBouncerChanges) {
+ mDontAnimateBouncerChanges = false;
+ }
updateScrims();
mDurationOverride = -1;
mAnimationDelay = 0;
+ mSkipFirstFrame = false;
// Make sure that we always call the listener even if we didn't start an animation.
- endAnimateKeyguardFadingOut();
- mAnimationStarted = false;
+ endAnimateKeyguardFadingOut(false /* force */);
return true;
}
- private void endAnimateKeyguardFadingOut() {
+ private void endAnimateKeyguardFadingOut(boolean force) {
mAnimateKeyguardFadingOut = false;
- if (!mAnimationStarted && mOnAnimationFinished != null) {
+ if ((force || (!isAnimating(mScrimInFront) && !isAnimating(mScrimBehind)))
+ && mOnAnimationFinished != null) {
mOnAnimationFinished.run();
mOnAnimationFinished = null;
}
}
+ private boolean isAnimating(View scrim) {
+ return scrim.getTag(TAG_KEY_ANIM) != null;
+ }
+
public void setBackDropView(BackDropView backDropView) {
mBackDropView = backDropView;
mBackDropView.setOnVisibilityChangedRunnable(new Runnable() {
@@ -471,4 +500,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mAnimateChange = false;
scheduleUpdate();
}
+
+ public void dontAnimateBouncerChangesUntilNextFrame() {
+ mDontAnimateBouncerChanges = true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
deleted file mode 100644
index 45c8938..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.hardware.camera2.CameraManager;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.util.Log;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Handles launching the secure camera properly even when other applications may be using the camera
- * hardware.
- *
- * When other applications (e.g., Face Unlock) are using the camera, they must close the camera to
- * allow the secure camera to open it. Since we want to minimize the delay when opening the secure
- * camera, other apps should close the camera at the first possible opportunity (i.e., as soon as
- * the user begins swiping to go to the secure camera).
- *
- * If the camera is unavailable when the user begins to swipe, the SecureCameraLaunchManager sends a
- * broadcast to tell other apps to close the camera. When and if the user completes their swipe to
- * launch the secure camera, the SecureCameraLaunchManager delays launching the secure camera until
- * a callback indicates that the camera has become available. If it doesn't receive that callback
- * within a specified timeout period, the secure camera is launched anyway.
- *
- * Ideally, the secure camera would handle waiting for the camera to become available. This allows
- * some of the time necessary to close the camera to happen in parallel with starting the secure
- * camera app. We can't rely on all third-party camera apps to handle this. However, an app can
- * put com.android.systemui.statusbar.phone.will_wait_for_camera_available in its meta-data to
- * indicate that it will be responsible for waiting for the camera to become available.
- *
- * It is assumed that the functions in this class, including the constructor, will be called from
- * the UI thread.
- */
-public class SecureCameraLaunchManager {
- private static final boolean DEBUG = false;
- private static final String TAG = "SecureCameraLaunchManager";
-
- // Action sent as a broadcast to tell other apps to stop using the camera. Other apps that use
- // the camera from keyguard (e.g., Face Unlock) should listen for this broadcast and close the
- // camera as soon as possible after receiving it.
- private static final String CLOSE_CAMERA_ACTION_NAME =
- "com.android.systemui.statusbar.phone.CLOSE_CAMERA";
-
- // Apps should put this field in their meta-data to indicate that they will take on the
- // responsibility of waiting for the camera to become available. If this field is present, the
- // SecureCameraLaunchManager launches the secure camera even if the camera hardware has not
- // become available. Having the secure camera app do the waiting is the optimal approach, but
- // without this field, the SecureCameraLaunchManager doesn't launch the secure camera until the
- // camera hardware is available.
- private static final String META_DATA_WILL_WAIT_FOR_CAMERA_AVAILABLE =
- "com.android.systemui.statusbar.phone.will_wait_for_camera_available";
-
- // If the camera hardware hasn't become available after this period of time, the
- // SecureCameraLaunchManager launches the secure camera anyway.
- private static final int CAMERA_AVAILABILITY_TIMEOUT_MS = 1000;
-
- private Context mContext;
- private Handler mHandler;
- private LockPatternUtils mLockPatternUtils;
- private KeyguardBottomAreaView mKeyguardBottomArea;
-
- private CameraManager mCameraManager;
- private CameraAvailabilityCallback mCameraAvailabilityCallback;
- private Map<String, Boolean> mCameraAvailabilityMap;
- private boolean mWaitingToLaunchSecureCamera;
- private Runnable mLaunchCameraRunnable;
-
- private class CameraAvailabilityCallback extends CameraManager.AvailabilityCallback {
- @Override
- public void onCameraUnavailable(String cameraId) {
- if (DEBUG) Log.d(TAG, "onCameraUnavailble(" + cameraId + ")");
- mCameraAvailabilityMap.put(cameraId, false);
- }
-
- @Override
- public void onCameraAvailable(String cameraId) {
- if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
- mCameraAvailabilityMap.put(cameraId, true);
-
- // If we were waiting for the camera hardware to become available to launch the
- // secure camera, we can launch it now if all cameras are available. If one or more
- // cameras are still not available, we will get this callback again for those
- // cameras.
- if (mWaitingToLaunchSecureCamera && areAllCamerasAvailable()) {
- mKeyguardBottomArea.launchCamera();
- mWaitingToLaunchSecureCamera = false;
-
- // We no longer need to launch the camera after the timeout hits.
- mHandler.removeCallbacks(mLaunchCameraRunnable);
- }
- }
- }
-
- public SecureCameraLaunchManager(Context context, KeyguardBottomAreaView keyguardBottomArea) {
- mContext = context;
- mHandler = new Handler();
- mLockPatternUtils = new LockPatternUtils(context);
- mKeyguardBottomArea = keyguardBottomArea;
-
- mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
- mCameraAvailabilityCallback = new CameraAvailabilityCallback();
-
- // An onCameraAvailable() or onCameraUnavailable() callback will be received for each camera
- // when the availability callback is registered, thus initializing the map.
- //
- // Keeping track of the state of all cameras using the onCameraAvailable() and
- // onCameraUnavailable() callbacks can get messy when dealing with hot-pluggable cameras.
- // However, we have a timeout in place such that we will never hang waiting for cameras.
- mCameraAvailabilityMap = new HashMap<String, Boolean>();
-
- mWaitingToLaunchSecureCamera = false;
- mLaunchCameraRunnable = new Runnable() {
- @Override
- public void run() {
- if (mWaitingToLaunchSecureCamera) {
- Log.w(TAG, "Timeout waiting for camera availability");
- mKeyguardBottomArea.launchCamera();
- mWaitingToLaunchSecureCamera = false;
- }
- }
- };
- }
-
- /**
- * Initializes the SecureCameraManager and starts listening for camera availability.
- */
- public void create() {
- mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, mHandler);
- }
-
- /**
- * Stops listening for camera availability and cleans up the SecureCameraManager.
- */
- public void destroy() {
- mCameraManager.unregisterAvailabilityCallback(mCameraAvailabilityCallback);
- }
-
- /**
- * Called when the user is starting to swipe horizontally, possibly to start the secure camera.
- * Although this swipe ultimately may not result in the secure camera opening, we need to stop
- * all other camera usage (e.g., Face Unlock) as soon as possible. We send out a broadcast to
- * notify other apps that they should close the camera immediately. The broadcast is sent even
- * if the camera appears to be available, because there could be an app that is about to open
- * the camera.
- */
- public void onSwipingStarted() {
- if (DEBUG) Log.d(TAG, "onSwipingStarted");
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- Intent intent = new Intent();
- intent.setAction(CLOSE_CAMERA_ACTION_NAME);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent);
- }
- });
- }
-
- /**
- * Called when the secure camera should be started. If the camera is available or the secure
- * camera app has indicated that it will wait for camera availability, the secure camera app is
- * launched immediately. Otherwise, we wait for the camera to become available (or timeout)
- * before launching the secure camera.
- */
- public void startSecureCameraLaunch() {
- if (DEBUG) Log.d(TAG, "startSecureCameraLunch");
- if (areAllCamerasAvailable() || targetWillWaitForCameraAvailable()) {
- mKeyguardBottomArea.launchCamera();
- } else {
- mWaitingToLaunchSecureCamera = true;
- mHandler.postDelayed(mLaunchCameraRunnable, CAMERA_AVAILABILITY_TIMEOUT_MS);
- }
- }
-
- /**
- * Returns true if all of the cameras we are tracking are currently available.
- */
- private boolean areAllCamerasAvailable() {
- for (boolean cameraAvailable: mCameraAvailabilityMap.values()) {
- if (!cameraAvailable) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Determines if the secure camera app will wait for the camera hardware to become available
- * before trying to open the camera. If so, we can fire off an intent to start the secure
- * camera app before the camera is available. Otherwise, it is our responsibility to wait for
- * the camera hardware to become available before firing off the intent to start the secure
- * camera.
- *
- * Ideally we are able to fire off the secure camera intent as early as possibly so that, if the
- * camera is closing, it can continue to close while the secure camera app is opening. This
- * improves secure camera startup time.
- */
- private boolean targetWillWaitForCameraAvailable() {
- // Create intent that would launch the secure camera.
- Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
- .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- PackageManager packageManager = mContext.getPackageManager();
-
- // Get the list of applications that can handle the intent.
- final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
- if (appList.size() == 0) {
- if (DEBUG) Log.d(TAG, "No targets found for secure camera intent");
- return false;
- }
-
- // Get the application that the intent resolves to.
- ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
- KeyguardUpdateMonitor.getCurrentUser());
-
- if (resolved == null || resolved.activityInfo == null) {
- return false;
- }
-
- // If we would need to launch the resolver activity, then we can't assume that the target
- // is one that would wait for the camera.
- if (wouldLaunchResolverActivity(resolved, appList)) {
- if (DEBUG) Log.d(TAG, "Secure camera intent would launch resolver");
- return false;
- }
-
- // If the target doesn't have meta-data we must assume it won't wait for the camera.
- if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
- if (DEBUG) Log.d(TAG, "No meta-data found for secure camera application");
- return false;
- }
-
- // Check the secure camera app meta-data to see if it indicates that it will wait for the
- // camera to become available.
- boolean willWaitForCameraAvailability =
- resolved.activityInfo.metaData.getBoolean(META_DATA_WILL_WAIT_FOR_CAMERA_AVAILABLE);
-
- if (DEBUG) Log.d(TAG, "Target will wait for camera: " + willWaitForCameraAvailability);
-
- return willWaitForCameraAvailability;
- }
-
- /**
- * Determines if the activity that would be launched by the intent is the ResolverActivity.
- */
- private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
- // If the list contains the resolved activity, then it can't be the ResolverActivity itself.
- for (int i = 0; i < appList.size(); i++) {
- ResolveInfo tmp = appList.get(i);
- if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
- && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index a1e9ece..18db5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -19,6 +19,7 @@ import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.graphics.drawable.RippleDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 6538ba6..0161b52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -32,6 +32,7 @@ import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
@@ -217,6 +218,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
});
requestCaptureValues();
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ ((RippleDrawable) getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 7ffbd65..0fc5a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -337,8 +337,10 @@ public class StatusBarIconController implements Tunable {
}
}
- public void setIconsDark(boolean dark) {
- if (mTransitionPending) {
+ public void setIconsDark(boolean dark, boolean animate) {
+ if (!animate) {
+ setIconTintInternal(dark ? 1.0f : 0.0f);
+ } else if (mTransitionPending) {
deferIconTintChange(dark ? 1.0f : 0.0f);
} else if (mTransitionDeferring) {
animateIconTint(dark ? 1.0f : 0.0f,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 735b604..25b653b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -24,6 +24,7 @@ import android.os.Trace;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
import com.android.internal.widget.LockPatternUtils;
@@ -48,6 +49,8 @@ public class StatusBarKeyguardViewManager {
// with the appear animations of the PIN/pattern/password views.
private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
+ private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200;
+
private static String TAG = "StatusBarKeyguardViewManager";
private final Context mContext;
@@ -56,6 +59,7 @@ public class StatusBarKeyguardViewManager {
private ViewMediatorCallback mViewMediatorCallback;
private PhoneStatusBar mPhoneStatusBar;
private ScrimController mScrimController;
+ private FingerprintUnlockController mFingerprintUnlockController;
private ViewGroup mContainer;
private StatusBarWindowManager mStatusBarWindowManager;
@@ -71,10 +75,8 @@ public class StatusBarKeyguardViewManager {
private boolean mLastOccluded;
private boolean mLastBouncerShowing;
private boolean mLastBouncerDismissible;
- private boolean mLastDeferScrimFadeOut;
private OnDismissAction mAfterKeyguardGoneAction;
private boolean mDeviceWillWakeUp;
- private boolean mWakeAndUnlocking;
private boolean mDeferScrimFadeOut;
public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
@@ -86,12 +88,14 @@ public class StatusBarKeyguardViewManager {
public void registerStatusBar(PhoneStatusBar phoneStatusBar,
ViewGroup container, StatusBarWindowManager statusBarWindowManager,
- ScrimController scrimController) {
+ ScrimController scrimController,
+ FingerprintUnlockController fingerprintUnlockController) {
mPhoneStatusBar = phoneStatusBar;
mContainer = container;
mStatusBarWindowManager = statusBarWindowManager;
mScrimController = scrimController;
if (mBouncer != null) mBouncer.removeView();
+ mFingerprintUnlockController = fingerprintUnlockController;
mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
mStatusBarWindowManager, container);
}
@@ -161,30 +165,39 @@ public class StatusBarKeyguardViewManager {
}
}
+ public void onStartedGoingToSleep() {
+ mPhoneStatusBar.onStartedGoingToSleep();
+ }
+
public void onFinishedGoingToSleep() {
mDeviceInteractive = false;
- mPhoneStatusBar.onScreenTurnedOff();
+ mPhoneStatusBar.onFinishedGoingToSleep();
mBouncer.onScreenTurnedOff();
}
public void onStartedWakingUp() {
mDeviceInteractive = true;
mDeviceWillWakeUp = false;
- mPhoneStatusBar.onScreenTurnedOn();
+ mPhoneStatusBar.onStartedWakingUp();
}
public void onScreenTurningOn() {
mPhoneStatusBar.onScreenTurningOn();
}
+ public boolean isScreenTurnedOn() {
+ return mScreenTurnedOn;
+ }
+
public void onScreenTurnedOn() {
mScreenTurnedOn = true;
- mWakeAndUnlocking = false;
if (mDeferScrimFadeOut) {
mDeferScrimFadeOut = false;
- animateScrimControllerKeyguardFadingOut(0, 200);
+ animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+ true /* skipFirstFrame */);
updateStates();
}
+ mPhoneStatusBar.onScreenTurnedOn();
}
public void onScreenTurnedOff() {
@@ -261,7 +274,8 @@ public class StatusBarKeyguardViewManager {
updateStates();
mScrimController.animateKeyguardFadingOut(
PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
- PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
+ PhoneStatusBar.FADE_KEYGUARD_DURATION, null,
+ false /* skipFirstFrame */);
}
}, new Runnable() {
@Override
@@ -273,18 +287,43 @@ public class StatusBarKeyguardViewManager {
}
});
} else {
- mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
- boolean staying = mPhoneStatusBar.hideKeyguard();
- if (!staying) {
+ if (mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
+ mFingerprintUnlockController.startKeyguardFadingAway();
+ mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 240);
mStatusBarWindowManager.setKeyguardFadingAway(true);
- if (mWakeAndUnlocking && !mScreenTurnedOn) {
- mDeferScrimFadeOut = true;
+ mPhoneStatusBar.fadeKeyguardWhilePulsing();
+ animateScrimControllerKeyguardFadingOut(0, 240, new Runnable() {
+ @Override
+ public void run() {
+ mPhoneStatusBar.hideKeyguard();
+ }
+ }, false /* skipFirstFrame */);
+ } else {
+ mFingerprintUnlockController.startKeyguardFadingAway();
+ mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
+ boolean staying = mPhoneStatusBar.hideKeyguard();
+ if (!staying) {
+ mStatusBarWindowManager.setKeyguardFadingAway(true);
+ if (mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) {
+ if (!mScreenTurnedOn) {
+ mDeferScrimFadeOut = true;
+ } else {
+
+ // Screen is already on, don't defer with fading out.
+ animateScrimControllerKeyguardFadingOut(0,
+ WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+ true /* skipFirstFrame */);
+ }
+ } else {
+ animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
+ false /* skipFirstFrame */);
+ }
} else {
- animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration);
+ mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
+ mPhoneStatusBar.finishKeyguardFadingAway();
}
- } else {
- mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
- mPhoneStatusBar.finishKeyguardFadingAway();
}
mStatusBarWindowManager.setKeyguardShowing(false);
mBouncer.hide(true /* destroyView */);
@@ -292,24 +331,31 @@ public class StatusBarKeyguardViewManager {
executeAfterKeyguardGoneAction();
updateStates();
}
+ }
+ private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+ boolean skipFirstFrame) {
+ animateScrimControllerKeyguardFadingOut(delay, duration, null /* endRunnable */,
+ skipFirstFrame);
}
- private void animateScrimControllerKeyguardFadingOut(long delay, long duration) {
+ private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+ final Runnable endRunnable, boolean skipFirstFrame) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "Fading out", 0);
mScrimController.animateKeyguardFadingOut(delay, duration, new Runnable() {
@Override
public void run() {
+ if (endRunnable != null) {
+ endRunnable.run();
+ }
mStatusBarWindowManager.setKeyguardFadingAway(false);
mPhoneStatusBar.finishKeyguardFadingAway();
- if (mPhoneStatusBar.getNavigationBarView() != null) {
- mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
- }
+ mFingerprintUnlockController.finishKeyguardFadingAway();
WindowManagerGlobal.getInstance().trimMemory(
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "Fading out", 0);
}
- });
+ }, skipFirstFrame);
}
private void executeAfterKeyguardGoneAction() {
@@ -349,6 +395,7 @@ public class StatusBarKeyguardViewManager {
*/
public boolean onBackPressed() {
if (mBouncer.isShowing()) {
+ mPhoneStatusBar.endAffordanceLaunch();
reset();
return true;
}
@@ -383,7 +430,6 @@ public class StatusBarKeyguardViewManager {
boolean occluded = mOccluded;
boolean bouncerShowing = mBouncer.isShowing();
boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
- boolean deferScrimFadeOut = mDeferScrimFadeOut;
if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
|| mFirstUpdate) {
@@ -394,16 +440,18 @@ public class StatusBarKeyguardViewManager {
}
}
- // Hide navigation bar on Keyguard but not on bouncer and also if we are deferring a scrim
- // fade out, i.e. we are waiting for the screen to have turned on.
- boolean navBarVisible = !deferScrimFadeOut && (!(showing && !occluded) || bouncerShowing);
- boolean lastNavBarVisible = !mLastDeferScrimFadeOut && (!(mLastShowing && !mLastOccluded)
- || mLastBouncerShowing);
+ boolean navBarVisible = (!(showing && !occluded) || bouncerShowing);
+ boolean lastNavBarVisible = (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing);
if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
if (mPhoneStatusBar.getNavigationBarView() != null) {
if (navBarVisible) {
- mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
- getNavBarShowDelay());
+ long delay = getNavBarShowDelay();
+ if (delay == 0) {
+ mMakeNavigationBarVisibleRunnable.run();
+ } else {
+ mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
+ delay);
+ }
} else {
mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
@@ -419,7 +467,7 @@ public class StatusBarKeyguardViewManager {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
- updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
+ updateMonitor.onKeyguardVisibilityChanged(showing && !occluded);
}
if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
@@ -428,7 +476,6 @@ public class StatusBarKeyguardViewManager {
mFirstUpdate = false;
mLastShowing = showing;
mLastOccluded = occluded;
- mLastDeferScrimFadeOut = deferScrimFadeOut;
mLastBouncerShowing = bouncerShowing;
mLastBouncerDismissible = bouncerDismissible;
@@ -485,16 +532,16 @@ public class StatusBarKeyguardViewManager {
* Notifies that the user has authenticated by other means than using the bouncer, for example,
* fingerprint.
*/
- public void notifyKeyguardAuthenticated() {
- mBouncer.notifyKeyguardAuthenticated();
+ public void notifyKeyguardAuthenticated(boolean strongAuth) {
+ mBouncer.notifyKeyguardAuthenticated(strongAuth);
}
- public void setWakeAndUnlocking() {
- mWakeAndUnlocking = true;
- mScrimController.setWakeAndUnlocking();
- if (mPhoneStatusBar.getNavigationBarView() != null) {
- mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
- }
+ public void showBouncerMessage(String message, int color) {
+ mBouncer.showMessage(message, color);
+ }
+
+ public ViewRootImpl getViewRootImpl() {
+ return mPhoneStatusBar.getStatusBarView().getViewRootImpl();
}
public boolean isKeyguardShowingMedia() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 48a8886..35bc599 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -24,6 +24,7 @@ import android.os.SystemProperties;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
import android.view.WindowManager;
import com.android.keyguard.R;
@@ -47,13 +48,15 @@ public class StatusBarWindowManager {
private WindowManager.LayoutParams mLpChanged;
private int mBarHeight;
private final boolean mKeyguardScreenRotation;
-
+ private final float mScreenBrightnessDoze;
private final State mCurrentState = new State();
public StatusBarWindowManager(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+ mScreenBrightnessDoze = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
}
private boolean shouldEnableKeyguardScreenRotation() {
@@ -181,6 +184,7 @@ public class StatusBarWindowManager {
applyInputFeatures(state);
applyFitsSystemWindows(state);
applyModalFlag(state);
+ applyBrightness(state);
if (mLp.copyFrom(mLpChanged) != 0) {
mWindowManager.updateViewLayout(mStatusBarView, mLp);
}
@@ -204,6 +208,14 @@ public class StatusBarWindowManager {
}
}
+ private void applyBrightness(State state) {
+ if (state.forceDozeBrightness) {
+ mLpChanged.screenBrightness = mScreenBrightnessDoze;
+ } else {
+ mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
+ }
+ }
+
public void setKeyguardShowing(boolean showing) {
mCurrentState.keyguardShowing = showing;
apply(mCurrentState);
@@ -278,6 +290,15 @@ public class StatusBarWindowManager {
apply(mCurrentState);
}
+ /**
+ * Set whether the screen brightness is forced to the value we use for doze mode by the status
+ * bar window.
+ */
+ public void setForceDozeBrightness(boolean forceDozeBrightness) {
+ mCurrentState.forceDozeBrightness = forceDozeBrightness;
+ apply(mCurrentState);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("StatusBarWindowManager state:");
pw.println(mCurrentState);
@@ -296,6 +317,7 @@ public class StatusBarWindowManager {
boolean headsUpShowing;
boolean forceStatusBarVisible;
boolean forceCollapsed;
+ boolean forceDozeBrightness;
/**
* The {@link BaseStatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index bd537f7..a91cd51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -132,7 +132,7 @@ public class UnlockMethodCache {
}
@Override
- public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
+ public void onFingerprintAuthenticated(int userId) {
if (!mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()) {
return;
}
@@ -143,6 +143,11 @@ public class UnlockMethodCache {
public void onFaceUnlockStateChanged(boolean running, int userId) {
update(false /* updateAlways */);
}
+
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ update(false /* updateAlways */);
+ }
};
public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 6af9854..1595d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -36,6 +36,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
@@ -62,8 +63,9 @@ public class SecurityControllerImpl implements SecurityController {
private final IConnectivityManager mConnectivityManagerService;
private final DevicePolicyManager mDevicePolicyManager;
private final UserManager mUserManager;
- private final ArrayList<SecurityControllerCallback> mCallbacks
- = new ArrayList<SecurityControllerCallback>();
+
+ @GuardedBy("mCallbacks")
+ private final ArrayList<SecurityControllerCallback> mCallbacks = new ArrayList<>();
private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>();
private int mCurrentUserId;
@@ -161,16 +163,20 @@ public class SecurityControllerImpl implements SecurityController {
@Override
public void removeCallback(SecurityControllerCallback callback) {
- if (callback == null) return;
- if (DEBUG) Log.d(TAG, "removeCallback " + callback);
- mCallbacks.remove(callback);
+ synchronized (mCallbacks) {
+ if (callback == null) return;
+ if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+ mCallbacks.remove(callback);
+ }
}
@Override
public void addCallback(SecurityControllerCallback callback) {
- if (callback == null || mCallbacks.contains(callback)) return;
- if (DEBUG) Log.d(TAG, "addCallback " + callback);
- mCallbacks.add(callback);
+ synchronized (mCallbacks) {
+ if (callback == null || mCallbacks.contains(callback)) return;
+ if (DEBUG) Log.d(TAG, "addCallback " + callback);
+ mCallbacks.add(callback);
+ }
}
@Override
@@ -202,8 +208,10 @@ public class SecurityControllerImpl implements SecurityController {
}
private void fireCallbacks() {
- for (SecurityControllerCallback callback : mCallbacks) {
- callback.onStateChanged();
+ synchronized (mCallbacks) {
+ for (SecurityControllerCallback callback : mCallbacks) {
+ callback.onStateChanged();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index 753a7f7..56f6564 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -34,6 +34,7 @@ public class AnimationFilter {
boolean hasDelays;
boolean hasGoToFullShadeEvent;
boolean hasDarkEvent;
+ boolean hasHeadsUpDisappearClickEvent;
int darkAnimationOriginIndex;
public AnimationFilter animateAlpha() {
@@ -106,6 +107,10 @@ public class AnimationFilter {
hasDarkEvent = true;
darkAnimationOriginIndex = ev.darkAnimationOriginIndex;
}
+ if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+ .ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
+ hasHeadsUpDisappearClickEvent = true;
+ }
}
}
@@ -135,6 +140,7 @@ public class AnimationFilter {
hasDelays = false;
hasGoToFullShadeEvent = false;
hasDarkEvent = false;
+ hasHeadsUpDisappearClickEvent = false;
darkAnimationOriginIndex =
NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 608228c..772fab6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -660,7 +660,7 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public float getFalsingThresholdFactor() {
- return mPhoneStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+ return mPhoneStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
}
public View getChildAtPosition(MotionEvent ev) {
@@ -1927,7 +1927,9 @@ public class NotificationStackScrollLayout extends ViewGroup
boolean onBottom = false;
boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
if (!mIsExpanded && !isHeadsUp) {
- type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+ type = row.wasJustClicked()
+ ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
} else {
StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
if (viewState == null) {
@@ -3028,6 +3030,15 @@ public class NotificationStackScrollLayout extends ViewGroup
.animateY()
.animateZ(),
+ // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ new AnimationFilter()
+ .animateAlpha()
+ .animateHeight()
+ .animateTopInset()
+ .animateY()
+ .animateZ()
+ .hasDelays(),
+
// ANIMATION_TYPE_HEADS_UP_OTHER
new AnimationFilter()
.animateAlpha()
@@ -3099,6 +3110,9 @@ public class NotificationStackScrollLayout extends ViewGroup
// ANIMATION_TYPE_HEADS_UP_DISAPPEAR
StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+ // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+
// ANIMATION_TYPE_HEADS_UP_OTHER
StackStateAnimator.ANIMATION_DURATION_STANDARD,
@@ -3122,8 +3136,9 @@ public class NotificationStackScrollLayout extends ViewGroup
static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13;
static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14;
static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15;
- static final int ANIMATION_TYPE_HEADS_UP_OTHER = 16;
- static final int ANIMATION_TYPE_EVERYTHING = 17;
+ static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK = 16;
+ static final int ANIMATION_TYPE_HEADS_UP_OTHER = 17;
+ static final int ANIMATION_TYPE_EVERYTHING = 18;
static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index ccbbbbd..93995f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -130,7 +130,7 @@ public class StackScrollAlgorithm {
mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
- >= DisplayMetrics.DENSITY_XXHIGH;
+ >= DisplayMetrics.DENSITY_420;
// We don't want to clip the notification if a theme overrides the corner radius with
// a value larger than the default.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 97c7d30..b4ab48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -54,6 +54,7 @@ public class StackStateAnimator {
public static final int ANIMATION_DELAY_PER_ELEMENT_DARK = 24;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE_CHILDREN = 3;
+ public static final int ANIMATION_DELAY_HEADS_UP = 120;
private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
@@ -320,6 +321,9 @@ public class StackStateAnimator {
if (mAnimationFilter.hasGoToFullShadeEvent) {
return calculateDelayGoToFullShade(viewState);
}
+ if (mAnimationFilter.hasHeadsUpDisappearClickEvent) {
+ return ANIMATION_DELAY_HEADS_UP;
+ }
long minDelay = 0;
for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
@@ -890,7 +894,9 @@ public class StackStateAnimator {
mHeadsUpAppearChildren.add(changingView);
finalState.applyState(changingView, mTmpState);
} else if (event.animationType == NotificationStackScrollLayout
- .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR ||
+ event.animationType == NotificationStackScrollLayout
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
mHeadsUpDisappearChildren.add(changingView);
if (mHostLayout.indexOfChild(changingView) == -1) {
// This notification was actually removed, so we need to add it to the overlay
@@ -900,7 +906,11 @@ public class StackStateAnimator {
// We temporarily enable Y animations, the real filter will be combined
// afterwards anyway
mAnimationFilter.animateY = true;
- startViewAnimations(changingView, mTmpState, 0,
+ startViewAnimations(changingView, mTmpState,
+ event.animationType == NotificationStackScrollLayout
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ ? ANIMATION_DELAY_HEADS_UP
+ : 0,
ANIMATION_DURATION_HEADS_UP_DISAPPEAR);
mChildrenToClearFromOverlay.add(changingView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 920b682..bbe5dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -171,6 +171,10 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
+ public void onCameraLaunchGestureDetected(int source) {
+ }
+
+ @Override
protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt,
boolean alertAgain) {
}