DO NOT MERGE Only send notification activity intents after dismissing Keyguard
Defers delivery of contentIntent and activity actions until the lockscreen has been dismissed, so that activities don't launch beneath it. Bug: 14491010 Change-Id: Ic8c61c18a75d4f0da2d82a0a8a038a5d98ebb71f (cherry picked from commit 79f640dd0d02c1cc199937b160d8f7abd3c1eaeb)
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user