diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index 268544716900b..d2bf30c172565 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -112,7 +112,9 @@ public class KeyguardHostView extends KeyguardViewBase { } public interface OnDismissAction { - /* returns true if the dismiss should be deferred */ + /** + * @return true if the dismiss should be deferred + */ boolean onDismiss(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 9435e8594436b..f4db6253a7baa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -84,6 +84,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; +import static com.android.keyguard.KeyguardHostView.OnDismissAction; + public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener { public static final String TAG = "StatusBar"; @@ -213,33 +215,47 @@ public abstract class BaseStatusBar extends SystemUI implements private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { @Override - public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { + public boolean onClickHandler( + final View view, final PendingIntent pendingIntent, final Intent fillInIntent) { if (DEBUG) { Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); } final boolean isActivity = pendingIntent.isActivity(); if (isActivity) { - try { - // The intent we are sending is for the application, which - // won't have permission to immediately start an activity after - // the user switches to home. We know it is safe to do at this - // point, so make sure new activity switches are now allowed. - ActivityManagerNative.getDefault().resumeAppSwitches(); - // Also, notifications can be launched from the lock screen, - // so dismiss the lock screen when the activity starts. - ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); - } catch (RemoteException e) { - } - } + startNotificationActivity(new OnDismissAction() { + @Override + public boolean onDismiss() { + try { + // The intent we are sending is for the application, which + // won't have permission to immediately start an activity after + // the user switches to home. We know it is safe to do at this + // point, so make sure new activity switches are now allowed. + ActivityManagerNative.getDefault().resumeAppSwitches(); + // Also, notifications can be launched from the lock screen, + // so dismiss the lock screen when the activity starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { + } - boolean handled = super.onClickHandler(view, pendingIntent, fillInIntent); + boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent); - if (isActivity && handled) { - // close the shade if it was open - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - visibilityChanged(false); + // close the shade if it was open + if (handled) { + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); + visibilityChanged(false); + } + return handled; // Wait for activity start. + } + }); + return true; + } else { + return super.onClickHandler(view, pendingIntent, fillInIntent); } - return handled; + } + + private boolean superOnClickHandler(View view, PendingIntent pendingIntent, + Intent fillInIntent) { + return super.onClickHandler(view, pendingIntent, fillInIntent); } }; @@ -434,6 +450,14 @@ public abstract class BaseStatusBar extends SystemUI implements } } + /** + * Takes the necessary steps to prepare the status bar for starting an activity, then starts it. + * @param action A dismiss action that is called if it's safe to start the activity. + */ + protected void startNotificationActivity(OnDismissAction action) { + action.onDismiss(); + } + @Override protected void onConfigurationChanged(Configuration newConfig) { final Locale locale = mContext.getResources().getConfiguration().locale; @@ -999,47 +1023,55 @@ public abstract class BaseStatusBar extends SystemUI implements mIsHeadsUp = forHun; } - public void onClick(View v) { - try { - // The intent we are sending is for the application, which - // won't have permission to immediately start an activity after - // the user switches to home. We know it is safe to do at this - // point, so make sure new activity switches are now allowed. - ActivityManagerNative.getDefault().resumeAppSwitches(); - // Also, notifications can be launched from the lock screen, - // so dismiss the lock screen when the activity starts. - ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); - } catch (RemoteException e) { - } + public void onClick(final View v) { + startNotificationActivity(new OnDismissAction() { + public boolean onDismiss() { + try { + // The intent we are sending is for the application, which + // won't have permission to immediately start an activity after + // the user switches to home. We know it is safe to do at this + // point, so make sure new activity switches are now allowed. + ActivityManagerNative.getDefault().resumeAppSwitches(); + // Also, notifications can be launched from the lock screen, + // so dismiss the lock screen when the activity starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { + } - if (mIntent != null) { - int[] pos = new int[2]; - v.getLocationOnScreen(pos); - Intent overlay = new Intent(); - overlay.setSourceBounds( - new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight())); - try { - mIntent.send(mContext, 0, overlay); - } catch (PendingIntent.CanceledException e) { - // the stack trace isn't very helpful here. Just log the exception message. - Log.w(TAG, "Sending contentIntent failed: " + e); + boolean sent = false; + if (mIntent != null) { + int[] pos = new int[2]; + v.getLocationOnScreen(pos); + Intent overlay = new Intent(); + overlay.setSourceBounds(new Rect(pos[0], pos[1], + pos[0]+v.getWidth(), pos[1]+v.getHeight())); + try { + mIntent.send(mContext, 0, overlay); + sent = true; + } catch (PendingIntent.CanceledException e) { + // the stack trace isn't very helpful here. + // Just log the exception message. + Log.w(TAG, "Sending contentIntent failed: " + e); + } + } + + try { + if (mIsHeadsUp) { + mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP); + } + mBarService.onNotificationClick(mNotificationKey); + } catch (RemoteException ex) { + // system process is dead if we're here. + } + + // close the shade if it was open + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); + visibilityChanged(false); + + boolean waitForActivityLaunch = sent && mIntent.isActivity(); + return waitForActivityLaunch; } - - KeyguardTouchDelegate.getInstance(mContext).dismiss(); - } - - try { - if (mIsHeadsUp) { - mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP); - } - mBarService.onNotificationClick(mNotificationKey); - } catch (RemoteException ex) { - // system process is dead if we're here. - } - - // close the shade if it was open - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - visibilityChanged(false); + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index d8e176697f557..9138867680853 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -28,6 +28,7 @@ import com.android.keyguard.R; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.keyguard.KeyguardViewMediator; +import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.keyguard.KeyguardSecurityModel.*; /** @@ -69,6 +70,12 @@ public class KeyguardBouncer { } } + public void showWithDismissAction(OnDismissAction r) { + ensureView(); + mKeyguardView.setOnDismissAction(r); + show(); + } + public void hide() { if (mKeyguardView != null) { mKeyguardView.cleanUp(); 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 152ca3f8ad413..0922abd77db90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -22,6 +22,7 @@ import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; +import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; @@ -2346,6 +2347,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }; + @Override + protected void startNotificationActivity(OnDismissAction action) { + if (mStatusBarKeyguardViewManager.isShowing()) { + mStatusBarKeyguardViewManager.dismissWithAction(action); + } else { + action.onDismiss(); + } + } + // SystemUIService notifies SystemBars of configuration changes, which then calls down here @Override protected void onConfigurationChanged(Configuration newConfig) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 1040c158f53e4..3849d8d7221cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -29,6 +29,8 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; +import static com.android.keyguard.KeyguardHostView.OnDismissAction; + /** * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done, @@ -108,6 +110,13 @@ public class StatusBarKeyguardViewManager { updateStates(); } + public void dismissWithAction(OnDismissAction r) { + if (!mOccluded) { + mBouncer.showWithDismissAction(r); + } + updateStates(); + } + /** * Reset the state of the view. */