Merge "Update the conversation priority flow" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2d880ae90a
@@ -254,7 +254,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
|
||||
android:visibility="gone"
|
||||
android:text="@string/notification_channel_summary_priority"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:ellipsize="end"
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
<!--
|
||||
~ Copyright (C) 2020 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
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/onboarding_half_shell_container"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/half_shell"
|
||||
android:layout_width="@dimen/qs_panel_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="bottom"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:background="@drawable/rounded_bg_full"
|
||||
>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:padding="12dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
>
|
||||
|
||||
<!-- Big icon: 52x52, 12dp padding left + top, 16dp padding right -->
|
||||
<ImageView
|
||||
android:id="@+id/conversation_icon"
|
||||
android:layout_width="@*android:dimen/conversation_avatar_size"
|
||||
android:layout_height="@*android:dimen/conversation_avatar_size"
|
||||
android:scaleType="centerCrop"
|
||||
android:importantForAccessibility="no"
|
||||
/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/conversation_icon_badge"
|
||||
android:layout_width="@*android:dimen/conversation_icon_size_badged"
|
||||
android:layout_height="@*android:dimen/conversation_icon_size_badged"
|
||||
android:layout_marginLeft="@*android:dimen/conversation_badge_side_margin"
|
||||
android:layout_marginTop="@*android:dimen/conversation_badge_side_margin"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/conversation_icon_badge_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:src="@*android:drawable/conversation_badge_background"
|
||||
android:forceHasOverlappingRendering="false"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_gravity="center"
|
||||
android:forceHasOverlappingRendering="false"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/conversation_icon_badge_ring"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@*android:drawable/conversation_badge_ring"
|
||||
android:forceHasOverlappingRendering="false"
|
||||
android:clipToPadding="false"
|
||||
android:scaleType="center"
|
||||
/>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/priority_onboarding_title"
|
||||
style="@style/TextAppearance.NotificationImportanceChannel"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:background="@color/material_grey_300" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:text="@string/priority_onboarding_behavior"
|
||||
style="@style/TextAppearance.NotificationImportanceChannelGroup"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/behaviors"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/TextAppearance.NotificationImportanceChannelGroup"
|
||||
/>
|
||||
|
||||
<!-- Bottom button container -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/settings_button"
|
||||
android:text="@string/priority_onboarding_settings_button_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:gravity="start|center_vertical"
|
||||
android:minWidth="@dimen/notification_importance_toggle_size"
|
||||
android:minHeight="@dimen/notification_importance_toggle_size"
|
||||
android:maxWidth="125dp"
|
||||
style="@style/TextAppearance.NotificationInfo.Button"/>
|
||||
<TextView
|
||||
android:id="@+id/done_button"
|
||||
android:text="@string/priority_onboarding_done_button_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:gravity="end|center_vertical"
|
||||
android:minWidth="@dimen/notification_importance_toggle_size"
|
||||
android:minHeight="@dimen/notification_importance_toggle_size"
|
||||
android:maxWidth="125dp"
|
||||
style="@style/TextAppearance.NotificationInfo.Button"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
@@ -1897,13 +1897,16 @@
|
||||
<string name="notification_channel_summary_automatic_demoted"><b>Status:</b> Ranked Lower</string>
|
||||
|
||||
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
|
||||
<string name="notification_channel_summary_priority">Always shown at the top of your notifications, even when Priority mode is on</string>
|
||||
<string name="notification_channel_summary_priority_baseline">Shows at the top of conversation notifications and as a profile picture on lock screen</string>
|
||||
<string name="notification_channel_summary_priority_bubble">Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble</string>
|
||||
<string name="notification_channel_summary_priority_dnd">Shows at the top of conversation notifications and as a profile picture on lock screen, interrupts Do Not Disturb</string>
|
||||
<string name="notification_channel_summary_priority_all">Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb</string>
|
||||
|
||||
<!--[CHAR LIMIT=30] Linkable text to Settings app -->
|
||||
<string name="notification_conversation_channel_settings">Settings</string>
|
||||
|
||||
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level -->
|
||||
<string name="notification_priority_title">Priority conversations</string>
|
||||
<string name="notification_priority_title">Priority</string>
|
||||
|
||||
<!-- Text shown in notification guts for conversation notifications that don't implement the full feature -->
|
||||
<string name="no_shortcut"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> doesn\u2019t support conversation features</string>
|
||||
@@ -2667,25 +2670,6 @@
|
||||
<!-- Title of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=25] -->
|
||||
<string name="inattentive_sleep_warning_title">Standby</string>
|
||||
|
||||
<!-- Priority conversation onboarding screen -->
|
||||
<!-- title of priority onboarding [CHAR LIMIT=75] -->
|
||||
<string name="priority_onboarding_title">Conversation set to priority</string>
|
||||
<!-- Text explaining that the following actions are the behaviors of priority conversations.
|
||||
E.g. priority conversations will show at the top of the conversation section [CHAR LIMIT=75] -->
|
||||
<string name="priority_onboarding_behavior">Priority conversations</string>
|
||||
<!-- Text explaining that priority conversations show at the top of the conversation section [CHAR LIMIT=120] -->
|
||||
<string name="priority_onboarding_show_at_top_text">These conversations are shown at the top of your list and can always reach you when Priority mode is on</string>
|
||||
<!-- Text explaining that priority conversations show an avatar on the lock screen [CHAR LIMIT=120] -->
|
||||
<string name="priority_onboarding_show_avatar_text">Profile pictures are shown on the lock screen</string>
|
||||
<!-- Text explaining that priority conversations will appear as a bubble [CHAR LIMIT=120] -->
|
||||
<string name="priority_onboarding_appear_as_bubble_text">You can easily find these conversations in bubbles on your Home screen</string>
|
||||
<!-- Text explaining that priority conversations can interrupt DnD settings [CHAR LIMIT=120] -->
|
||||
<string name="priority_onboarding_ignores_dnd_text">Interrupt Do Not Disturb</string>
|
||||
<!-- Title for the affirmative button [CHAR LIMIT=50] -->
|
||||
<string name="priority_onboarding_done_button_title">Got it</string>
|
||||
<!-- Title for the settings button button [CHAR LIMIT=50] -->
|
||||
<string name="priority_onboarding_settings_button_title">Settings</string>
|
||||
|
||||
<!-- Window Magnification strings -->
|
||||
<!-- Title for Magnification Window [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_window_title">Magnification Window</string>
|
||||
|
||||
@@ -73,8 +73,7 @@ public final class Prefs {
|
||||
Key.TOUCHED_RINGER_TOGGLE,
|
||||
Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP,
|
||||
Key.HAS_SEEN_REVERSE_BOTTOM_SHEET,
|
||||
Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT,
|
||||
Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S
|
||||
Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT
|
||||
})
|
||||
// TODO: annotate these with their types so {@link PrefsCommandLine} can know how to set them
|
||||
public @interface Key {
|
||||
@@ -123,8 +122,6 @@ public final class Prefs {
|
||||
String HAS_SEEN_ODI_CAPTIONS_TOOLTIP = "HasSeenODICaptionsTooltip";
|
||||
String HAS_SEEN_REVERSE_BOTTOM_SHEET = "HasSeenReverseBottomSheet";
|
||||
String CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT = "ControlsStructureSwipeTooltipCount";
|
||||
/** Tracks whether the user has seen the onboarding screen for priority conversations */
|
||||
String HAS_SEEN_PRIORITY_ONBOARDING_IN_S = "HasUserSeenPriorityOnboardingInS";
|
||||
}
|
||||
|
||||
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
|
||||
|
||||
@@ -168,7 +168,6 @@ private class PrefsCommand(val context: Context) : Command {
|
||||
|
||||
when (topLevel) {
|
||||
"list-prefs" -> listPrefs(pw)
|
||||
"set-pref" -> setPref(pw, args.drop(1))
|
||||
else -> help(pw)
|
||||
}
|
||||
}
|
||||
@@ -180,25 +179,4 @@ private class PrefsCommand(val context: Context) : Command {
|
||||
pw.println(field.get(Prefs.Key::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a preference from [Prefs]
|
||||
*/
|
||||
private fun setPref(pw: PrintWriter, args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
pw.println("invalid arguments: $args")
|
||||
return
|
||||
}
|
||||
val pref = args[0]
|
||||
|
||||
when (pref) {
|
||||
Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S -> {
|
||||
val value = Integer.parseInt(args[1])
|
||||
Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, value != 0)
|
||||
}
|
||||
else -> {
|
||||
pw.println("Cannot set pref ($pref)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg
|
||||
import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
|
||||
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
|
||||
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
|
||||
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
@@ -141,7 +140,6 @@ public interface NotificationsModule {
|
||||
ShortcutManager shortcutManager,
|
||||
ChannelEditorDialogController channelEditorDialogController,
|
||||
UserContextProvider contextTracker,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
Optional<BubblesManager> bubblesManagerOptional,
|
||||
UiEventLogger uiEventLogger,
|
||||
@@ -161,7 +159,6 @@ public interface NotificationsModule {
|
||||
shortcutManager,
|
||||
channelEditorDialogController,
|
||||
contextTracker,
|
||||
builderProvider,
|
||||
assistantFeedbackController,
|
||||
bubblesManagerOptional,
|
||||
uiEventLogger,
|
||||
|
||||
@@ -22,6 +22,8 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
|
||||
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
|
||||
|
||||
import static com.android.systemui.animation.Interpolators.FAST_OUT_SLOW_IN;
|
||||
|
||||
@@ -34,7 +36,6 @@ import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -55,7 +56,6 @@ import android.transition.TransitionManager;
|
||||
import android.transition.TransitionSet;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.ImageView;
|
||||
@@ -64,7 +64,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settingslib.notification.ConversationIconFactory;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
@@ -78,8 +77,6 @@ import com.android.systemui.wmshell.BubblesManager;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* The guts of a conversation notification revealed when performing a long press.
|
||||
*/
|
||||
@@ -107,7 +104,6 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
private StatusBarNotification mSbn;
|
||||
@Nullable private Notification.BubbleMetadata mBubbleMetadata;
|
||||
private Context mUserContext;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
|
||||
private boolean mIsDeviceProvisioned;
|
||||
private int mAppBubble;
|
||||
|
||||
@@ -172,13 +168,9 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
private OnClickListener mOnDone = v -> {
|
||||
mPressedApply = true;
|
||||
|
||||
// If the user selected Priority, maybe show the priority onboarding.
|
||||
// If the user selected Priority and the previous selection was not priority, show a
|
||||
// People Tile add request. If showing the priority onboarding, however, delay the request
|
||||
// to when the onboarding dialog closes.
|
||||
if (mSelectedAction == ACTION_FAVORITE && shouldShowPriorityOnboarding()) {
|
||||
showPriorityOnboarding();
|
||||
} else if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) {
|
||||
// People Tile add request.
|
||||
if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) {
|
||||
mShadeController.animateCollapsePanels();
|
||||
mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle());
|
||||
}
|
||||
@@ -229,7 +221,6 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
OnSnoozeClickListener onSnoozeClickListener,
|
||||
ConversationIconFactory conversationIconFactory,
|
||||
Context userContext,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
|
||||
boolean isDeviceProvisioned,
|
||||
@Main Handler mainHandler,
|
||||
@Background Handler bgHandler,
|
||||
@@ -258,7 +249,6 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
mBubbleMetadata = bubbleMetadata;
|
||||
mBubblesManagerOptional = bubblesManagerOptional;
|
||||
mShadeController = shadeController;
|
||||
mBuilderProvider = builderProvider;
|
||||
mMainHandler = mainHandler;
|
||||
mBgHandler = bgHandler;
|
||||
mShortcutManager = shortcutManager;
|
||||
@@ -342,6 +332,18 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
// bindName();
|
||||
bindPackage();
|
||||
bindIcon(mNotificationChannel.isImportantConversation());
|
||||
|
||||
mPriorityDescriptionView = findViewById(R.id.priority_summary);
|
||||
if (willShowAsBubble() && willBypassDnd()) {
|
||||
mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_all);
|
||||
} else if (willShowAsBubble()) {
|
||||
mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_bubble);
|
||||
} else if (willBypassDnd()) {
|
||||
mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_dnd);
|
||||
} else {
|
||||
mPriorityDescriptionView.setText(
|
||||
R.string.notification_channel_summary_priority_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindIcon(boolean important) {
|
||||
@@ -428,7 +430,6 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mPriorityDescriptionView = findViewById(R.id.priority_summary);
|
||||
mDefaultDescriptionView = findViewById(R.id.default_summary);
|
||||
mSilentDescriptionView = findViewById(R.id.silence_summary);
|
||||
}
|
||||
@@ -552,51 +553,22 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||
}
|
||||
|
||||
private boolean shouldShowPriorityOnboarding() {
|
||||
return !Prefs.getBoolean(mUserContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, false);
|
||||
}
|
||||
|
||||
private void showPriorityOnboarding() {
|
||||
View onboardingView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.priority_onboarding_half_shell, null);
|
||||
|
||||
boolean ignoreDnd = false;
|
||||
private boolean willBypassDnd() {
|
||||
boolean bypassesDnd = false;
|
||||
try {
|
||||
ignoreDnd = mINotificationManager
|
||||
.getConsolidatedNotificationPolicy().priorityConversationSenders ==
|
||||
NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
|
||||
int allowedSenders = mINotificationManager
|
||||
.getConsolidatedNotificationPolicy().priorityConversationSenders;
|
||||
bypassesDnd = allowedSenders == CONVERSATION_SENDERS_IMPORTANT
|
||||
|| allowedSenders == CONVERSATION_SENDERS_ANYONE;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not check conversation senders", e);
|
||||
}
|
||||
return bypassesDnd;
|
||||
}
|
||||
|
||||
boolean showAsBubble = mBubbleMetadata != null
|
||||
&& mBubbleMetadata.getAutoExpandBubble()
|
||||
private boolean willShowAsBubble() {
|
||||
return mBubbleMetadata != null
|
||||
&& BubblesManager.areBubblesEnabled(mContext, mSbn.getUser());
|
||||
|
||||
Drawable person = mIconFactory.getBaseIconDrawable(mShortcutInfo);
|
||||
if (person == null) {
|
||||
person = mContext.getDrawable(R.drawable.ic_person).mutate();
|
||||
TypedArray ta = mContext.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
|
||||
int colorAccent = ta.getColor(0, 0);
|
||||
ta.recycle();
|
||||
person.setTint(colorAccent);
|
||||
}
|
||||
|
||||
PriorityOnboardingDialogController controller = mBuilderProvider.get()
|
||||
.setContext(mUserContext)
|
||||
.setView(onboardingView)
|
||||
.setIgnoresDnd(ignoreDnd)
|
||||
.setShowsAsBubble(showAsBubble)
|
||||
.setIcon(person)
|
||||
.setBadge(mIconFactory.getAppBadge(
|
||||
mPackageName, UserHandle.getUserId(mSbn.getUid())))
|
||||
.setOnSettingsClick(mOnConversationSettingsClickListener)
|
||||
.setPeopleSpaceWidgetManager(mPeopleSpaceWidgetManager)
|
||||
.setShadeController(mShadeController)
|
||||
.build();
|
||||
|
||||
controller.init(mShortcutInfo);
|
||||
controller.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -129,7 +129,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
private final LauncherApps mLauncherApps;
|
||||
private final ShortcutManager mShortcutManager;
|
||||
private final UserContextProvider mContextTracker;
|
||||
private final Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final ShadeController mShadeController;
|
||||
private final AppWidgetManager mAppWidgetManager;
|
||||
@@ -150,7 +149,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
ShortcutManager shortcutManager,
|
||||
ChannelEditorDialogController channelEditorDialogController,
|
||||
UserContextProvider contextTracker,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
Optional<BubblesManager> bubblesManagerOptional,
|
||||
UiEventLogger uiEventLogger,
|
||||
@@ -168,7 +166,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
mLauncherApps = launcherApps;
|
||||
mShortcutManager = shortcutManager;
|
||||
mContextTracker = contextTracker;
|
||||
mBuilderProvider = builderProvider;
|
||||
mChannelEditorDialogController = channelEditorDialogController;
|
||||
mAssistantFeedbackController = assistantFeedbackController;
|
||||
mBubblesManagerOptional = bubblesManagerOptional;
|
||||
@@ -503,7 +500,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
onSnoozeClickListener,
|
||||
iconFactoryLoader,
|
||||
mContextTracker.getUserContext(),
|
||||
mBuilderProvider,
|
||||
mDeviceProvisionedController.isDeviceProvisioned(),
|
||||
mMainHandler,
|
||||
mBgHandler,
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.notification.row
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.graphics.Color
|
||||
import android.graphics.PixelFormat
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.BulletSpan
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.view.Window
|
||||
import android.view.WindowInsets.Type.statusBars
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.Interpolator
|
||||
import android.view.animation.PathInterpolator
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.android.systemui.Prefs
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Interpolators.LINEAR_OUT_SLOW_IN
|
||||
import com.android.systemui.people.widget.PeopleSpaceWidgetManager
|
||||
import com.android.systemui.statusbar.notification.row.NotificationConversationInfo.OnConversationSettingsClickListener
|
||||
import com.android.systemui.statusbar.phone.ShadeController
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Controller to handle presenting the priority conversations onboarding dialog
|
||||
*/
|
||||
class PriorityOnboardingDialogController @Inject constructor(
|
||||
val view: View,
|
||||
val context: Context,
|
||||
private val ignoresDnd: Boolean,
|
||||
private val showsAsBubble: Boolean,
|
||||
val icon: Drawable,
|
||||
private val onConversationSettingsClickListener: OnConversationSettingsClickListener,
|
||||
val badge: Drawable,
|
||||
private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager,
|
||||
private val shadeController: ShadeController
|
||||
) {
|
||||
|
||||
private lateinit var dialog: Dialog
|
||||
private lateinit var shortcutInfo: ShortcutInfo
|
||||
private val OVERSHOOT: Interpolator = PathInterpolator(0.4f, 0f, 0.2f, 1.4f)
|
||||
private val IMPORTANCE_ANIM_DELAY = 150L
|
||||
private val IMPORTANCE_ANIM_GROW_DURATION = 250L
|
||||
private val IMPORTANCE_ANIM_SHRINK_DURATION = 200L
|
||||
private val IMPORTANCE_ANIM_SHRINK_DELAY = 25L
|
||||
|
||||
fun init(info: ShortcutInfo) {
|
||||
shortcutInfo = info
|
||||
initDialog()
|
||||
}
|
||||
|
||||
fun show() {
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun done() {
|
||||
// Log that the user has seen the onboarding
|
||||
Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true)
|
||||
dialog.dismiss()
|
||||
shadeController.animateCollapsePanels()
|
||||
peopleSpaceWidgetManager.requestPinAppWidget(shortcutInfo, Bundle())
|
||||
}
|
||||
|
||||
private fun settings() {
|
||||
// Log that the user has seen the onboarding
|
||||
Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true)
|
||||
dialog.dismiss()
|
||||
onConversationSettingsClickListener?.onClick()
|
||||
}
|
||||
|
||||
class Builder @Inject constructor() {
|
||||
private lateinit var view: View
|
||||
private lateinit var context: Context
|
||||
private var ignoresDnd = false
|
||||
private var showAsBubble = false
|
||||
private lateinit var icon: Drawable
|
||||
private lateinit var onConversationSettingsClickListener:
|
||||
OnConversationSettingsClickListener
|
||||
private lateinit var badge: Drawable
|
||||
private lateinit var peopleSpaceWidgetManager: PeopleSpaceWidgetManager
|
||||
private lateinit var shadeController: ShadeController
|
||||
|
||||
fun setView(v: View): Builder {
|
||||
view = v
|
||||
return this
|
||||
}
|
||||
|
||||
fun setContext(c: Context): Builder {
|
||||
context = c
|
||||
return this
|
||||
}
|
||||
|
||||
fun setIgnoresDnd(ignore: Boolean): Builder {
|
||||
ignoresDnd = ignore
|
||||
return this
|
||||
}
|
||||
|
||||
fun setShowsAsBubble(bubble: Boolean): Builder {
|
||||
showAsBubble = bubble
|
||||
return this
|
||||
}
|
||||
|
||||
fun setIcon(draw: Drawable): Builder {
|
||||
icon = draw
|
||||
return this
|
||||
}
|
||||
fun setBadge(badge: Drawable): Builder {
|
||||
this.badge = badge
|
||||
return this
|
||||
}
|
||||
|
||||
fun setOnSettingsClick(onClick: OnConversationSettingsClickListener): Builder {
|
||||
onConversationSettingsClickListener = onClick
|
||||
return this
|
||||
}
|
||||
|
||||
fun setShadeController(shadeController: ShadeController): Builder {
|
||||
this.shadeController = shadeController
|
||||
return this
|
||||
}
|
||||
|
||||
fun setPeopleSpaceWidgetManager(peopleSpaceWidgetManager: PeopleSpaceWidgetManager):
|
||||
Builder {
|
||||
this.peopleSpaceWidgetManager = peopleSpaceWidgetManager
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): PriorityOnboardingDialogController {
|
||||
val controller = PriorityOnboardingDialogController(
|
||||
view, context, ignoresDnd, showAsBubble, icon,
|
||||
onConversationSettingsClickListener, badge, peopleSpaceWidgetManager,
|
||||
shadeController)
|
||||
return controller
|
||||
}
|
||||
}
|
||||
|
||||
private fun initDialog() {
|
||||
dialog = Dialog(context)
|
||||
|
||||
if (dialog.window == null) {
|
||||
throw IllegalStateException("Need a window for the onboarding dialog to show")
|
||||
}
|
||||
|
||||
dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
// Prevent a11y readers from reading the first element in the dialog twice
|
||||
dialog.setTitle("\u00A0")
|
||||
dialog.apply {
|
||||
setContentView(view)
|
||||
setCanceledOnTouchOutside(true)
|
||||
|
||||
findViewById<TextView>(R.id.done_button)?.setOnClickListener {
|
||||
done()
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.settings_button)?.setOnClickListener {
|
||||
settings()
|
||||
}
|
||||
|
||||
findViewById<ImageView>(R.id.conversation_icon)?.setImageDrawable(icon)
|
||||
findViewById<ImageView>(R.id.icon)?.setImageDrawable(badge)
|
||||
val mImportanceRingView = findViewById<ImageView>(R.id.conversation_icon_badge_ring)
|
||||
val conversationIconBadgeBg = findViewById<ImageView>(R.id.conversation_icon_badge_bg)
|
||||
|
||||
val ring: GradientDrawable = mImportanceRingView.drawable as GradientDrawable
|
||||
ring.mutate()
|
||||
val bg = conversationIconBadgeBg.drawable as GradientDrawable
|
||||
bg.mutate()
|
||||
val ringColor = context.getResources()
|
||||
.getColor(com.android.internal.R.color.conversation_important_highlight)
|
||||
val standardThickness = context.resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.importance_ring_stroke_width)
|
||||
val largeThickness = context.resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.importance_ring_anim_max_stroke_width)
|
||||
val standardSize = context.resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.importance_ring_size)
|
||||
val baseSize = standardSize - standardThickness * 2
|
||||
val largeSize = baseSize + largeThickness * 2
|
||||
val bgSize = context.resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.conversation_icon_size_badged)
|
||||
|
||||
val animatorUpdateListener: ValueAnimator.AnimatorUpdateListener =
|
||||
ValueAnimator.AnimatorUpdateListener { animation ->
|
||||
val strokeWidth = animation.animatedValue as Int
|
||||
ring.setStroke(strokeWidth, ringColor)
|
||||
val newSize = baseSize + strokeWidth * 2
|
||||
ring.setSize(newSize, newSize)
|
||||
mImportanceRingView.invalidate()
|
||||
}
|
||||
|
||||
val growAnimation: ValueAnimator = ValueAnimator.ofInt(0, largeThickness)
|
||||
growAnimation.interpolator = LINEAR_OUT_SLOW_IN
|
||||
growAnimation.duration = IMPORTANCE_ANIM_GROW_DURATION
|
||||
growAnimation.addUpdateListener(animatorUpdateListener)
|
||||
|
||||
val shrinkAnimation: ValueAnimator =
|
||||
ValueAnimator.ofInt(largeThickness, standardThickness)
|
||||
shrinkAnimation.duration = IMPORTANCE_ANIM_SHRINK_DURATION
|
||||
shrinkAnimation.startDelay = IMPORTANCE_ANIM_SHRINK_DELAY
|
||||
shrinkAnimation.interpolator = OVERSHOOT
|
||||
shrinkAnimation.addUpdateListener(animatorUpdateListener)
|
||||
shrinkAnimation.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
// Shrink the badge bg so that it doesn't peek behind the animation
|
||||
bg.setSize(baseSize, baseSize)
|
||||
conversationIconBadgeBg.invalidate()
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
// Reset bg back to normal size
|
||||
bg.setSize(bgSize, bgSize)
|
||||
conversationIconBadgeBg.invalidate()
|
||||
}
|
||||
})
|
||||
|
||||
val anims = AnimatorSet()
|
||||
anims.startDelay = IMPORTANCE_ANIM_DELAY
|
||||
anims.playSequentially(growAnimation, shrinkAnimation)
|
||||
|
||||
val gapWidth = dialog.context.getResources().getDimensionPixelSize(
|
||||
R.dimen.conversation_onboarding_bullet_gap_width)
|
||||
val description = SpannableStringBuilder()
|
||||
description.append(context.getText(R.string.priority_onboarding_show_at_top_text),
|
||||
BulletSpan(gapWidth), /* flags */0)
|
||||
description.append(System.lineSeparator())
|
||||
description.append(context.getText(R.string.priority_onboarding_show_avatar_text),
|
||||
BulletSpan(gapWidth), /* flags */0)
|
||||
if (showsAsBubble) {
|
||||
description.append(System.lineSeparator())
|
||||
description.append(context.getText(
|
||||
R.string.priority_onboarding_appear_as_bubble_text),
|
||||
BulletSpan(gapWidth), /* flags */0)
|
||||
}
|
||||
if (ignoresDnd) {
|
||||
description.append(System.lineSeparator())
|
||||
description.append(context.getText(R.string.priority_onboarding_ignores_dnd_text),
|
||||
BulletSpan(gapWidth), /* flags */0)
|
||||
}
|
||||
findViewById<TextView>(R.id.behaviors).setText(description)
|
||||
|
||||
window?.apply {
|
||||
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
addFlags(wmFlags)
|
||||
setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
|
||||
setWindowAnimations(com.android.internal.R.style.Animation_InputMethod)
|
||||
|
||||
attributes = attributes.apply {
|
||||
format = PixelFormat.TRANSLUCENT
|
||||
title = PriorityOnboardingDialogController::class.java.simpleName
|
||||
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
||||
fitInsetsTypes = attributes.fitInsetsTypes and statusBars().inv()
|
||||
width = MATCH_PARENT
|
||||
height = WRAP_CONTENT
|
||||
}
|
||||
}
|
||||
anims.start()
|
||||
}
|
||||
}
|
||||
|
||||
private val wmFlags = (WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
||||
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
||||
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
|
||||
}
|
||||
@@ -21,6 +21,8 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
|
||||
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
|
||||
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
@@ -150,9 +152,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
private ShadeController mShadeController;
|
||||
@Mock
|
||||
private ConversationIconFactory mIconFactory;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private PriorityOnboardingDialogController.Builder mBuilder;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider = () -> mBuilder;
|
||||
@Mock
|
||||
private Notification.BubbleMetadata mBubbleMetadata;
|
||||
private Handler mTestHandler;
|
||||
@@ -236,8 +235,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
when(mMockINotificationManager.getConsolidatedNotificationPolicy())
|
||||
.thenReturn(mock(NotificationManager.Policy.class));
|
||||
|
||||
when(mBuilder.build()).thenReturn(mock(PriorityOnboardingDialogController.class));
|
||||
|
||||
when(mPeopleSpaceWidgetManager.requestPinAppWidget(any(), any())).thenReturn(true);
|
||||
}
|
||||
|
||||
@@ -258,7 +255,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -285,7 +281,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -340,7 +335,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -368,7 +362,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -395,7 +388,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -433,7 +425,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -464,7 +455,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -493,7 +483,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -523,7 +512,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
false,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -551,7 +539,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -582,7 +569,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -616,7 +602,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -626,6 +611,110 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
assertThat(((TextView) view.findViewById(R.id.default_summary)).getText()).isEqualTo(
|
||||
mContext.getString(R.string.notification_channel_summary_default_with_bubbles,
|
||||
"App Name"));
|
||||
assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText())
|
||||
.isEqualTo(mContext.getString(
|
||||
R.string.notification_channel_summary_priority_bubble));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindNotification_priorityDnd() throws Exception {
|
||||
NotificationManager.Policy policy = new NotificationManager.Policy(
|
||||
PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE);
|
||||
when(mMockINotificationManager.getConsolidatedNotificationPolicy())
|
||||
.thenReturn(policy);
|
||||
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
|
||||
mConversationChannel.setImportance(IMPORTANCE_HIGH);
|
||||
mConversationChannel.setImportantConversation(false);
|
||||
mConversationChannel.setAllowBubbles(false);
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mPeopleSpaceWidgetManager,
|
||||
mMockINotificationManager,
|
||||
mOnUserInteractionCallback,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
mShadeController);
|
||||
assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText())
|
||||
.isEqualTo(mContext.getString(
|
||||
R.string.notification_channel_summary_priority_dnd));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindNotification_priorityBaseline() throws Exception {
|
||||
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
|
||||
mConversationChannel.setImportance(IMPORTANCE_HIGH);
|
||||
mConversationChannel.setImportantConversation(false);
|
||||
mConversationChannel.setAllowBubbles(false);
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mPeopleSpaceWidgetManager,
|
||||
mMockINotificationManager,
|
||||
mOnUserInteractionCallback,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
mShadeController);
|
||||
assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText())
|
||||
.isEqualTo(mContext.getString(
|
||||
R.string.notification_channel_summary_priority_baseline));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindNotification_priorityDndAndBubble() throws Exception {
|
||||
NotificationManager.Policy policy = new NotificationManager.Policy(
|
||||
PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE);
|
||||
when(mMockINotificationManager.getConsolidatedNotificationPolicy())
|
||||
.thenReturn(policy);
|
||||
|
||||
when(mMockINotificationManager.getBubblePreferenceForPackage(anyString(), anyInt()))
|
||||
.thenReturn(BUBBLE_PREFERENCE_ALL);
|
||||
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
|
||||
mConversationChannel.setImportance(IMPORTANCE_HIGH);
|
||||
mConversationChannel.setImportantConversation(false);
|
||||
mConversationChannel.setAllowBubbles(true);
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mPeopleSpaceWidgetManager,
|
||||
mMockINotificationManager,
|
||||
mOnUserInteractionCallback,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
mBubbleMetadata,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
mShadeController);
|
||||
assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText())
|
||||
.isEqualTo(mContext.getString(
|
||||
R.string.notification_channel_summary_priority_all));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -649,7 +738,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -696,7 +784,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -742,7 +829,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -789,7 +875,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -829,7 +914,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -868,7 +952,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -911,7 +994,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -944,7 +1026,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -976,7 +1057,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1015,7 +1095,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1054,7 +1133,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1092,7 +1170,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1129,7 +1206,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1157,7 +1233,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1167,98 +1242,9 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
anyString(), anyInt(), any(), eq(CONVERSATION_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPriorityPresentsOnboarding_firstTime() {
|
||||
// GIVEN pref is false
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, false);
|
||||
|
||||
// GIVEN the priority onboarding screen is present
|
||||
PriorityOnboardingDialogController.Builder b =
|
||||
mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF);
|
||||
PriorityOnboardingDialogController controller =
|
||||
mock(PriorityOnboardingDialogController.class);
|
||||
when(b.build()).thenReturn(controller);
|
||||
|
||||
// GIVEN the user is changing conversation settings
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mPeopleSpaceWidgetManager,
|
||||
mMockINotificationManager,
|
||||
mOnUserInteractionCallback,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
mBubbleMetadata,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
() -> b,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
mShadeController);
|
||||
|
||||
// WHEN user clicks "priority"
|
||||
mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
|
||||
verify(controller, never()).show();
|
||||
|
||||
// and then done
|
||||
mNotificationInfo.findViewById(R.id.done).performClick();
|
||||
|
||||
// THEN the user is presented with the priority onboarding screen
|
||||
verify(controller, atLeastOnce()).show();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPriorityDoesNotShowOnboarding_secondTime() {
|
||||
//WHEN pref is true
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true);
|
||||
|
||||
PriorityOnboardingDialogController.Builder b =
|
||||
mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF);
|
||||
PriorityOnboardingDialogController controller =
|
||||
mock(PriorityOnboardingDialogController.class);
|
||||
when(b.build()).thenReturn(controller);
|
||||
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mPeopleSpaceWidgetManager,
|
||||
mMockINotificationManager,
|
||||
mOnUserInteractionCallback,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
mBubbleMetadata,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
() -> b,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
mShadeController);
|
||||
|
||||
// WHEN user clicks "priority"
|
||||
mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
|
||||
verify(controller, never()).show();
|
||||
|
||||
// and then done
|
||||
mNotificationInfo.findViewById(R.id.done).performClick();
|
||||
|
||||
// THEN the user is presented with the priority onboarding screen
|
||||
verify(controller, never()).show();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPriorityRequestsPinPeopleTile() {
|
||||
//WHEN pref is true and channel is default importance
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true);
|
||||
//WHEN channel is default importance
|
||||
mNotificationChannel.setImportantConversation(false);
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
@@ -1275,7 +1261,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1293,9 +1278,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testSelectDefaultDoesNotRequestPinPeopleTile() {
|
||||
//WHEN pref is true
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true);
|
||||
|
||||
mNotificationInfo.bindNotification(
|
||||
-1,
|
||||
mShortcutManager,
|
||||
@@ -1311,7 +1293,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
@@ -1329,8 +1310,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testSelectPriority_AlreadyPriority_DoesNotRequestPinPeopleTile() {
|
||||
//WHEN pref is true and channel is priority
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true);
|
||||
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
|
||||
mConversationChannel.setImportance(IMPORTANCE_HIGH);
|
||||
mConversationChannel.setImportantConversation(true);
|
||||
@@ -1350,7 +1329,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
mIconFactory,
|
||||
mContext,
|
||||
mBuilderProvider,
|
||||
true,
|
||||
mTestHandler,
|
||||
mTestHandler, null, Optional.of(mBubblesManager),
|
||||
|
||||
@@ -139,9 +139,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
@Mock private BubblesManager mBubblesManager;
|
||||
@Mock private ShadeController mShadeController;
|
||||
@Mock private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private PriorityOnboardingDialogController.Builder mBuilder;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mProvider = () -> mBuilder;
|
||||
@Mock private AssistantFeedbackController mAssistantFeedbackController;
|
||||
|
||||
@Before
|
||||
@@ -163,7 +160,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
() -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider,
|
||||
mINotificationManager, mNotificationEntryManager, mPeopleSpaceWidgetManager,
|
||||
mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker,
|
||||
mProvider, mAssistantFeedbackController, Optional.of(mBubblesManager),
|
||||
mAssistantFeedbackController, Optional.of(mBubblesManager),
|
||||
new UiEventLoggerFake(), mOnUserInteractionCallback, mShadeController);
|
||||
mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
|
||||
mCheckSaveListener, mOnSettingsClickListener);
|
||||
|
||||
Reference in New Issue
Block a user