Make notification reply can response to work challenge

When user clicks work notification reply button while work user has
challenge, it will bring you to work challenge, and click on the reply
button when work challenge is unlock.

Bug: 28036566
Change-Id: I7b8520c4e58c0c0f965e4770ab0c7b926d8fb39a
This commit is contained in:
Ricky Wai
2016-05-03 11:07:07 +01:00
parent ecd73f48fe
commit cd35def3c3
5 changed files with 172 additions and 49 deletions

View File

@@ -457,9 +457,17 @@ public abstract class BaseStatusBar extends SystemUI implements
row.setUserExpanded(true);
if (isLockscreenPublicMode() && !mAllowLockscreenRemoteInput) {
onLockedRemoteInput(row, view);
return true;
if (!mAllowLockscreenRemoteInput) {
if (isLockscreenPublicMode()) {
onLockedRemoteInput(row, view);
return true;
}
final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
if (mUserManager.getUserInfo(userId).isManagedProfile()
&& mKeyguardManager.isDeviceLocked(userId)) {
onLockedWorkRemoteInput(userId, row, view);
return true;
}
}
riv.setVisibility(View.VISIBLE);
@@ -540,16 +548,21 @@ public abstract class BaseStatusBar extends SystemUI implements
} else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) {
final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
try {
mContext.startIntentSender(intentSender, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
/* ignore */
if (intentSender != null) {
try {
mContext.startIntentSender(intentSender, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
/* ignore */
}
}
try {
mBarService.onNotificationClick(notificationKey);
} catch (RemoteException e) {
/* ignore */
if (notificationKey != null) {
try {
mBarService.onNotificationClick(notificationKey);
} catch (RemoteException e) {
/* ignore */
}
}
onWorkChallengeUnlocked();
}
}
};
@@ -1389,6 +1402,8 @@ public abstract class BaseStatusBar extends SystemUI implements
return mLockscreenPublicMode;
}
protected void onWorkChallengeUnlocked() {}
/**
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
* "public" (secure & locked) mode?
@@ -1498,6 +1513,9 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
View clicked) {}
@Override
public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
}
@@ -1925,39 +1943,6 @@ public abstract class BaseStatusBar extends SystemUI implements
}, afterKeyguardGone);
}
public boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
null, userId);
if (newIntent == null) {
return false;
}
final Intent callBackIntent = new Intent(
WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
callBackIntent.setPackage(mContext.getPackageName());
PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
mContext,
0,
callBackIntent,
PendingIntent.FLAG_CANCEL_CURRENT |
PendingIntent.FLAG_ONE_SHOT |
PendingIntent.FLAG_IMMUTABLE
);
newIntent.putExtra(
Intent.EXTRA_INTENT,
callBackPendingIntent.getIntentSender()
);
try {
ActivityManagerNative.getDefault().startConfirmDeviceCredentialIntent(newIntent);
} catch (RemoteException ex) {
// ignore
}
return true;
}
public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification.contentIntent != null || notification.fullScreenIntent != null) {
@@ -1984,6 +1969,37 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
null, userId);
if (newIntent == null) {
return false;
}
final Intent callBackIntent = new Intent(
WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
callBackIntent.setPackage(mContext.getPackageName());
PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
mContext,
0,
callBackIntent,
PendingIntent.FLAG_CANCEL_CURRENT |
PendingIntent.FLAG_ONE_SHOT |
PendingIntent.FLAG_IMMUTABLE);
newIntent.putExtra(
Intent.EXTRA_INTENT,
callBackPendingIntent.getIntentSender());
try {
ActivityManagerNative.getDefault().startConfirmDeviceCredentialIntent(newIntent);
} catch (RemoteException ex) {
// ignore
}
return true;
}
protected Bundle getActivityOptions() {
// Anything launched from the notification shade should always go into the
// fullscreen stack.

View File

@@ -1239,6 +1239,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|| !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
}
public void makeActionsVisibile() {
setUserExpanded(true, true);
if (isChildInGroup()) {
mGroupManager.setGroupExpanded(mStatusBarNotification, true);
}
notifyHeightChanged(false);
}
public void setChildrenExpanded(boolean expanded, boolean animate) {
mChildrenExpanded = expanded;
if (mNotificationHeader != null) {

View File

@@ -32,6 +32,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -89,6 +90,7 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.animation.AccelerateInterpolator;
@@ -348,6 +350,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// RemoteInputView to be activated after unlock
private View mPendingRemoteInputView;
private View mPendingWorkRemoteInputView;
int mMaxAllowedKeyguardNotifications;
@@ -4292,6 +4295,92 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mPendingRemoteInputView = clicked;
}
@Override
protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
// Clear pending remote view, as we do not want to trigger pending remote input view when
// it's called by other code
mPendingWorkRemoteInputView = null;
return super.startWorkChallengeIfNecessary(userId, intendSender, notificationKey);
}
@Override
protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
View clicked) {
// Collapse notification and show work challenge
animateCollapsePanels();
startWorkChallengeIfNecessary(userId, null, null);
// Add pending remote input view after starting work challenge, as starting work challenge
// will clear all previous pending review view
mPendingWorkRemoteInputView = clicked;
}
@Override
protected void onWorkChallengeUnlocked() {
if (mPendingWorkRemoteInputView != null) {
final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView;
// Expand notification panel and the notification row, then click on remote input view
final Runnable clickPendingViewRunnable = new Runnable() {
@Override
public void run() {
if (mPendingWorkRemoteInputView != null) {
final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView;
ViewParent p = pendingWorkRemoteInputView.getParent();
while (p != null) {
if (p instanceof ExpandableNotificationRow) {
final ExpandableNotificationRow row = (ExpandableNotificationRow) p;
ViewParent viewParent = row.getParent();
if (viewParent instanceof NotificationStackScrollLayout) {
final NotificationStackScrollLayout scrollLayout =
(NotificationStackScrollLayout) viewParent;
row.makeActionsVisibile();
row.post(new Runnable() {
@Override
public void run() {
final Runnable finishScrollingCallback = new Runnable()
{
@Override
public void run() {
mPendingWorkRemoteInputView.callOnClick();
mPendingWorkRemoteInputView = null;
scrollLayout.setFinishScrollingCallback(null);
}
};
if (scrollLayout.scrollTo(row)) {
// It scrolls! So call it when it's finished.
scrollLayout.setFinishScrollingCallback(
finishScrollingCallback);
} else {
// It does not scroll, so call it now!
finishScrollingCallback.run();
}
}
});
}
break;
}
p = p.getParent();
}
}
}
};
mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (mNotificationPanel.mStatusBar.getStatusBarWindow()
.getHeight() != mNotificationPanel.mStatusBar
.getStatusBarHeight()) {
mNotificationPanel.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
mNotificationPanel.post(clickPendingViewRunnable);
}
}
});
instantExpandNotificationsPanel();
}
}
@Override
public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);

View File

@@ -94,7 +94,6 @@ public class NotificationStackScrollLayout extends ViewGroup
private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
/**
* Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
*/
@@ -116,6 +115,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private VelocityTracker mVelocityTracker;
private OverScroller mScroller;
private Runnable mFinishScrollingCallback;
private int mTouchSlop;
private int mMinimumVelocity;
private int mMaximumVelocity;
@@ -922,17 +922,19 @@ public class NotificationStackScrollLayout extends ViewGroup
mScrollingEnabled = enable;
}
public void scrollTo(View v) {
public boolean scrollTo(View v) {
ExpandableView expandableView = (ExpandableView) v;
int positionInLinearLayout = getPositionInLinearLayout(v);
int targetScroll = positionInLinearLayout + expandableView.getActualHeight() +
int targetScroll = positionInLinearLayout + expandableView.getIntrinsicHeight() +
getImeInset() - getHeight() + getTopPadding();
if (mOwnScrollY < targetScroll) {
mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
mDontReportNextOverScroll = true;
postInvalidateOnAnimation();
return true;
}
return false;
}
@Override
@@ -1291,6 +1293,10 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
public void setFinishScrollingCallback(Runnable runnable) {
mFinishScrollingCallback = runnable;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
@@ -1321,6 +1327,9 @@ public class NotificationStackScrollLayout extends ViewGroup
postInvalidateOnAnimation();
} else {
mDontClampNextScroll = false;
if (mFinishScrollingCallback != null) {
mFinishScrollingCallback.run();
}
}
}

View File

@@ -31,8 +31,9 @@ public interface ScrollContainer {
/**
* Request that the view is made visible by scrolling to it.
* Return true if it scrolls.
*/
void scrollTo(View v);
boolean scrollTo(View v);
/**
* Request that the view does not dismiss for the current touch.