diff options
Diffstat (limited to 'packages/SystemUI/src/com')
13 files changed, 443 insertions, 49 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 0f32dc0..5a55292 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -88,14 +88,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView if (mDownY > getActualHeight()) { return false; } - - // Call the listener tentatively directly, even if we don't know whether the user - // will stay within the touch slop, as the listener is implemented as a scale - // animation, which is cancellable without jarring effects when swiping away - // notifications. - if (mOnActivatedListener != null) { - mOnActivatedListener.onActivated(this); - } break; case MotionEvent.ACTION_MOVE: if (!isWithinTouchSlop(event)) { @@ -109,8 +101,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView makeActive(event.getX(), event.getY()); postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS); } else { - performClick(); makeInactive(); + performClick(); } } else { makeInactive(); @@ -128,6 +120,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void makeActive(float x, float y) { mCustomBackground.setHotspot(0, x, y); mActivated = true; + if (mOnActivatedListener != null) { + mOnActivatedListener.onActivated(this); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 9149e2d..829cee4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -167,7 +167,11 @@ public abstract class BaseStatusBar extends SystemUI implements protected int mZenMode; - protected boolean mOnKeyguard; + /** + * The {@link StatusBarState} of the status bar. + */ + protected int mState; + protected NotificationOverflowContainer mKeyguardIconOverflowContainer; public boolean isDeviceProvisioned() { @@ -1057,9 +1061,10 @@ public abstract class BaseStatusBar extends SystemUI implements mKeyguardIconOverflowContainer.getIconsView().removeAllViews(); int n = mNotificationData.size(); int visibleNotifications = 0; + boolean onKeyguard = mState == StatusBarState.KEYGUARD; for (int i = n-1; i >= 0; i--) { NotificationData.Entry entry = mNotificationData.get(i); - if (mOnKeyguard) { + if (onKeyguard) { entry.row.setExpansionDisabled(true); } else { entry.row.setExpansionDisabled(false); @@ -1068,10 +1073,10 @@ public abstract class BaseStatusBar extends SystemUI implements entry.row.setSystemExpanded(top); } } - entry.row.setDimmed(mOnKeyguard); - entry.row.setLocked(mOnKeyguard); + entry.row.setDimmed(onKeyguard); + entry.row.setLocked(onKeyguard); boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification); - if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications + if (onKeyguard && (visibleNotifications >= maxKeyguardNotifications || !showOnKeyguard)) { entry.row.setVisibility(View.GONE); if (showOnKeyguard) { @@ -1087,7 +1092,7 @@ public abstract class BaseStatusBar extends SystemUI implements } } - if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) { + if (onKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) { mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE); } else { mKeyguardIconOverflowContainer.setVisibility(View.GONE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java new file mode 100644 index 0000000..af4c8b8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java @@ -0,0 +1,158 @@ +/* + * 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; + +import android.content.Context; +import android.util.ArraySet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +import com.android.systemui.ExpandHelper; +import com.android.systemui.Gefingerpoken; +import com.android.systemui.R; + +import java.util.HashSet; + +/** + * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand + * the notification where the drag started. + */ +public class DragDownHelper implements Gefingerpoken { + + private int mMinDragDistance; + private ExpandHelper.Callback mCallback; + private float mInitialTouchX; + private float mInitialTouchY; + private boolean mDraggingDown; + private float mTouchSlop; + private OnDragDownListener mOnDragDownListener; + private View mHost; + private final int[] mTemp2 = new int[2]; + private final ArraySet<View> mHoveredChildren = new ArraySet<View>(); + private boolean mDraggedFarEnough; + private View mStartingChild; + + public DragDownHelper(Context context, View host, ExpandHelper.Callback callback, + OnDragDownListener onDragDownListener) { + mMinDragDistance = context.getResources().getDimensionPixelSize( + R.dimen.keyguard_drag_down_min_distance); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mCallback = callback; + mOnDragDownListener = onDragDownListener; + mHost = host; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + final float x = event.getX(); + final float y = event.getY(); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mHoveredChildren.clear(); + mDraggedFarEnough = false; + mDraggingDown = false; + mStartingChild = null; + mInitialTouchY = y; + mInitialTouchX = x; + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) { + mDraggingDown = true; + mInitialTouchY = y; + mInitialTouchX = x; + return true; + } + break; + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!mDraggingDown) { + return false; + } + final float x = event.getX(); + final float y = event.getY(); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + View child = findView(x, y); + if (child != null) { + hoverChild(findView(x, y)); + } + if (h > mMinDragDistance) { + if (!mDraggedFarEnough) { + mDraggedFarEnough = true; + mOnDragDownListener.onThresholdReached(); + } + } else { + if (mDraggedFarEnough) { + mDraggedFarEnough = false; + mOnDragDownListener.onReset(); + } + } + return true; + case MotionEvent.ACTION_UP: + if (mDraggedFarEnough) { + mOnDragDownListener.onDraggedDown(mStartingChild); + } else { + stopDragging(); + return false; + } + break; + case MotionEvent.ACTION_CANCEL: + stopDragging(); + return false; + } + return false; + } + + private void stopDragging() { + mDraggingDown = false; + mOnDragDownListener.onReset(); + } + + private void hoverChild(View child) { + if (mHoveredChildren.isEmpty()) { + mStartingChild = child; + } + if (!mHoveredChildren.contains(child)) { + mOnDragDownListener.onHover(child); + mHoveredChildren.add(child); + } + } + + private View findView(float x, float y) { + mHost.getLocationOnScreen(mTemp2); + x += mTemp2[0]; + y += mTemp2[1]; + return mCallback.getChildAtRawPosition(x, y); + } + + public interface OnDragDownListener { + void onHover(View child); + void onDraggedDown(View startingChild); + void onReset(); + void onThresholdReached(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 61aad6f..5b70cd3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -23,7 +23,8 @@ import android.view.accessibility.AccessibilityEvent; import com.android.systemui.R; -public class ExpandableNotificationRow extends ActivatableNotificationView { +public class ExpandableNotificationRow extends ActivatableNotificationView implements + NotificationActivatable { private int mRowMinHeight; private int mRowMaxHeight; @@ -64,7 +65,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic); mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded); - mActivator = new NotificationActivator(this); + mActivator = new NotificationActivator(this, this); } @Override @@ -113,6 +114,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void setUserExpanded(boolean userExpanded) { mHasUserChangedExpansion = true; mUserExpanded = userExpanded; + applyExpansionToLayout(); } public boolean isUserLocked() { @@ -225,6 +227,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return mMaxExpandHeight; } + @Override public NotificationActivator getActivator() { return mActivator; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivatable.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivatable.java new file mode 100644 index 0000000..410a3aa --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivatable.java @@ -0,0 +1,25 @@ +/* + * 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; + +/** + * An interface which defines a view to be activatable in the meaning of + * {@link NotificationActivator}. + */ +public interface NotificationActivatable { + NotificationActivator getActivator(); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java index 620e457..097857c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java @@ -34,14 +34,40 @@ public class NotificationActivator { private static final float INVERSE_ALPHA = 0.9f; private static final float DIMMED_SCALE = 0.95f; - private final View mTargetView; + /** + * Normal state. Notification is fully interactable. + */ + private static final int STATE_NORMAL = 0; + + /** + * Dimmed state. Neutral state when on the lockscreen, with slight transparency and scaled down + * a bit. + */ + private static final int STATE_DIMMED = 1; + + /** + * Activated state. Used after tapping a notification on the lockscreen. Normal transparency and + * normal scale. + */ + private static final int STATE_ACTIVATED = 2; + /** + * Inverse activated state. Used for the other notifications on the lockscreen when tapping on + * one. + */ + private static final int STATE_ACTIVATED_INVERSE = 3; + + private final View mTargetView; + private final View mHotspotView; private final Interpolator mFastOutSlowInInterpolator; private final Interpolator mLinearOutSlowInInterpolator; private final int mTranslationZ; - public NotificationActivator(View targetView) { + private int mState; + + public NotificationActivator(View targetView, View hotspotView) { mTargetView = targetView; + mHotspotView = hotspotView; Context ctx = targetView.getContext(); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in); @@ -53,18 +79,37 @@ public class NotificationActivator { } public void activateInverse() { + if (mState == STATE_ACTIVATED_INVERSE) { + return; + } + mTargetView.animate().cancel(); mTargetView.animate().withLayer().alpha(INVERSE_ALPHA); + mState = STATE_ACTIVATED_INVERSE; + } + + public void addHotspot() { + mHotspotView.getBackground().setHotspot( + 0, mHotspotView.getWidth()/2, mHotspotView.getHeight()/2); } public void activate() { + if (mState == STATE_ACTIVATED) { + return; + } + mTargetView.animate().cancel(); mTargetView.animate() .setInterpolator(mLinearOutSlowInInterpolator) .scaleX(1) .scaleY(1) .translationZBy(mTranslationZ); + mState = STATE_ACTIVATED; } public void reset() { + if (mState == STATE_DIMMED) { + return; + } + mTargetView.animate().cancel(); mTargetView.animate() .setInterpolator(mFastOutSlowInInterpolator) .scaleX(DIMMED_SCALE) @@ -73,15 +118,21 @@ public class NotificationActivator { if (mTargetView.getAlpha() != 1.0f) { mTargetView.animate().withLayer().alpha(1); } + mHotspotView.getBackground().removeHotspot(0); + mState = STATE_DIMMED; } public void setDimmed(boolean dimmed) { if (dimmed) { + mTargetView.animate().cancel(); mTargetView.setScaleX(DIMMED_SCALE); mTargetView.setScaleY(DIMMED_SCALE); + mState = STATE_DIMMED; } else { + mTargetView.animate().cancel(); mTargetView.setScaleX(1); mTargetView.setScaleY(1); + mState = STATE_NORMAL; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java index 8ebd50d..6f9cbf8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java @@ -25,7 +25,8 @@ import com.android.systemui.R; /** * Container view for overflowing notification icons on Keyguard. */ -public class NotificationOverflowContainer extends ActivatableNotificationView { +public class NotificationOverflowContainer extends ActivatableNotificationView implements + NotificationActivatable { private NotificationOverflowIconsView mIconsView; private NotificationActivator mActivator; @@ -60,7 +61,7 @@ public class NotificationOverflowContainer extends ActivatableNotificationView { mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view); mIconsView.setMoreText((TextView) findViewById(R.id.more_text)); - mActivator = new NotificationActivator(this); + mActivator = new NotificationActivator(this, this); mActivator.setDimmed(true); setLocked(true); setDimmed(true); @@ -70,6 +71,7 @@ public class NotificationOverflowContainer extends ActivatableNotificationView { return mIconsView; } + @Override public NotificationActivator getActivator() { return mActivator; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java new file mode 100644 index 0000000..9d75228 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java @@ -0,0 +1,40 @@ +/* + * 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; + +/** + * Class to encapsulate all possible status bar states regarding Keyguard. + */ +public class StatusBarState { + + /** + * The status bar is in the "normal" shade mode. + */ + public static final int SHADE = 0; + + /** + * Status bar is currently the Keyguard. + */ + public static final int KEYGUARD = 1; + + /** + * Status bar is in the special mode, where it is fully interactive but still locked. So + * dismissing the shade will still show the bouncer. + */ + public static final int SHADE_LOCKED = 2; + +} 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 712eec8..ec7d80a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -25,6 +25,7 @@ import android.view.accessibility.AccessibilityEvent; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.GestureRecorder; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; public class NotificationPanelView extends PanelView implements @@ -76,7 +77,7 @@ public class NotificationPanelView extends PanelView implements super.onLayout(changed, left, top, right, bottom); int keyguardBottomMargin = ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin; - mNotificationStackScroller.setTopPadding(mStatusBar.isOnKeyguard() + mNotificationStackScroller.setTopPadding(mStatusBar.getBarState() == StatusBarState.KEYGUARD ? mKeyguardStatusView.getBottom() + keyguardBottomMargin : mHeader.getBottom() + mNotificationTopPadding); } @@ -107,14 +108,18 @@ public class NotificationPanelView extends PanelView implements public boolean onInterceptTouchEvent(MotionEvent event) { // intercept for quick settings if (event.getAction() == MotionEvent.ACTION_DOWN) { - final View target = mStatusBar.isOnKeyguard() ? mKeyguardStatusView : mHeader; + final View target = mStatusBar.getBarState() == StatusBarState.KEYGUARD + ? mKeyguardStatusView + : mHeader; final boolean inTarget = PhoneStatusBar.inBounds(target, event, true); if (inTarget && !isInSettings()) { mTrackingSettings = true; + requestDisallowInterceptTouchEvent(true); return true; } if (!inTarget && isInSettings()) { mTrackingSettings = true; + requestDisallowInterceptTouchEvent(true); return true; } } 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 0c3462c..7d8f3ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -96,13 +96,17 @@ import com.android.systemui.R; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.DragDownHelper; +import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.InterceptedNotifications; +import com.android.systemui.statusbar.NotificationActivatable; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.NotificationOverflowContainer; import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.StatusBarIconView; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.DateView; @@ -120,7 +124,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -public class PhoneStatusBar extends BaseStatusBar implements DemoMode { +public class PhoneStatusBar extends BaseStatusBar implements DemoMode, + DragDownHelper.OnDragDownListener { static final String TAG = "PhoneStatusBar"; public static final boolean DEBUG = BaseStatusBar.DEBUG; public static final boolean SPEW = false; @@ -233,6 +238,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { View mNotificationPanelHeader; View mKeyguardStatusView; View mKeyguardBottomArea; + boolean mLeaveOpenOnKeyguardHide; KeyguardIndicationTextView mKeyguardIndicationTextView; // TODO: Fetch phrase from search/hotword provider. @@ -470,6 +476,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } }; + private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + goToLockedShade(null); + } + }; + @Override public void setZenMode(int mode) { super.setZenMode(mode); @@ -619,6 +632,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false); mKeyguardIconOverflowContainer.setOnActivatedListener(this); mKeyguardCarrierLabel = mStatusBarWindow.findViewById(R.id.keyguard_carrier_text); + mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener); mStackScroller.addView(mKeyguardIconOverflowContainer); mExpandedContents = mStackScroller; @@ -784,7 +798,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL)) { final float dy = event.getY() - mSettingsDownY; - final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper; + final FlipperButton flipper = mState == StatusBarState.KEYGUARD + ? mKeyguardFlipper + : mHeaderFlipper; final boolean inButton = flipper.inHolderBounds(event); final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop; if (!qsTap && !inButton) { @@ -1192,7 +1208,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 - && !mNotificationPanel.isTracking() && !mOnKeyguard) { + && !mNotificationPanel.isTracking() && mState != StatusBarState.KEYGUARD) { animateCollapsePanels(); } } @@ -1346,7 +1362,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { && mStackScroller.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight) && mStackScroller.getVisibility() == View.VISIBLE - && !mOnKeyguard; + && mState != StatusBarState.KEYGUARD; if (force || mCarrierLabelVisible != makeVisible) { mCarrierLabelVisible = makeVisible; @@ -2097,7 +2113,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mDemoMode) return; int sbMode = mStatusBarMode; if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0 - && !mOnKeyguard) { + && mState != StatusBarState.KEYGUARD) { // if panels are expandable, force the status bar opaque on any interaction sbMode = MODE_OPAQUE; } @@ -2957,28 +2973,37 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } } - public boolean isOnKeyguard() { - return mOnKeyguard; + /** + * @return The {@link StatusBarState} the status bar is in. + */ + public int getBarState() { + return mState; } public void showKeyguard() { - mOnKeyguard = true; + setBarState(StatusBarState.KEYGUARD); updateKeyguardState(); instantExpandNotificationsPanel(); + mLeaveOpenOnKeyguardHide = false; } public void hideKeyguard() { - mOnKeyguard = false; + setBarState(StatusBarState.SHADE); + if (mLeaveOpenOnKeyguardHide) { + mLeaveOpenOnKeyguardHide = false; + } else { + instantCollapseNotificationPanel(); + } updateKeyguardState(); - instantCollapseNotificationPanel(); } private void updatePublicMode() { - setLockscreenPublicMode(mOnKeyguard && mStatusBarKeyguardViewManager.isSecure()); + setLockscreenPublicMode(mState == StatusBarState.KEYGUARD + && mStatusBarKeyguardViewManager.isSecure()); } private void updateKeyguardState() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD) { if (isFlippedToSettings()) { flipToNotifications(false /*animate*/); } @@ -3010,17 +3035,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } public void userActivity() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD) { mKeyguardViewMediatorCallback.userActivity(); } } public boolean onMenuPressed() { - return mOnKeyguard && mStatusBarKeyguardViewManager.onMenuPressed(); + return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed(); } public boolean onBackPressed() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { return mStatusBarKeyguardViewManager.onBackPressed(); } else { animateCollapsePanels(); @@ -3029,7 +3054,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } private void showBouncer() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { mStatusBarKeyguardViewManager.dismiss(); } } @@ -3065,6 +3090,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { super.onActivated(view); } + /** + * @param state The {@link StatusBarState} to set. + */ + public void setBarState(int state) { + mState = state; + mStatusBarWindowManager.setStatusBarState(state); + } + @Override public void onReset(View view) { super.onReset(view); @@ -3072,13 +3105,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } public void onTrackingStarted() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD) { mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock); } } public void onTrackingStopped() { - if (mOnKeyguard) { + if (mState == StatusBarState.KEYGUARD) { mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase); } } @@ -3092,6 +3125,56 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { return mNavigationBarView; } + // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ + + @Override + public void onDraggedDown(View startingChild) { + goToLockedShade(startingChild); + } + + @Override + public void onReset() { + onReset(null); + } + + public void onHover(View child) { + if (child instanceof NotificationActivatable) { + NotificationActivatable activatable = (NotificationActivatable) child; + activatable.getActivator().activate(); + activatable.getActivator().addHotspot(); + } + } + + public void onThresholdReached() { + // TODO: Add visual hint that threshold is reached. + } + + /** + * If secure with redaction: Show bouncer, go to unlocked shade. + * + * <p>If secure without redaction: Go to {@link StatusBarState#SHADE_LOCKED}.</p> + * + * <p>Otherwise go directly to unlocked shade.</p> + * + * @param expandView The view to expand after going to the shade. + */ + public void goToLockedShade(View expandView) { + if (expandView instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) expandView; + row.setUserExpanded(true); + } + if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) { + mLeaveOpenOnKeyguardHide = true; + showBouncer(); + } else if (mStatusBarKeyguardViewManager.isSecure()) { + setBarState(StatusBarState.SHADE_LOCKED); + updateKeyguardState(); + } else { + mLeaveOpenOnKeyguardHide = true; + mStatusBarKeyguardViewManager.dismiss(); + } + } + /** * @return a ViewGroup that spans the entire panel which contains the quick settings */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 79c63f7..c9c2867 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -29,6 +29,7 @@ import android.view.accessibility.AccessibilityEvent; import com.android.systemui.EventLogTags; import com.android.systemui.R; +import com.android.systemui.statusbar.StatusBarState; public class PhoneStatusBarView extends PanelBar { private static final String TAG = "PhoneStatusBarView"; @@ -187,7 +188,9 @@ public class PhoneStatusBarView extends PanelBar { if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx() && mBar.mStatusBarWindow != null) { if (mShouldFade) { - int scrimColor = mBar.isOnKeyguard() ? mScrimColorKeyguard : mScrimColor; + int scrimColor = mBar.getBarState() == StatusBarState.KEYGUARD + ? mScrimColorKeyguard + : mScrimColor; frac = mPanelExpandedFractionSum; // don't judge me // let's start this 20% of the way down the screen frac = frac * 1.2f - 0.2f; 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 d175d7a..a04baea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.phone; -import android.app.ActionBar; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; @@ -28,6 +27,8 @@ import android.view.ViewGroup; import android.view.WindowManager; import com.android.keyguard.R; +import com.android.systemui.statusbar.BaseStatusBar; +import com.android.systemui.statusbar.StatusBarState; /** * Encapsulates all logic for the status bar window state management. @@ -137,7 +138,8 @@ public class StatusBarWindowManager { } private void applyUserActivityTimeout(State state) { - if (state.isKeyguardShowingAndNotOccluded()) { + if (state.isKeyguardShowingAndNotOccluded() + && state.statusBarState == StatusBarState.KEYGUARD) { mLp.userActivityTimeout = state.keyguardUserActivityTimeout; } else { mLp.userActivityTimeout = -1; @@ -194,6 +196,14 @@ public class StatusBarWindowManager { apply(mCurrentState); } + /** + * @param state The {@link StatusBarState} of the status bar. + */ + public void setStatusBarState(int state) { + mCurrentState.statusBarState = state; + apply(mCurrentState); + } + private static class State { boolean keyguardShowing; boolean keyguardOccluded; @@ -202,6 +212,11 @@ public class StatusBarWindowManager { boolean statusBarFocusable; long keyguardUserActivityTimeout; + /** + * The {@link BaseStatusBar} state from the status bar. + */ + int statusBarState; + private boolean isKeyguardShowingAndNotOccluded() { return keyguardShowing && !keyguardOccluded; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 6b5ef5a..3e5ba16 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -31,16 +31,17 @@ import android.widget.FrameLayout; import com.android.systemui.ExpandHelper; import com.android.systemui.R; import com.android.systemui.statusbar.BaseStatusBar; -import com.android.systemui.statusbar.policy.ScrollAdapter; +import com.android.systemui.statusbar.DragDownHelper; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; -public class StatusBarWindowView extends FrameLayout -{ +public class StatusBarWindowView extends FrameLayout { public static final String TAG = "StatusBarWindowView"; public static final boolean DEBUG = BaseStatusBar.DEBUG; private ExpandHelper mExpandHelper; + private DragDownHelper mDragDownHelper; private NotificationStackScrollLayout mStackScrollLayout; private NotificationPanelView mNotificationPanel; @@ -75,6 +76,7 @@ public class StatusBarWindowView extends FrameLayout minHeight, maxHeight); mExpandHelper.setEventSource(this); mExpandHelper.setScrollAdapter(mStackScrollLayout); + mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService); // We really need to be able to animate while window animations are going on // so that activities may be started asynchronously from panel animations @@ -106,8 +108,12 @@ public class StatusBarWindowView extends FrameLayout boolean intercept = false; if (mNotificationPanel.isFullyExpanded() && mStackScrollLayout.getVisibility() == View.VISIBLE - && !mService.isOnKeyguard()) { + && mService.getBarState() != StatusBarState.KEYGUARD) { intercept = mExpandHelper.onInterceptTouchEvent(ev); + } else if (mNotificationPanel.isFullyExpanded() + && mStackScrollLayout.getVisibility() == View.VISIBLE + && mService.getBarState() == StatusBarState.KEYGUARD) { + intercept = mDragDownHelper.onInterceptTouchEvent(ev); } if (!intercept) { super.onInterceptTouchEvent(ev); @@ -124,8 +130,11 @@ public class StatusBarWindowView extends FrameLayout @Override public boolean onTouchEvent(MotionEvent ev) { boolean handled = false; - if (mNotificationPanel.isFullyExpanded()) { + if (mNotificationPanel.isFullyExpanded() + && mService.getBarState() != StatusBarState.KEYGUARD) { handled = mExpandHelper.onTouchEvent(ev); + } else if (mService.getBarState() == StatusBarState.KEYGUARD) { + handled = mDragDownHelper.onTouchEvent(ev); } if (!handled) { handled = super.onTouchEvent(ev); |