diff options
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.java | 698 |
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; } } |