DO NOT MERGE: Show an onboarding screen for priority conversations
Test: atest SystemUITests Bug: 151843296 Change-Id: I5280cff71591f8551016b6ba00d3a579507367cb
This commit is contained in:
194
packages/SystemUI/res/layout/priority_onboarding_half_shell.xml
Normal file
194
packages/SystemUI/res/layout/priority_onboarding_half_shell.xml
Normal file
@@ -0,0 +1,194 @@
|
||||
<!--
|
||||
~ 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:paddingBottom="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"
|
||||
>
|
||||
|
||||
<!-- We have a known number of rows that can be shown; just design them all here -->
|
||||
<LinearLayout
|
||||
android:id="@+id/show_at_top_tip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/bell_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/ic_notifications_alert"
|
||||
android:tint="?android:attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/show_at_top_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textSize="15sp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/priority_onboarding_show_at_top_text"
|
||||
style="@style/TextAppearance.NotificationInfo"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_avatar_tip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/avatar_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/ic_person"
|
||||
android:tint="?android:attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/avatar_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textSize="15sp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/priority_onboarding_show_avatar_text"
|
||||
style="@style/TextAppearance.NotificationInfo"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- These rows show optionally -->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/floating_bubble_tip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bubble_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/ic_create_bubble"
|
||||
android:tint="?android:attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bubble_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textSize="15sp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/priority_onboarding_appear_as_bubble_text"
|
||||
style="@style/TextAppearance.NotificationInfo"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ignore_dnd_tip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dnd_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/moon"
|
||||
android:tint="?android:attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dnd_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textSize="15sp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/priority_onboarding_ignores_dnd_text"
|
||||
style="@style/TextAppearance.NotificationInfo"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Bottom button container -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<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>
|
||||
@@ -2639,6 +2639,18 @@
|
||||
<!-- 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 -->
|
||||
<!-- Text explaining that priority conversations show at the top of the conversation section [CHAR LIMIT=50] -->
|
||||
<string name="priority_onboarding_show_at_top_text">Show at top of conversation section</string>
|
||||
<!-- Text explaining that priority conversations show an avatar on the lock screen [CHAR LIMIT=50] -->
|
||||
<string name="priority_onboarding_show_avatar_text">Show profile picture on lock screen</string>
|
||||
<!-- Text explaining that priority conversations will appear as a bubble [CHAR LIMIT=50] -->
|
||||
<string name="priority_onboarding_appear_as_bubble_text">Appear as a floating bubble on top of apps</string>
|
||||
<!-- Text explaining that priority conversations can interrupt DnD settings [CHAR LIMIT=50] -->
|
||||
<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>
|
||||
|
||||
<!-- Window Magnification strings -->
|
||||
<!-- Title for Magnification Overlay Window [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_overlay_title">Magnification Overlay Window</string>
|
||||
|
||||
@@ -21,11 +21,25 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
|
||||
import com.android.systemui.settings.CurrentUserContextTracker;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A helper class to store simple preferences for SystemUI. Its main use case is things such as
|
||||
* feature education, e.g. "has the user seen this tooltip".
|
||||
*
|
||||
* As of this writing, feature education settings are *intentionally exempted* from backup and
|
||||
* restore because there is not a great way to know which subset of features the user _should_ see
|
||||
* again if, for instance, they are coming from multiple OSes back or switching OEMs.
|
||||
*
|
||||
* NOTE: Clients of this class should take care to pass in the correct user context when querying
|
||||
* settings, otherwise you will always read/write for user 0 which is almost never what you want.
|
||||
* See {@link CurrentUserContextTracker} for a simple way to get the current context
|
||||
*/
|
||||
public final class Prefs {
|
||||
private Prefs() {} // no instantation
|
||||
|
||||
@@ -109,6 +123,8 @@ public final class Prefs {
|
||||
String HAS_SEEN_BUBBLES_EDUCATION = "HasSeenBubblesOnboarding";
|
||||
String HAS_SEEN_BUBBLES_MANAGE_EDUCATION = "HasSeenBubblesManageOnboarding";
|
||||
String CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT = "ControlsStructureSwipeTooltipCount";
|
||||
/** Tracks whether the user has seen the onboarding screen for priority conversations */
|
||||
String HAS_SEEN_PRIORITY_ONBOARDING = "HasSeenPriorityOnboarding";
|
||||
}
|
||||
|
||||
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.keyguard.KeyguardViewController;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.dock.DockManagerImpl;
|
||||
import com.android.systemui.plugins.qs.QSFactory;
|
||||
@@ -33,6 +34,7 @@ import com.android.systemui.power.EnhancedEstimatesImpl;
|
||||
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.RecentsImplementation;
|
||||
import com.android.systemui.settings.CurrentUserContextTracker;
|
||||
import com.android.systemui.stackdivider.DividerModule;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
@@ -136,4 +138,15 @@ public abstract class SystemUIDefaultModule {
|
||||
@Binds
|
||||
abstract KeyguardViewController bindKeyguardViewController(
|
||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager);
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
static CurrentUserContextTracker provideCurrentUserContextTracker(
|
||||
Context context,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
CurrentUserContextTracker tracker =
|
||||
new CurrentUserContextTracker(context, broadcastDispatcher);
|
||||
tracker.initialize();
|
||||
return tracker;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.os.UserHandle
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.util.Assert
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Tracks a reference to the context for the current user
|
||||
*/
|
||||
@Singleton
|
||||
class CurrentUserContextTracker @Inject constructor(
|
||||
private val sysuiContext: Context,
|
||||
broadcastDispatcher: BroadcastDispatcher
|
||||
) {
|
||||
private val userTracker: CurrentUserTracker
|
||||
var currentUserContext: Context
|
||||
|
||||
init {
|
||||
userTracker = object : CurrentUserTracker(broadcastDispatcher) {
|
||||
override fun onUserSwitched(newUserId: Int) {
|
||||
handleUserSwitched(newUserId)
|
||||
}
|
||||
}
|
||||
|
||||
currentUserContext = makeUserContext(userTracker.currentUserId)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
userTracker.startTracking()
|
||||
}
|
||||
|
||||
private fun handleUserSwitched(newUserId: Int) {
|
||||
currentUserContext = makeUserContext(newUserId)
|
||||
}
|
||||
|
||||
private fun makeUserContext(uid: Int): Context {
|
||||
Assert.isMainThread()
|
||||
return sysuiContext.createContextAsUser(
|
||||
UserHandle.getUserHandleForUid(userTracker.currentUserId), 0)
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dagger.qualifiers.UiBackground;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.settings.CurrentUserContextTracker;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.NotificationListener;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -53,6 +54,7 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
|
||||
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
@@ -60,6 +62,7 @@ import com.android.systemui.util.leak.LeakDetector;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Binds;
|
||||
@@ -109,7 +112,9 @@ public interface NotificationsModule {
|
||||
HighPriorityProvider highPriorityProvider,
|
||||
INotificationManager notificationManager,
|
||||
LauncherApps launcherApps,
|
||||
ShortcutManager shortcutManager) {
|
||||
ShortcutManager shortcutManager,
|
||||
CurrentUserContextTracker contextTracker,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider) {
|
||||
return new NotificationGutsManager(
|
||||
context,
|
||||
visualStabilityManager,
|
||||
@@ -119,7 +124,9 @@ public interface NotificationsModule {
|
||||
highPriorityProvider,
|
||||
notificationManager,
|
||||
launcherApps,
|
||||
shortcutManager);
|
||||
shortcutManager,
|
||||
contextTracker,
|
||||
builderProvider);
|
||||
}
|
||||
|
||||
/** Provides an instance of {@link VisualStabilityManager} */
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.provider.Settings.Global.NOTIFICATION_BUBBLES;
|
||||
|
||||
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
|
||||
|
||||
@@ -45,6 +46,7 @@ import android.graphics.drawable.Icon;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.text.TextUtils;
|
||||
import android.transition.ChangeBounds;
|
||||
@@ -53,7 +55,7 @@ import android.transition.TransitionManager;
|
||||
import android.transition.TransitionSet;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.ImageView;
|
||||
@@ -63,6 +65,7 @@ import android.widget.TextView;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settingslib.notification.ConversationIconFactory;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.NotificationChannelHelper;
|
||||
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
@@ -71,6 +74,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* The guts of a conversation notification revealed when performing a long press.
|
||||
*/
|
||||
@@ -93,6 +98,9 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
private ShortcutInfo mShortcutInfo;
|
||||
private String mConversationId;
|
||||
private StatusBarNotification mSbn;
|
||||
private Notification.BubbleMetadata mBubbleMetadata;
|
||||
private Context mUserContext;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
|
||||
private boolean mIsDeviceProvisioned;
|
||||
private int mAppBubble;
|
||||
|
||||
@@ -136,17 +144,17 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
*/
|
||||
|
||||
private OnClickListener mOnFavoriteClick = v -> {
|
||||
mSelectedAction = ACTION_FAVORITE;
|
||||
setSelectedAction(ACTION_FAVORITE);
|
||||
updateToggleActions(mSelectedAction, true);
|
||||
};
|
||||
|
||||
private OnClickListener mOnDefaultClick = v -> {
|
||||
mSelectedAction = ACTION_DEFAULT;
|
||||
setSelectedAction(ACTION_DEFAULT);
|
||||
updateToggleActions(mSelectedAction, true);
|
||||
};
|
||||
|
||||
private OnClickListener mOnMuteClick = v -> {
|
||||
mSelectedAction = ACTION_MUTE;
|
||||
setSelectedAction(ACTION_MUTE);
|
||||
updateToggleActions(mSelectedAction, true);
|
||||
};
|
||||
|
||||
@@ -170,6 +178,23 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
void onClick(View v, int hoursToSnooze);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setSelectedAction(int selectedAction) {
|
||||
if (mSelectedAction == selectedAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSelectedAction = selectedAction;
|
||||
onSelectedActionChanged();
|
||||
}
|
||||
|
||||
private void onSelectedActionChanged() {
|
||||
// If the user selected Priority, maybe show the priority onboarding
|
||||
if (mSelectedAction == ACTION_FAVORITE && shouldShowPriorityOnboarding()) {
|
||||
showPriorityOnboarding();
|
||||
}
|
||||
}
|
||||
|
||||
public void bindNotification(
|
||||
ShortcutManager shortcutManager,
|
||||
PackageManager pm,
|
||||
@@ -181,6 +206,8 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
OnSettingsClickListener onSettingsClick,
|
||||
OnSnoozeClickListener onSnoozeClickListener,
|
||||
ConversationIconFactory conversationIconFactory,
|
||||
Context userContext,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
|
||||
boolean isDeviceProvisioned) {
|
||||
mSelectedAction = -1;
|
||||
mINotificationManager = iNotificationManager;
|
||||
@@ -196,6 +223,9 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
mIsDeviceProvisioned = isDeviceProvisioned;
|
||||
mOnSnoozeClickListener = onSnoozeClickListener;
|
||||
mIconFactory = conversationIconFactory;
|
||||
mUserContext = userContext;
|
||||
mBubbleMetadata = entry.getBubbleMetadata();
|
||||
mBuilderProvider = builderProvider;
|
||||
|
||||
mShortcutManager = shortcutManager;
|
||||
mConversationId = mNotificationChannel.getConversationId();
|
||||
@@ -213,7 +243,7 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
try {
|
||||
mAppBubble = mINotificationManager.getBubblePreferenceForPackage(mPackageName, mAppUid);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "can't reach OS", e);
|
||||
Log.e(TAG, "can't reach OS", e);
|
||||
mAppBubble = BUBBLE_PREFERENCE_SELECTED;
|
||||
}
|
||||
|
||||
@@ -491,6 +521,38 @@ public class NotificationConversationInfo extends LinearLayout implements
|
||||
mAppUid, mSelectedAction, mNotificationChannel));
|
||||
}
|
||||
|
||||
private boolean shouldShowPriorityOnboarding() {
|
||||
return !Prefs.getBoolean(mUserContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING, false);
|
||||
}
|
||||
|
||||
private void showPriorityOnboarding() {
|
||||
View onboardingView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.priority_onboarding_half_shell, null);
|
||||
|
||||
boolean ignoreDnd = false;
|
||||
try {
|
||||
ignoreDnd = (mINotificationManager
|
||||
.getConsolidatedNotificationPolicy().priorityConversationSenders
|
||||
& NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT) != 0;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not check conversation senders", e);
|
||||
}
|
||||
|
||||
boolean showAsBubble = mBubbleMetadata.getAutoExpandBubble()
|
||||
&& Settings.Global.getInt(mContext.getContentResolver(),
|
||||
NOTIFICATION_BUBBLES, 0) == 1;
|
||||
|
||||
PriorityOnboardingDialogController controller = mBuilderProvider.get()
|
||||
.setContext(mUserContext)
|
||||
.setView(onboardingView)
|
||||
.setIgnoresDnd(ignoreDnd)
|
||||
.setShowsAsBubble(showAsBubble)
|
||||
.build();
|
||||
|
||||
controller.init();
|
||||
controller.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the controls and commits the updated importance values (indirectly).
|
||||
*
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.settings.CurrentUserContextTracker;
|
||||
import com.android.systemui.statusbar.NotificationLifetimeExtender;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
@@ -67,6 +68,8 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import dagger.Lazy;
|
||||
|
||||
/**
|
||||
@@ -111,6 +114,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
private final INotificationManager mNotificationManager;
|
||||
private final LauncherApps mLauncherApps;
|
||||
private final ShortcutManager mShortcutManager;
|
||||
private final CurrentUserContextTracker mContextTracker;
|
||||
private final Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
|
||||
|
||||
/**
|
||||
* Injected constructor. See {@link NotificationsModule}.
|
||||
@@ -121,7 +126,9 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
HighPriorityProvider highPriorityProvider,
|
||||
INotificationManager notificationManager,
|
||||
LauncherApps launcherApps,
|
||||
ShortcutManager shortcutManager) {
|
||||
ShortcutManager shortcutManager,
|
||||
CurrentUserContextTracker contextTracker,
|
||||
Provider<PriorityOnboardingDialogController.Builder> builderProvider) {
|
||||
mContext = context;
|
||||
mVisualStabilityManager = visualStabilityManager;
|
||||
mStatusBarLazy = statusBarLazy;
|
||||
@@ -131,6 +138,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
mNotificationManager = notificationManager;
|
||||
mLauncherApps = launcherApps;
|
||||
mShortcutManager = shortcutManager;
|
||||
mContextTracker = contextTracker;
|
||||
mBuilderProvider = builderProvider;
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter,
|
||||
@@ -403,6 +412,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
onSettingsClick,
|
||||
onSnoozeClickListener,
|
||||
iconFactoryLoader,
|
||||
mContextTracker.getCurrentUserContext(),
|
||||
mBuilderProvider,
|
||||
mDeviceProvisionedController.isDeviceProvisioned());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.PixelFormat
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
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.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.android.systemui.Prefs
|
||||
import com.android.systemui.R
|
||||
import java.lang.IllegalStateException
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Controller to handle presenting the priority conversations onboarding dialog
|
||||
*/
|
||||
class PriorityOnboardingDialogController @Inject constructor(
|
||||
val view: View,
|
||||
val context: Context,
|
||||
val ignoresDnd: Boolean,
|
||||
val showsAsBubble: Boolean
|
||||
) {
|
||||
|
||||
private lateinit var dialog: Dialog
|
||||
|
||||
fun init() {
|
||||
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, true)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
class Builder @Inject constructor() {
|
||||
private lateinit var view: View
|
||||
private lateinit var context: Context
|
||||
private var ignoresDnd = false
|
||||
private var showAsBubble = false
|
||||
|
||||
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 build(): PriorityOnboardingDialogController {
|
||||
val controller = PriorityOnboardingDialogController(
|
||||
view, context, ignoresDnd, showAsBubble)
|
||||
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()
|
||||
}
|
||||
|
||||
if (!ignoresDnd) {
|
||||
findViewById<LinearLayout>(R.id.ignore_dnd_tip).visibility = GONE
|
||||
}
|
||||
|
||||
if (!showsAsBubble) {
|
||||
findViewById<LinearLayout>(R.id.floating_bubble_tip).visibility = GONE
|
||||
}
|
||||
|
||||
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 = ChannelEditorDialogController::class.java.simpleName
|
||||
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
||||
fitInsetsTypes = attributes.fitInsetsTypes and statusBars().inv()
|
||||
width = MATCH_PARENT
|
||||
height = WRAP_CONTENT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val wmFlags = (WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
||||
or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
||||
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
|
||||
}
|
||||
@@ -16,15 +16,12 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static android.app.Notification.FLAG_BUBBLE;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
|
||||
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.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
|
||||
import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
|
||||
import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
@@ -38,8 +35,10 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -51,6 +50,7 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Person;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
@@ -61,20 +61,19 @@ import android.content.pm.ShortcutManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.settingslib.notification.ConversationIconFactory;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.bubbles.BubbleController;
|
||||
@@ -89,6 +88,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
@@ -99,6 +99,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
@@ -145,6 +147,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
private ShadeController mShadeController;
|
||||
@Mock
|
||||
private ConversationIconFactory mIconFactory;
|
||||
@Mock
|
||||
private Context mUserContext;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private PriorityOnboardingDialogController.Builder mBuilder;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider = () -> mBuilder;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -236,6 +243,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final ImageView view = mNotificationInfo.findViewById(R.id.conversation_icon);
|
||||
assertEquals(mIconDrawable, view.getDrawable());
|
||||
@@ -255,6 +264,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
|
||||
assertTrue(textView.getText().toString().contains("App Name"));
|
||||
@@ -300,6 +311,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
|
||||
assertTrue(textView.getText().toString().contains(group.getName()));
|
||||
@@ -321,6 +334,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
|
||||
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
|
||||
@@ -341,6 +356,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
|
||||
assertEquals(GONE, nameView.getVisibility());
|
||||
@@ -368,6 +385,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
|
||||
assertEquals(VISIBLE, nameView.getVisibility());
|
||||
@@ -391,6 +410,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
},
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
|
||||
@@ -412,6 +433,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
|
||||
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
|
||||
@@ -434,6 +457,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
},
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
false);
|
||||
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
|
||||
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
|
||||
@@ -454,6 +479,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
View view = mNotificationInfo.findViewById(R.id.silence);
|
||||
assertThat(view.isSelected()).isTrue();
|
||||
@@ -477,6 +504,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
View view = mNotificationInfo.findViewById(R.id.default_behavior);
|
||||
assertThat(view.isSelected()).isTrue();
|
||||
@@ -503,6 +532,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
View view = mNotificationInfo.findViewById(R.id.default_behavior);
|
||||
assertThat(view.isSelected()).isTrue();
|
||||
@@ -528,6 +559,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
View fave = mNotificationInfo.findViewById(R.id.priority);
|
||||
@@ -566,6 +599,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
|
||||
@@ -603,6 +638,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
View silence = mNotificationInfo.findViewById(R.id.silence);
|
||||
@@ -641,6 +678,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
View fave = mNotificationInfo.findViewById(R.id.priority);
|
||||
@@ -673,6 +712,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
View fave = mNotificationInfo.findViewById(R.id.priority);
|
||||
@@ -703,6 +744,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
|
||||
@@ -734,6 +777,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
|
||||
@@ -765,6 +810,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
|
||||
@@ -795,6 +842,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
View silence = mNotificationInfo.findViewById(R.id.silence);
|
||||
@@ -824,6 +873,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
verify(mMockINotificationManager, times(1)).createConversationNotificationChannelForPackage(
|
||||
@@ -844,9 +895,81 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
|
||||
anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPriorityPresentsOnboarding_firstTime() {
|
||||
// GIVEN pref is false
|
||||
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING, false);
|
||||
|
||||
// GIVEN the priority onboarding screen is present
|
||||
PriorityOnboardingDialogController.Builder b =
|
||||
new PriorityOnboardingDialogController.Builder();
|
||||
PriorityOnboardingDialogController controller =
|
||||
mock(PriorityOnboardingDialogController.class);
|
||||
when(b.build()).thenReturn(controller);
|
||||
|
||||
// GIVEN the user is changing conversation settings
|
||||
when(mBuilderProvider.get()).thenReturn(b);
|
||||
mNotificationInfo.bindNotification(
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mMockINotificationManager,
|
||||
mVisualStabilityManager,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
// WHEN user clicks "priority"
|
||||
mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
|
||||
|
||||
// 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, true);
|
||||
|
||||
PriorityOnboardingDialogController.Builder b =
|
||||
new PriorityOnboardingDialogController.Builder();
|
||||
PriorityOnboardingDialogController controller =
|
||||
mock(PriorityOnboardingDialogController.class);
|
||||
when(b.build()).thenReturn(controller);
|
||||
|
||||
when(mBuilderProvider.get()).thenReturn(b);
|
||||
mNotificationInfo.bindNotification(
|
||||
mShortcutManager,
|
||||
mMockPackageManager,
|
||||
mMockINotificationManager,
|
||||
mVisualStabilityManager,
|
||||
TEST_PACKAGE_NAME,
|
||||
mNotificationChannel,
|
||||
mEntry,
|
||||
null,
|
||||
null,
|
||||
mIconFactory,
|
||||
mUserContext,
|
||||
mBuilderProvider,
|
||||
true);
|
||||
|
||||
// WHEN user clicks "priority"
|
||||
mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
|
||||
|
||||
// THEN the user is presented with the priority onboarding screen
|
||||
verify(controller, never()).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.settings.CurrentUserContextTracker;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
@@ -83,11 +84,14 @@ import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* Tests for {@link NotificationGutsManager}.
|
||||
*/
|
||||
@@ -120,6 +124,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
@Mock private LauncherApps mLauncherApps;
|
||||
@Mock private ShortcutManager mShortcutManager;
|
||||
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
@Mock private CurrentUserContextTracker mContextTracker;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private PriorityOnboardingDialogController.Builder mBuilder;
|
||||
private Provider<PriorityOnboardingDialogController.Builder> mProvider = () -> mBuilder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -136,7 +144,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
|
||||
mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
|
||||
() -> mStatusBar, mHandler, mAccessibilityManager, mHighPriorityProvider,
|
||||
mINotificationManager, mLauncherApps, mShortcutManager);
|
||||
mINotificationManager, mLauncherApps, mShortcutManager, mContextTracker, mProvider);
|
||||
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
|
||||
mCheckSaveListener, mOnSettingsClickListener);
|
||||
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
|
||||
|
||||
Reference in New Issue
Block a user