Merge "CallStyle notifications now include their adjusted actions in the actions list." into sc-dev
This commit is contained in:
@@ -5445,8 +5445,12 @@ public class Notification implements Parcelable
|
||||
return p.allowColorization && mN.isColorized();
|
||||
}
|
||||
|
||||
private boolean isCallActionColorCustomizable(StandardTemplateParams p) {
|
||||
return isColorized(p) && mContext.getResources().getBoolean(
|
||||
private boolean isCallActionColorCustomizable() {
|
||||
// NOTE: this doesn't need to check StandardTemplateParams.allowColorization because
|
||||
// that is only used for disallowing colorization of headers for the minimized state,
|
||||
// and neither of those conditions applies when showing actions.
|
||||
// Not requiring StandardTemplateParams as an argument simplifies the creation process.
|
||||
return mN.isColorized() && mContext.getResources().getBoolean(
|
||||
R.bool.config_callNotificationActionColorsRequireColorized);
|
||||
}
|
||||
|
||||
@@ -5512,13 +5516,13 @@ public class Notification implements Parcelable
|
||||
*/
|
||||
private @NonNull List<Notification.Action> getNonContextualActions() {
|
||||
if (mActions == null) return Collections.emptyList();
|
||||
List<Notification.Action> contextualActions = new ArrayList<>();
|
||||
List<Notification.Action> standardActions = new ArrayList<>();
|
||||
for (Notification.Action action : mActions) {
|
||||
if (!action.isContextual()) {
|
||||
contextualActions.add(action);
|
||||
standardActions.add(action);
|
||||
}
|
||||
}
|
||||
return contextualActions;
|
||||
return standardActions;
|
||||
}
|
||||
|
||||
private RemoteViews applyStandardTemplateWithActions(int layoutId,
|
||||
@@ -5538,16 +5542,29 @@ public class Notification implements Parcelable
|
||||
// filter them out here.
|
||||
List<Notification.Action> nonContextualActions = getNonContextualActions();
|
||||
|
||||
int N = nonContextualActions.size();
|
||||
boolean emphazisedMode = mN.fullScreenIntent != null;
|
||||
int numActions = Math.min(nonContextualActions.size(), MAX_ACTION_BUTTONS);
|
||||
boolean emphazisedMode = mN.fullScreenIntent != null || p.mCallStyleActions;
|
||||
if (p.mCallStyleActions) {
|
||||
// Clear view padding to allow buttons to start on the left edge.
|
||||
// This must be done before 'setEmphasizedMode' which sets top/bottom margins.
|
||||
big.setViewPadding(R.id.actions, 0, 0, 0, 0);
|
||||
// Add an optional indent that will make buttons start at the correct column when
|
||||
// there is enough space to do so (and fall back to the left edge if not).
|
||||
big.setInt(R.id.actions, "setCollapsibleIndentDimen",
|
||||
R.dimen.call_notification_collapsible_indent);
|
||||
}
|
||||
big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode);
|
||||
if (N > 0 && !p.mHideActions) {
|
||||
if (p.mCallStyleActions) {
|
||||
// Use "wrap_content" (unlike normal emphasized mode) and allow prioritizing the
|
||||
// required actions (Answer, Decline, and Hang Up).
|
||||
big.setBoolean(R.id.actions, "setPrioritizedWrapMode", true);
|
||||
}
|
||||
if (numActions > 0 && !p.mHideActions) {
|
||||
big.setViewVisibility(R.id.actions_container, View.VISIBLE);
|
||||
big.setViewVisibility(R.id.actions, View.VISIBLE);
|
||||
big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
|
||||
RemoteViews.MARGIN_BOTTOM, 0);
|
||||
if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
|
||||
for (int i=0; i<N; i++) {
|
||||
for (int i = 0; i < numActions; i++) {
|
||||
Action action = nonContextualActions.get(i);
|
||||
|
||||
boolean actionHasValidInput = hasValidRemoteInput(action);
|
||||
@@ -5558,6 +5575,11 @@ public class Notification implements Parcelable
|
||||
// Clear the drawable
|
||||
button.setInt(R.id.action0, "setBackgroundResource", 0);
|
||||
}
|
||||
if (p.mCallStyleActions && i > 0) {
|
||||
// Clear start margin from non-first buttons to reduce the gap between them.
|
||||
// (8dp remaining gap is from all buttons' standard 4dp inset).
|
||||
button.setViewLayoutMarginDimen(R.id.action0, RemoteViews.MARGIN_START, 0);
|
||||
}
|
||||
big.addView(R.id.actions, button);
|
||||
}
|
||||
} else {
|
||||
@@ -6019,7 +6041,7 @@ public class Notification implements Parcelable
|
||||
button.setColorStateList(R.id.action0, "setButtonBackground",
|
||||
ColorStateList.valueOf(background));
|
||||
button.setBoolean(R.id.action0, "setHasStroke", !hasColorOverride);
|
||||
if (p.mAllowActionIcons) {
|
||||
if (p.mCallStyleActions) {
|
||||
button.setImageViewIcon(R.id.action0, action.getIcon());
|
||||
boolean priority = action.getExtras().getBoolean(CallStyle.KEY_ACTION_PRIORITY);
|
||||
button.setBoolean(R.id.action0, "setWrapModePriority", priority);
|
||||
@@ -9265,6 +9287,17 @@ public class Notification implements Parcelable
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public Notification buildStyled(Notification wip) {
|
||||
wip = super.buildStyled(wip);
|
||||
// ensure that the actions in the builder and notification are corrected.
|
||||
mBuilder.mActions = getActionsListWithSystemActions();
|
||||
wip.actions = new Action[mBuilder.mActions.size()];
|
||||
mBuilder.mActions.toArray(wip.actions);
|
||||
return wip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -9324,14 +9357,14 @@ public class Notification implements Parcelable
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Action makeNegativeAction(@NonNull StandardTemplateParams p) {
|
||||
private Action makeNegativeAction() {
|
||||
if (mDeclineIntent == null) {
|
||||
return makeAction(p, R.drawable.ic_call_decline,
|
||||
return makeAction(R.drawable.ic_call_decline,
|
||||
R.string.call_notification_hang_up_action,
|
||||
mDeclineButtonColor, R.color.call_notification_decline_color,
|
||||
mHangUpIntent);
|
||||
} else {
|
||||
return makeAction(p, R.drawable.ic_call_decline,
|
||||
return makeAction(R.drawable.ic_call_decline,
|
||||
R.string.call_notification_decline_action,
|
||||
mDeclineButtonColor, R.color.call_notification_decline_color,
|
||||
mDeclineIntent);
|
||||
@@ -9339,18 +9372,17 @@ public class Notification implements Parcelable
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Action makeAnswerAction(@NonNull StandardTemplateParams p) {
|
||||
return mAnswerIntent == null ? null : makeAction(p, R.drawable.ic_call_answer,
|
||||
private Action makeAnswerAction() {
|
||||
return mAnswerIntent == null ? null : makeAction(R.drawable.ic_call_answer,
|
||||
R.string.call_notification_answer_action,
|
||||
mAnswerButtonColor, R.color.call_notification_answer_color,
|
||||
mAnswerIntent);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Action makeAction(@NonNull StandardTemplateParams p,
|
||||
@DrawableRes int icon, @StringRes int title,
|
||||
private Action makeAction(@DrawableRes int icon, @StringRes int title,
|
||||
@ColorInt Integer colorInt, @ColorRes int defaultColorRes, PendingIntent intent) {
|
||||
if (colorInt == null || !mBuilder.isCallActionColorCustomizable(p)) {
|
||||
if (colorInt == null || !mBuilder.isCallActionColorCustomizable()) {
|
||||
colorInt = mBuilder.mContext.getColor(defaultColorRes);
|
||||
}
|
||||
Action action = new Action.Builder(Icon.createWithResource("", icon),
|
||||
@@ -9362,29 +9394,62 @@ public class Notification implements Parcelable
|
||||
return action;
|
||||
}
|
||||
|
||||
private ArrayList<Action> makeActionsList(@NonNull StandardTemplateParams p) {
|
||||
final Action negativeAction = makeNegativeAction(p);
|
||||
final Action answerAction = makeAnswerAction(p);
|
||||
private boolean isActionAddedByCallStyle(Action action) {
|
||||
// This is an internal extra added by the style to these actions. If an app were to add
|
||||
// this extra to the action themselves, the action would be dropped. :shrug:
|
||||
return action != null && action.getExtras().getBoolean(KEY_ACTION_PRIORITY);
|
||||
}
|
||||
|
||||
ArrayList<Action> actions = new ArrayList<>(MAX_ACTION_BUTTONS);
|
||||
final Action lastAction;
|
||||
if (answerAction == null) {
|
||||
// If there's no answer action, put the hang up / decline action at the end
|
||||
lastAction = negativeAction;
|
||||
} else {
|
||||
// Otherwise put the answer action at the end, and put the decline action at start.
|
||||
actions.add(negativeAction);
|
||||
lastAction = answerAction;
|
||||
/**
|
||||
* Gets the actions list for the call with the answer/decline/hangUp actions inserted in
|
||||
* the correct place. This returns the correct result even if the system actions have
|
||||
* already been added, and even if more actions were added since then.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public ArrayList<Action> getActionsListWithSystemActions() {
|
||||
// Define the system actions we expect to see
|
||||
final Action negativeAction = makeNegativeAction();
|
||||
final Action answerAction = makeAnswerAction();
|
||||
// Sort the expected actions into the correct order:
|
||||
// * If there's no answer action, put the hang up / decline action at the end
|
||||
// * Otherwise put the answer action at the end, and put the decline action at start.
|
||||
final Action firstAction = answerAction == null ? null : negativeAction;
|
||||
final Action lastAction = answerAction == null ? negativeAction : answerAction;
|
||||
|
||||
// Start creating the result list.
|
||||
int nonContextualActionSlotsRemaining = MAX_ACTION_BUTTONS;
|
||||
ArrayList<Action> resultActions = new ArrayList<>(MAX_ACTION_BUTTONS);
|
||||
if (firstAction != null) {
|
||||
resultActions.add(firstAction);
|
||||
--nonContextualActionSlotsRemaining;
|
||||
}
|
||||
// For consistency with the standard actions bar, contextual actions are ignored.
|
||||
for (Action action : mBuilder.getNonContextualActions()) {
|
||||
if (actions.size() >= MAX_ACTION_BUTTONS - 1) {
|
||||
break;
|
||||
|
||||
// Copy actions into the new list, correcting system actions.
|
||||
if (mBuilder.mActions != null) {
|
||||
for (Notification.Action action : mBuilder.mActions) {
|
||||
if (action.isContextual()) {
|
||||
// Always include all contextual actions
|
||||
resultActions.add(action);
|
||||
} else if (isActionAddedByCallStyle(action)) {
|
||||
// Drop any old versions of system actions
|
||||
} else {
|
||||
// Copy non-contextual actions; decrement the remaining action slots.
|
||||
resultActions.add(action);
|
||||
--nonContextualActionSlotsRemaining;
|
||||
}
|
||||
// If there's exactly one action slot left, fill it with the lastAction.
|
||||
if (nonContextualActionSlotsRemaining == 1) {
|
||||
resultActions.add(lastAction);
|
||||
--nonContextualActionSlotsRemaining;
|
||||
}
|
||||
}
|
||||
actions.add(action);
|
||||
}
|
||||
actions.add(lastAction);
|
||||
return actions;
|
||||
// If there are any action slots left, the lastAction still needs to be added.
|
||||
if (nonContextualActionSlotsRemaining >= 1) {
|
||||
resultActions.add(lastAction);
|
||||
}
|
||||
return resultActions;
|
||||
}
|
||||
|
||||
private RemoteViews makeCallLayout() {
|
||||
@@ -9397,19 +9462,15 @@ public class Notification implements Parcelable
|
||||
// Bind standard template
|
||||
StandardTemplateParams p = mBuilder.mParams.reset()
|
||||
.viewType(StandardTemplateParams.VIEW_TYPE_BIG)
|
||||
.allowActionIcons(true)
|
||||
.callStyleActions(true)
|
||||
.allowTextWithProgress(true)
|
||||
.hideLargeIcon(true)
|
||||
.text(text)
|
||||
.summaryText(mBuilder.processLegacyText(mVerificationText));
|
||||
RemoteViews contentView = mBuilder.applyStandardTemplate(
|
||||
mBuilder.mActions = getActionsListWithSystemActions();
|
||||
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
|
||||
mBuilder.getCallLayoutResource(), p, null /* result */);
|
||||
|
||||
// Bind actions.
|
||||
mBuilder.resetStandardTemplateWithActions(contentView);
|
||||
mBuilder.bindSnoozeAction(contentView, p);
|
||||
bindCallActions(contentView, p);
|
||||
|
||||
// Bind some extra conversation-specific header fields.
|
||||
mBuilder.setTextViewColorPrimary(contentView, R.id.conversation_text, p);
|
||||
mBuilder.setTextViewColorSecondary(contentView, R.id.app_name_divider, p);
|
||||
@@ -9429,41 +9490,6 @@ public class Notification implements Parcelable
|
||||
return contentView;
|
||||
}
|
||||
|
||||
private void bindCallActions(RemoteViews view, StandardTemplateParams p) {
|
||||
view.setViewVisibility(R.id.actions_container, View.VISIBLE);
|
||||
view.setViewVisibility(R.id.actions, View.VISIBLE);
|
||||
view.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
|
||||
RemoteViews.MARGIN_BOTTOM, 0);
|
||||
|
||||
// Clear view padding to allow buttons to start on the left edge.
|
||||
// This must be done before 'setEmphasizedMode' which sets top/bottom margins.
|
||||
view.setViewPadding(R.id.actions, 0, 0, 0, 0);
|
||||
// Add an optional indent that will make buttons start at the correct column when
|
||||
// there is enough space to do so (and fall back to the left edge if not).
|
||||
view.setInt(R.id.actions, "setCollapsibleIndentDimen",
|
||||
R.dimen.call_notification_collapsible_indent);
|
||||
|
||||
// Emphasize so that buttons have borders or colored backgrounds
|
||||
boolean emphasizedMode = true;
|
||||
view.setBoolean(R.id.actions, "setEmphasizedMode", emphasizedMode);
|
||||
// Use "wrap_content" (unlike normal emphasized mode) and allow prioritizing the
|
||||
// required actions (Answer, Decline, and Hang Up).
|
||||
view.setBoolean(R.id.actions, "setPrioritizedWrapMode", true);
|
||||
|
||||
// Create the buttons for the generated actions list.
|
||||
int i = 0;
|
||||
for (Action action : makeActionsList(p)) {
|
||||
final RemoteViews button = mBuilder.generateActionButton(action, emphasizedMode, p);
|
||||
if (i > 0) {
|
||||
// Clear start margin from non-first buttons to reduce the gap between buttons.
|
||||
// (8dp remaining gap is from all buttons' standard 4dp inset).
|
||||
button.setViewLayoutMarginDimen(R.id.action0, RemoteViews.MARGIN_START, 0);
|
||||
}
|
||||
view.addView(R.id.actions, button);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
private void bindCallerVerification(RemoteViews contentView, StandardTemplateParams p) {
|
||||
String iconContentDescription = null;
|
||||
boolean showDivider = true;
|
||||
@@ -12121,7 +12147,7 @@ public class Notification implements Parcelable
|
||||
boolean mHideProgress;
|
||||
boolean mHideSnoozeButton;
|
||||
boolean mPromotePicture;
|
||||
boolean mAllowActionIcons;
|
||||
boolean mCallStyleActions;
|
||||
boolean mAllowTextWithProgress;
|
||||
CharSequence title;
|
||||
CharSequence text;
|
||||
@@ -12140,7 +12166,7 @@ public class Notification implements Parcelable
|
||||
mHideProgress = false;
|
||||
mHideSnoozeButton = false;
|
||||
mPromotePicture = false;
|
||||
mAllowActionIcons = false;
|
||||
mCallStyleActions = false;
|
||||
mAllowTextWithProgress = false;
|
||||
title = null;
|
||||
text = null;
|
||||
@@ -12181,8 +12207,8 @@ public class Notification implements Parcelable
|
||||
return this;
|
||||
}
|
||||
|
||||
final StandardTemplateParams allowActionIcons(boolean allowActionIcons) {
|
||||
this.mAllowActionIcons = allowActionIcons;
|
||||
final StandardTemplateParams callStyleActions(boolean callStyleActions) {
|
||||
this.mCallStyleActions = callStyleActions;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,6 @@ import android.app.AlarmManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.AutomaticZenRule;
|
||||
import android.app.BroadcastOptions;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.ITransientNotification;
|
||||
@@ -6082,6 +6081,17 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure CallStyle has all the correct actions
|
||||
if ("android.app.Notification$CallStyle".equals(
|
||||
notification.extras.getString(Notification.EXTRA_TEMPLATE))) {
|
||||
Notification.Builder builder =
|
||||
Notification.Builder.recoverBuilder(getContext(), notification);
|
||||
Notification.CallStyle style = (Notification.CallStyle) builder.getStyle();
|
||||
List<Notification.Action> actions = style.getActionsListWithSystemActions();
|
||||
notification.actions = new Notification.Action[actions.size()];
|
||||
actions.toArray(notification.actions);
|
||||
}
|
||||
|
||||
// Remote views? Are they too big?
|
||||
checkRemoteViews(pkg, tag, id, notification);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user