summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java')
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java698
1 files changed, 515 insertions, 183 deletions
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 aaa7019..e4e02a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -18,37 +18,41 @@ package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
+import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.RemoteException;
+import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.MathUtils;
+import android.view.Display;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -62,6 +66,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
import com.android.systemui.qs.QSContainer;
import com.android.systemui.qs.QSDragPanel;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -73,22 +78,22 @@ import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.LiveLockScreenController;
+import com.android.systemui.statusbar.policy.WeatherController;
+import com.android.systemui.statusbar.policy.WeatherControllerImpl;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
-import cyanogenmod.externalviews.KeyguardExternalView;
import cyanogenmod.providers.CMSettings;
+import cyanogenmod.weather.util.WeatherUtils;
import java.util.List;
-import java.util.Objects;
-
-import org.cyanogenmod.internal.util.CmLockPatternUtils;
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
- HeadsUpManager.OnHeadsUpChangedListener {
+ HeadsUpManager.OnHeadsUpChangedListener, WeatherController.Callback {
private static final boolean DEBUG = false;
@@ -106,13 +111,19 @@ public class NotificationPanelView extends PanelView implements
private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
- public static final long DOZE_ANIMATION_DURATION = 700;
+ private static final long SLIDE_PANEL_IN_ANIMATION_DURATION = 300;
+ private static final String KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD =
+ "user_expanded_notifications_in_keyguard";
+ private static final String KEY_USER_INTERACTED_WITH_LLS =
+ "user_interacted_with_lls";
+ private static final String KEY_USER_UNLOCKED =
+ "user_unlocked";
+ private static final String KEY_USER_RETURNED_FROM_LLS =
+ "user_returned_from_lls";
+
+ public static final long DOZE_ANIMATION_DURATION = 700;
- // Layout params for external keyguard view
- private static final FrameLayout.LayoutParams EXTERNAL_KEYGUARD_VIEW_PARAMS =
- new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
@@ -229,11 +240,6 @@ public class NotificationPanelView extends PanelView implements
private boolean mLaunchingAffordance;
private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
- private ComponentName mThirdPartyKeyguardViewComponent;
- private KeyguardExternalView mKeyguardExternalView;
- private CmLockPatternUtils mLockPatternUtils;
- private boolean mLiveLockScreenEnabled;
-
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@Override
public void run() {
@@ -254,6 +260,107 @@ public class NotificationPanelView extends PanelView implements
private int mStatusBarHeaderHeight;
private GestureDetector mDoubleTapGesture;
+ // Used to identify whether showUnlock() can dismiss the keyguard
+ // or not.
+ // TODO - add a new state to make it easier to identify keyguard vs
+ // LiveLockscreen
+ public boolean mCanDismissKeyguard;
+
+ // Used to track which direction the user is currently
+ // interacting with and ensure they don't alternate back
+ // and forth. Reset every MOTION_UP/MOTION_CANCEL
+ private SwipeLockedDirection mLockedDirection;
+
+ private SwipeHelper mSwipeHelper;
+ private final int mMinimumFlingVelocity;
+ private final int mScreenHeight;
+ private LiveLockScreenController mLiveLockscreenController;
+ private final GestureDetector mGestureDetector;
+ private ViewLinker mViewLinker;
+ private final UnlockMethodCache mUnlockMethodCache;
+ private boolean mDetailScrollLock;
+
+ private boolean mKeyguardWeatherEnabled;
+ private TextView mKeyguardWeatherInfo;
+ private WeatherControllerImpl mWeatherController;
+
+ // Keep track of common user interactions on the lock screen
+ private boolean mUserUnlocked;
+ private boolean mUserExpandedNotifications;
+ private boolean mUserInteractedWithLiveLockScreen;
+ private boolean mUserReturnedFromLiveLockScreen;
+
+ private boolean mScreenOnHintsEnabled;
+
+ private enum SwipeLockedDirection {
+ UNKNOWN,
+ HORIZONTAL,
+ VERTICAL
+ }
+
+ // Handles swiping to the LiveLockscreen from keyguard
+ SwipeHelper.SimpleCallback mSwipeCallback = new SwipeHelper.SimpleCallback() {
+ @Override
+ public View getChildAtPosition(MotionEvent ev) {
+ return mViewLinker.getParent();
+ }
+
+ @Override
+ public View getChildContentView(View v) {
+ return mViewLinker.getParent();
+ }
+
+ @Override
+ public boolean canChildBeDismissed(View v) {
+ return true;
+ }
+
+ @Override
+ public void onChildDismissed(View v) {
+ mCanDismissKeyguard = false;
+ mStatusBar.focusKeyguardExternalView();
+ mLiveLockscreenController.onLiveLockScreenFocusChanged(true /* hasFocus */);
+ if (!mUserInteractedWithLiveLockScreen) {
+ mUserInteractedWithLiveLockScreen = true;
+ saveUserInteractedWithLls(true);
+ }
+ if (!mUserReturnedFromLiveLockScreen) {
+ startShowNotificationsHintAnimation();
+ }
+ resetAlphaTranslation();
+ // Enables the left edge gesture to allow user
+ // to return to keyguard
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .setLiveLockscreenEdgeDetector(true);
+ } catch (RemoteException e){
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
+ // Let live lockscreen know of swipe progress to allow
+ // them to translate content in.
+ mLiveLockscreenController.getLiveLockScreenView()
+ .onLockscreenSlideOffsetChanged(swipeProgress);
+
+ // Fade out scrim background
+ float alpha = ScrimController.SCRIM_BEHIND_ALPHA_KEYGUARD - (1f - swipeProgress);
+ alpha = Math.max(0, alpha);
+ mStatusBar.getScrimController().setScrimBehindColor(alpha);
+ return false;
+ }
+
+ private void resetAlphaTranslation() {
+ mNotificationStackScroller.setTranslationX(0);
+ mNotificationStackScroller.setAlpha(1f);
+
+ mKeyguardStatusView.setTranslationX(0);
+ mKeyguardStatusView.setAlpha(1f);
+ }
+ };
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(!DEBUG);
@@ -268,12 +375,78 @@ public class NotificationPanelView extends PanelView implements
return true;
}
});
+
+ Resources res = getContext().getResources();
+ final int gradientStart = res.getColor(R.color.live_lockscreen_gradient_start);
+ final int gradientEnd = res.getColor(R.color.live_lockscreen_gradient_end);
+ mGestureDetector = new GestureDetector(getContext(),
+ new GestureDetector.SimpleOnGestureListener() {
+ private float mDown;
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ // Ensure we only capture swipes in the up direction
+ if (velocityY > 0 || Math.abs(velocityY) <= mMinimumFlingVelocity) {
+ return false;
+ }
+ mCanDismissKeyguard = true;
+ mStatusBar.showBouncer();
+ return true;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ float delta = mDown - e2.getRawY();
+ delta = Math.max(0, delta);
+ float screenHeightHalf = (float) mScreenHeight / 2f;
+ int color = (Integer) ArgbEvaluator.getInstance()
+ .evaluate(delta / screenHeightHalf, gradientStart, gradientEnd);
+ mKeyguardBottomArea.setBackgroundColor(color);
+ return super.onScroll(e1, e2, distanceX, distanceY);
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ mDown = e.getRawY();
+ mKeyguardBottomArea.expand(true);
+ return true;
+ }
+ });
+
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X,
+ SwipeHelper.SWIPE_ZONE_LEFT, mSwipeCallback, mContext);
+ mSwipeHelper.setSwipeProgressFadeEnd(1.0f);
+ mMinimumFlingVelocity = ViewConfiguration.get(getContext())
+ .getScaledMinimumFlingVelocity();
+
+ WindowManager windowManager = (WindowManager) mContext
+ .getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ Point point = new Point();
+ display.getSize(point);
+ mScreenHeight = point.y;
+ mUnlockMethodCache = UnlockMethodCache.getInstance(context);
+
+ mScreenOnHintsEnabled = res.getBoolean(R.bool.config_showScreenOnLockScreenHints);
+ mUserUnlocked = getUserUnlocked();
+ mUserExpandedNotifications = getUserExpandedNotificationsInKeyguard();
+ mUserInteractedWithLiveLockScreen = getUserInteractedWithLls();
+ mUserReturnedFromLiveLockScreen = getUserReturnedFromLls();
}
public void setStatusBar(PhoneStatusBar bar) {
mStatusBar = bar;
}
+ public void setLiveController(LiveLockScreenController liveController) {
+ mLiveLockscreenController = liveController;
+ }
+
+ public void setWeatherController(WeatherControllerImpl weatherController) {
+ mWeatherController = weatherController;
+ mWeatherController.addCallback(this);
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -283,6 +456,7 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container);
mQsPanel = (QSDragPanel) findViewById(R.id.quick_settings_panel);
+ mQsPanel.setPanelView(this);
mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
mScrollView.setFocusable(false);
@@ -301,7 +475,64 @@ public class NotificationPanelView extends PanelView implements
android.R.interpolator.fast_out_linear_in);
mDozeAnimationInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.linear_out_slow_in);
- mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
+
+ mViewLinker = new ViewLinker<NotificationStackScrollLayout>(mNotificationStackScroller,
+ new ViewLinker.LinkInfo(mKeyguardStatusBar, ViewLinker.LINK_ALPHA),
+ new ViewLinker.LinkInfo(mKeyguardStatusView, ViewLinker.LINK_ALPHA
+ | ViewLinker.LINK_TRANSLATION));
+
+ mKeyguardBottomArea = (KeyguardBottomAreaView) View.inflate(getContext(),
+ R.layout.keyguard_bottom_area, null);
+ /** Keyguard bottom area lives in a separate window, and as such,
+ * we must redirect its touch events through the proper flow
+ */
+ mKeyguardBottomArea.setOnInterceptTouchListener(new KeyguardBottomAreaView.OnInterceptTouchEventListener() {
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent e) {
+ boolean intercept = false;
+ if (mLiveLockscreenController.getLiveLockScreenHasFocus()) {
+ // Handles swipe up to fade/dismiss when showing
+ // live lock screen
+ intercept = mAfforanceHelper.onInterceptTouchEvent(e);
+ if (!intercept) {
+ intercept = mGestureDetector.onTouchEvent(e);
+ }
+ } else {
+ intercept = NotificationPanelView.this.onInterceptTouchEvent(e);
+ }
+ return intercept;
+ }
+ });
+ mKeyguardBottomArea.setOnTouchListener(new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent e) {
+ int action = e.getAction();
+
+ boolean isCancelOrUp = action == MotionEvent.ACTION_UP ||
+ action == MotionEvent.ACTION_CANCEL;
+ if (isCancelOrUp) {
+ mKeyguardBottomArea.setBackground(null);
+ }
+
+ boolean intercept = false;
+ if (mLiveLockscreenController.getLiveLockScreenHasFocus()) {
+ intercept = mAfforanceHelper.onTouchEvent(e);
+ // If the touch did not originate on the affordance helper,
+ // we must collapse the panel here since we can't rely on
+ // the swipe callbacks from being invoked.
+ if (isCancelOrUp && !isAffordanceSwipeInProgress()) {
+ mKeyguardBottomArea.expand(false);
+ }
+ if (!intercept) {
+ intercept = mGestureDetector.onTouchEvent(e);
+ }
+ } else {
+ intercept = NotificationPanelView.this.onTouchEvent(e);
+ }
+ return intercept;
+ }
+ });
+
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
mLastOrientation = getResources().getConfiguration().orientation;
@@ -319,19 +550,17 @@ public class NotificationPanelView extends PanelView implements
}
});
- mLockPatternUtils = new CmLockPatternUtils(getContext());
- if (mLockPatternUtils.isThirdPartyKeyguardEnabled() && mLiveLockScreenEnabled) {
- mThirdPartyKeyguardViewComponent = mLockPatternUtils.getThirdPartyKeyguardComponent();
- }
+ mKeyguardWeatherInfo = (TextView) mKeyguardStatusView.findViewById(R.id.weather_info);
+ }
+
+ public boolean isAffordanceSwipeInProgress() {
+ return mAfforanceHelper.isSwipingInProgress();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mSettingsObserver.observe();
- mContext.registerReceiver(mExternalKeyguardViewChangedReceiver,
- new IntentFilter(CmLockPatternUtils.ACTION_THIRD_PARTY_KEYGUARD_COMPONENT_CHANGED));
-
mScrollView.setListener(this);
}
@@ -339,7 +568,7 @@ public class NotificationPanelView extends PanelView implements
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mSettingsObserver.unobserve();
- mContext.unregisterReceiver(mExternalKeyguardViewChangedReceiver);
+ mWeatherController.removeCallback(this);
}
@Override
@@ -619,6 +848,10 @@ public class NotificationPanelView extends PanelView implements
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
+ // Reset locked direction
+ mLockedDirection = SwipeLockedDirection.UNKNOWN;
+ mCanDismissKeyguard = true;
+
if (mBlockTouches) {
return false;
}
@@ -640,7 +873,15 @@ public class NotificationPanelView extends PanelView implements
if (!isFullyCollapsed() && onQsIntercept(event)) {
return true;
}
- return super.onInterceptTouchEvent(event);
+
+ if (isKeyguardInteractiveAndShowing() || mStatusBar.isKeyguardShowingMedia() ||
+ (mUnlockMethodCache.isTrustManaged() && mAfforanceHelper.isOnLockIcon(event))) {
+ return super.onInterceptTouchEvent(event);
+ }
+
+ // We want both, we really do
+ return mSwipeHelper.onInterceptTouchEvent(event)
+ & super.onInterceptTouchEvent(event);
}
private boolean onQsIntercept(MotionEvent event) {
@@ -795,6 +1036,12 @@ public class NotificationPanelView extends PanelView implements
if (mBlockTouches) {
return false;
}
+
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mKeyguardBottomArea.setBackground(null);
+ }
+
if (mDoubleTapToSleepEnabled
&& mStatusBarState == StatusBarState.KEYGUARD
&& event.getY() < mStatusBarHeaderHeight) {
@@ -808,7 +1055,8 @@ public class NotificationPanelView extends PanelView implements
}
if ((!mIsExpanding || mHintAnimationRunning)
&& !mQsExpanded
- && mStatusBar.getBarState() != StatusBarState.SHADE) {
+ && (mStatusBar.getBarState() != StatusBarState.SHADE
+ || mLiveLockscreenController.getLiveLockScreenHasFocus())) {
mAfforanceHelper.onTouchEvent(event);
}
if (mOnlyAffordanceInThisMotion) {
@@ -822,10 +1070,39 @@ public class NotificationPanelView extends PanelView implements
MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
updateVerticalPanelPosition(event.getX());
}
- super.onTouchEvent(event);
+
+ if (isKeyguardInteractiveAndShowing() || mStatusBar.isKeyguardShowingMedia() ||
+ (mUnlockMethodCache.isTrustManaged() && mAfforanceHelper.isOnLockIcon(event))) {
+ super.onTouchEvent(event);
+ return true;
+ }
+
+ if ((!mIsExpanding || mHintAnimationRunning)
+ && !mQsExpanded
+ && mLockedDirection != SwipeLockedDirection.VERTICAL
+ && mStatusBar.getBarState() != StatusBarState.SHADE) {
+ mSwipeHelper.onTouchEvent(event);
+ if (mSwipeHelper.isDragging()) {
+ mLockedDirection = SwipeLockedDirection.HORIZONTAL;
+ }
+ if (mLockedDirection == SwipeLockedDirection.HORIZONTAL) {
+ requestDisallowInterceptTouchEvent(true);
+ return true;
+ }
+ }
+
+ if (super.onTouchEvent(event)) {
+ mLockedDirection = SwipeLockedDirection.VERTICAL;
+ }
return true;
}
+ private boolean isKeyguardInteractiveAndShowing() {
+ return mLiveLockscreenController.getLiveLockScreenHasFocus() ||
+ mStatusBar.getBarState() != StatusBarState.KEYGUARD ||
+ !mLiveLockscreenController.isLiveLockScreenInteractive();
+ }
+
private boolean handleQsTouch(MotionEvent event) {
final int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
@@ -857,7 +1134,8 @@ public class NotificationPanelView extends PanelView implements
mTwoFingerQsExpandPossible = true;
}
if (mTwoFingerQsExpandPossible && isOpenQsEvent(event)
- && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
+ && event.getY(event.getActionIndex()) < mStatusBarMinHeight
+ && mExpandedHeight <= mQsPeekHeight) {
MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1);
mQsExpandImmediate = true;
requestPanelHeightUpdate();
@@ -915,7 +1193,7 @@ public class NotificationPanelView extends PanelView implements
private void handleQsDown(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN
- && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+ && shouldQuickSettingsIntercept(event.getX(), event.getRawY(), -1)) {
mQsTracking = true;
onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
@@ -997,8 +1275,13 @@ public class NotificationPanelView extends PanelView implements
mTrackingPointer = -1;
trackMovement(event);
float fraction = getQsExpansionFraction();
- if ((fraction != 0f || y >= mInitialTouchY)
- && (fraction != 1f || y <= mInitialTouchY)) {
+ final boolean fling = (fraction != 0f || y >= mInitialTouchY)
+ && (fraction != 1f || y <= mInitialTouchY);
+ final boolean flingExpand = Math.abs(getCurrentVelocity())
+ > mFlingAnimationUtils.getMinVelocityPxPerSecond();
+ final boolean detailFling = mDetailScrollLock && mQsExpanded
+ && flingExpand;
+ if ((fling && !mDetailScrollLock) || detailFling) {
flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
} else {
@@ -1099,9 +1382,17 @@ public class NotificationPanelView extends PanelView implements
mStatusBarState = statusBarState;
mKeyguardShowing = keyguardShowing;
+ if (oldState != statusBarState && statusBarState == StatusBarState.KEYGUARD) {
+ mCanDismissKeyguard = true;
+ }
- if (goingToFullShade || (oldState == StatusBarState.KEYGUARD
- && statusBarState == StatusBarState.SHADE_LOCKED)) {
+ boolean keyguardToShadeLocked = oldState == StatusBarState.KEYGUARD
+ && statusBarState == StatusBarState.SHADE_LOCKED;
+ if (goingToFullShade || keyguardToShadeLocked) {
+ if (keyguardToShadeLocked && !mUserExpandedNotifications) {
+ mUserExpandedNotifications = true;
+ saveUserExpandedNotificationsInKeyguard(true);
+ }
animateKeyguardStatusBarOut();
animateHeaderSlidingIn();
} else if (oldState == StatusBarState.SHADE_LOCKED
@@ -1116,26 +1407,14 @@ public class NotificationPanelView extends PanelView implements
mAfforanceHelper.updatePreviews();
}
}
+ if (oldState != StatusBarState.SHADE && statusBarState == StatusBarState.SHADE &&
+ !mUserUnlocked) {
+ mUserUnlocked = true;
+ saveUserUnlocked(true);
+ }
if (statusBarState == StatusBarState.KEYGUARD ||
statusBarState == StatusBarState.SHADE_LOCKED) {
updateDozingVisibilities(false /* animate */);
- if (mThirdPartyKeyguardViewComponent != null) {
- if (mKeyguardExternalView == null) {
- mKeyguardExternalView =
- getExternalKeyguardView(mThirdPartyKeyguardViewComponent);
- if (mKeyguardExternalView != null) {
- mKeyguardExternalView.registerKeyguardExternalViewCallback(
- mExternalKeyguardViewCallbacks);
- }
- }
- if (mKeyguardExternalView != null && !mKeyguardExternalView.isAttachedToWindow()) {
- addView(mKeyguardExternalView, 0, EXTERNAL_KEYGUARD_VIEW_PARAMS);
- }
- }
- } else {
- if (mKeyguardExternalView != null && mKeyguardExternalView.isAttachedToWindow()) {
- removeView(mKeyguardExternalView);
- }
}
resetVerticalPanelPosition();
updateQsState();
@@ -1213,82 +1492,6 @@ public class NotificationPanelView extends PanelView implements
}
};
- private KeyguardExternalView.KeyguardExternalViewCallbacks mExternalKeyguardViewCallbacks =
- new KeyguardExternalView.KeyguardExternalViewCallbacks() {
- @Override
- public boolean requestDismiss() {
- if (hasExternalKeyguardView()) {
- post(new Runnable() {
- @Override
- public void run() {
- mStatusBar.showKeyguard();
- mStatusBar.showBouncer();
- }
- });
- return true;
- }
- return false;
- }
-
- @Override
- public boolean requestDismissAndStartActivity(final Intent intent) {
- if (hasExternalKeyguardView()) {
- if (hasExternalKeyguardView()) {
- post(new Runnable() {
- @Override
- public void run() {
- mStatusBar.showKeyguard();
- mStatusBar.startActivityDismissingKeyguard(intent, false, true, true,
- null);
- }
- });
- }
- return true;
- }
- return false;
- }
-
- @Override
- public void collapseNotificationPanel() {
- if (mStatusBar.getBarState() == StatusBarState.KEYGUARD && hasExternalKeyguardView() &&
- mKeyguardExternalView.isInteractive()) {
- post(new Runnable() {
- @Override
- public void run() {
- mStatusBar.focusKeyguardExternalView();
- }
- });
- }
- }
-
- @Override
- public void providerDied() {
- mKeyguardExternalView.unregisterKeyguardExternalViewCallback(
- mExternalKeyguardViewCallbacks);
- mKeyguardExternalView = null;
- }
- };
-
- private BroadcastReceiver mExternalKeyguardViewChangedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String pkgName = getSendingPackage(intent);
- if (pkgName != null) {
- PackageManager pm = context.getPackageManager();
- if (pm.checkPermission(android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
- pkgName) != PackageManager.PERMISSION_GRANTED) {
- // we should not be here if the sending app does not have the proper permission,
- // so do nothing and return.
- return;
- }
- } else {
- // null package name? something is not right so just return and skip doing anything
- return;
- }
- updateExternalKeyguardView();
- }
- };
-
private void animateHeaderSlidingIn() {
// If the QS is already expanded we don't need to slide in the header as it's already
// visible.
@@ -1487,8 +1690,7 @@ public class NotificationPanelView extends PanelView implements
if (mKeyguardShowing) {
updateHeaderKeyguard();
}
- if (mStatusBarState == StatusBarState.SHADE_LOCKED
- || mStatusBarState == StatusBarState.KEYGUARD) {
+ if (mStatusBarState == StatusBarState.KEYGUARD) {
updateKeyguardBottomAreaAlpha();
}
if (mStatusBarState == StatusBarState.SHADE && mQsExpanded
@@ -1669,7 +1871,8 @@ public class NotificationPanelView extends PanelView implements
&& y >= header.getTop() && y <= header.getBottom();
if (mQsExpanded) {
- return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y);
+ return onHeader || mDetailScrollLock
+ || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y);
} else {
return onHeader;
}
@@ -1759,7 +1962,7 @@ public class NotificationPanelView extends PanelView implements
*/
private int getTempQsMaxExpansion() {
int qsTempMaxExpansion = mQsMaxExpansionHeight;
- if (mScrollYOverride != -1) {
+ if (mScrollYOverride != -1 && !mDetailScrollLock) {
qsTempMaxExpansion -= mScrollYOverride;
}
return qsTempMaxExpansion;
@@ -1926,12 +2129,14 @@ public class NotificationPanelView extends PanelView implements
}
private void updateHeaderKeyguardAlpha() {
+ if (mSwipeHelper.isDragging()) {
+ return;
+ }
float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
* mKeyguardStatusBarAnimateAlpha);
mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f
&& !mDozing ? VISIBLE : INVISIBLE);
- mStatusBar.getVisualizer().setAlpha(mKeyguardStatusBar.getAlpha());
}
private void updateHeaderKeyguard() {
@@ -1941,6 +2146,9 @@ public class NotificationPanelView extends PanelView implements
private void updateKeyguardBottomAreaAlpha() {
float alpha = Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction());
+ if (mLiveLockscreenController.getLiveLockScreenHasFocus()) {
+ alpha = 1f;
+ }
mKeyguardBottomArea.setAlpha(alpha);
mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f
? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
@@ -2164,10 +2372,12 @@ public class NotificationPanelView extends PanelView implements
mLaunchAnimationEndRunnable.run();
mLaunchAnimationEndRunnable = null;
}
+ mKeyguardBottomArea.setVisibility(View.GONE);
}
@Override
protected void startUnlockHintAnimation() {
+ mKeyguardBottomArea.expand(true);
super.startUnlockHintAnimation();
startHighlightIconAnimation(getCenterIcon());
}
@@ -2202,11 +2412,13 @@ public class NotificationPanelView extends PanelView implements
requestDisallowInterceptTouchEvent(true);
mOnlyAffordanceInThisMotion = true;
mQsTracking = false;
+ mKeyguardBottomArea.expand(true);
}
@Override
public void onSwipingAborted() {
mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
+ mKeyguardBottomArea.expand(false);
}
@Override
@@ -2215,6 +2427,8 @@ public class NotificationPanelView extends PanelView implements
return;
}
mHintAnimationRunning = true;
+ mKeyguardBottomArea.expand(true);
+ mKeyguardBottomArea.getIndicationView().animate().cancel();
mAfforanceHelper.startHintAnimation(rightIcon, new Runnable() {
@Override
public void run() {
@@ -2395,11 +2609,6 @@ public class NotificationPanelView extends PanelView implements
// Hide "No notifications" in QS.
mNotificationStackScroller.updateEmptyShadeView(mShadeEmpty && !mQsExpanded);
- if (mStatusBarState == StatusBarState.KEYGUARD
- && (!mQsExpanded || mQsExpandImmediate || mIsExpanding
- && mQsExpandedWhenExpandingStarted)) {
- positionClockAndNotifications();
- }
}
public void setQsScrimEnabled(boolean qsScrimEnabled) {
@@ -2423,6 +2632,11 @@ public class NotificationPanelView extends PanelView implements
public void onScreenTurningOn() {
mKeyguardStatusView.refreshTime();
+ if (shouldShowScreenOnHints()) {
+ startScreenOnHintAnimation(mLiveLockscreenController.isLiveLockScreenInteractive() &&
+ !mUserInteractedWithLiveLockScreen,
+ !mUserUnlocked, !mUserExpandedNotifications);
+ }
}
@Override
@@ -2584,6 +2798,10 @@ public class NotificationPanelView extends PanelView implements
return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
}
+ public KeyguardBottomAreaView getKeyguardBottomArea() {
+ return mKeyguardBottomArea;
+ }
+
class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
super(handler);
@@ -2596,7 +2814,7 @@ public class NotificationPanelView extends PanelView implements
resolver.registerContentObserver(CMSettings.System.getUriFor(
CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE), false, this);
resolver.registerContentObserver(CMSettings.Secure.getUriFor(
- CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED), false, this);
+ CMSettings.Secure.LOCK_SCREEN_WEATHER_ENABLED), false, this);
update();
}
@@ -2622,11 +2840,12 @@ public class NotificationPanelView extends PanelView implements
mDoubleTapToSleepEnabled = CMSettings.System.getInt(
resolver, CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE, 1) == 1;
- boolean liveLockScreenEnabled = CMSettings.Secure.getInt(
- resolver, CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED, 0) == 1;
- if (liveLockScreenEnabled != mLiveLockScreenEnabled) {
- mLiveLockScreenEnabled = liveLockScreenEnabled;
- updateExternalKeyguardView();
+ boolean wasKeyguardWeatherEnabled = mKeyguardWeatherEnabled;
+ mKeyguardWeatherEnabled = CMSettings.Secure.getInt(
+ resolver, CMSettings.Secure.LOCK_SCREEN_WEATHER_ENABLED, 0) == 1;
+ if (mWeatherController != null
+ && wasKeyguardWeatherEnabled != mKeyguardWeatherEnabled) {
+ onWeatherChanged(mWeatherController.getWeatherInfo());
}
}
}
@@ -2641,6 +2860,8 @@ public class NotificationPanelView extends PanelView implements
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
} else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
+ } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE;
} else {
// Default.
@@ -2650,7 +2871,8 @@ public class NotificationPanelView extends PanelView implements
// 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()) {
+ if (!isFullyCollapsed() && mLastCameraLaunchSource ==
+ KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE) {
mLaunchingAffordance = true;
setLaunchingAffordance(true);
} else {
@@ -2699,48 +2921,158 @@ public class NotificationPanelView extends PanelView implements
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
}
- public boolean hasExternalKeyguardView() {
- return mKeyguardExternalView != null && mKeyguardExternalView.isAttachedToWindow();
+ public void setDetailRequestedScrollLock(boolean detailScrollFlag) {
+ if (mDetailScrollLock != detailScrollFlag) {
+ if (mStatusBarState != StatusBarState.SHADE) {
+ mDetailScrollLock = false;
+ } else {
+ mDetailScrollLock = detailScrollFlag;
+ }
+ if (!detailScrollFlag && getQsExpansionFraction() > 0.3f) {
+ flingSettings(getCurrentVelocity(), true, new Runnable() {
+ @Override
+ public void run() {
+ mStackScrollerOverscrolling = false;
+ mQsExpansionFromOverscroll = false;
+ updateQsState();
+ updateHeader();
+ updateMaxHeadsUpTranslation();
+ updatePanelExpanded();
+ requestLayout();
+ }
+ }, false);
+ } else {
+ requestLayout();
+ }
+ }
}
- public boolean isExternalKeyguardViewInteractive() {
- return mKeyguardExternalView != null && mKeyguardExternalView.isInteractive();
+ @Override
+ public void onWeatherChanged(WeatherController.WeatherInfo info) {
+ if (!mKeyguardWeatherEnabled || Double.isNaN(info.temp) || info.condition == null) {
+ mKeyguardWeatherInfo.setVisibility(GONE);
+ } else {
+ mKeyguardWeatherInfo.setText(mContext.getString(
+ R.string.keyguard_status_view_weather_format,
+ WeatherUtils.formatTemperature(info.temp, info.tempUnit),
+ info.condition));
+ mKeyguardWeatherInfo.setVisibility(VISIBLE);
+ }
}
- public KeyguardExternalView getExternalKeyguardView() {
- return mKeyguardExternalView;
- }
+ private class SlideInAnimationListener implements ValueAnimator.AnimatorUpdateListener,
+ ValueAnimator.AnimatorListener {
+ @Override
+ public void onAnimationStart(Animator animator) {}
- private KeyguardExternalView getExternalKeyguardView(ComponentName componentName) {
- try {
- return new KeyguardExternalView(getContext(), null, componentName);
- } catch (Exception e) {
- // just return null below and move on
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ animationFinished(animator);
}
- return null;
- }
- private void updateExternalKeyguardView() {
- ComponentName cn = mLiveLockScreenEnabled ?
- mLockPatternUtils.getThirdPartyKeyguardComponent() : null;
- // If mThirdPartyKeyguardViewComponent differs from cn, go ahead and update
- if (!Objects.equals(mThirdPartyKeyguardViewComponent, cn)) {
- mThirdPartyKeyguardViewComponent = cn;
- if (mKeyguardExternalView != null) {
- if (indexOfChild(mKeyguardExternalView) >= 0) {
- removeView(mKeyguardExternalView);
- }
- mKeyguardExternalView.unregisterKeyguardExternalViewCallback(
- mExternalKeyguardViewCallbacks);
- if (mThirdPartyKeyguardViewComponent != null) {
- mKeyguardExternalView =
- getExternalKeyguardView(mThirdPartyKeyguardViewComponent);
- mKeyguardExternalView.registerKeyguardExternalViewCallback(
- mExternalKeyguardViewCallbacks);
- } else {
- mKeyguardExternalView = null;
- }
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ animationFinished(animator);
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {}
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ View statusBarView = mStatusBar.getStatusBarWindow();
+ if (valueAnimator.getAnimatedFraction() > 0 &&
+ statusBarView.getVisibility() != View.VISIBLE) {
+ statusBarView.setVisibility(View.VISIBLE);
}
+ float translationX = (Float) valueAnimator.getAnimatedValue();
+ float alpha = valueAnimator.getAnimatedFraction();
+
+ mViewLinker.getParent().setTranslationX(translationX);
+ mViewLinker.getParent().setAlpha(alpha);
+
+ float alpha1 = ScrimController.SCRIM_BEHIND_ALPHA_KEYGUARD * alpha;
+ alpha1 = Math.max(0, alpha1);
+ mStatusBar.getScrimController().setScrimBehindColor(alpha1);
+ mLiveLockscreenController.getLiveLockScreenView()
+ .onLockscreenSlideOffsetChanged(alpha);
}
+
+ private void animationFinished(Animator animator) {
+ mLiveLockscreenController.onLiveLockScreenFocusChanged(false);
+ }
+ }
+
+ private SlideInAnimationListener mSlideInAnimationListener = new SlideInAnimationListener();
+
+ public void slideLockScreenIn() {
+ mNotificationStackScroller.setVisibility(View.VISIBLE);
+ mNotificationStackScroller.setAlpha(0f);
+ mNotificationStackScroller.setTranslationX(-mNotificationStackScroller.getWidth());
+ mKeyguardStatusView.setVisibility(View.VISIBLE);
+ mKeyguardStatusView.setAlpha(0f);
+ mKeyguardStatusView.setTranslationX(mNotificationStackScroller.getTranslationX());
+ mKeyguardStatusBar.setAlpha(0f);
+
+ mStatusBar.getScrimController().setScrimBehindColor(0f);
+ ValueAnimator animator = ValueAnimator.ofFloat(
+ mNotificationStackScroller.getTranslationX(),
+ 0f);
+ animator.setDuration(SLIDE_PANEL_IN_ANIMATION_DURATION);
+ animator.addUpdateListener(mSlideInAnimationListener);
+ animator.addListener(mSlideInAnimationListener);
+ animator.start();
+
+ if (!mUserReturnedFromLiveLockScreen) {
+ mUserReturnedFromLiveLockScreen = true;
+ saveUserReturnedFromLls(true);
+ }
+ }
+
+ private void saveBooleanSharedPreference(String key, boolean value) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ prefs.edit().putBoolean(key, value).apply();
+ }
+
+ private boolean getSharedPreferenceBoolean(String key, boolean defValue) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ return prefs.getBoolean(key, defValue);
+ }
+
+ private void saveUserExpandedNotificationsInKeyguard(boolean expanded) {
+ saveBooleanSharedPreference(KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD, expanded);
+ }
+
+ private boolean getUserExpandedNotificationsInKeyguard() {
+ return getSharedPreferenceBoolean(KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD, false);
+ }
+
+ private void saveUserInteractedWithLls(boolean interacted) {
+ saveBooleanSharedPreference(KEY_USER_INTERACTED_WITH_LLS, interacted);
+ }
+
+ private boolean getUserInteractedWithLls() {
+ return getSharedPreferenceBoolean(KEY_USER_INTERACTED_WITH_LLS, false);
+ }
+
+ private void saveUserUnlocked(boolean unlocked) {
+ saveBooleanSharedPreference(KEY_USER_UNLOCKED, unlocked);
+ }
+
+ private boolean getUserUnlocked() {
+ return getSharedPreferenceBoolean(KEY_USER_UNLOCKED, false);
+ }
+
+ private void saveUserReturnedFromLls(boolean revealed) {
+ saveBooleanSharedPreference(KEY_USER_RETURNED_FROM_LLS, revealed);
+ }
+
+ private boolean getUserReturnedFromLls() {
+ return getSharedPreferenceBoolean(KEY_USER_RETURNED_FROM_LLS, false);
+ }
+
+ public boolean shouldShowScreenOnHints() {
+ return mScreenOnHintsEnabled && mStatusBar.isDeviceProvisioned() &&
+ mStatusBarState == StatusBarState.KEYGUARD;
}
}