blob: f543db74d91aa7117794a056088efe4595b99a24 [file] [log] [blame]
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.notification.row;
18
Julia Reynolds8d257092020-04-15 15:57:21 -040019import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
Mady Mellora92268c2020-03-09 17:25:08 -070020import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
21import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050022import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
23import static android.app.NotificationManager.IMPORTANCE_LOW;
24import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Evan Laird31ca5472020-04-08 17:45:24 -040025import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050026
Julia Reynoldsa856e492020-03-18 17:30:06 -040027import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
28
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050029import static java.lang.annotation.RetentionPolicy.SOURCE;
30
31import android.annotation.IntDef;
32import android.annotation.NonNull;
Evan Laird03c44452020-04-16 12:26:07 -040033import android.annotation.Nullable;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050034import android.app.INotificationManager;
35import android.app.Notification;
36import android.app.NotificationChannel;
37import android.app.NotificationChannelGroup;
Julia Reynolds8d257092020-04-15 15:57:21 -040038import android.app.NotificationManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050039import android.content.Context;
40import android.content.Intent;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050041import android.content.pm.ApplicationInfo;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050042import android.content.pm.PackageManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050043import android.content.pm.ShortcutInfo;
44import android.content.pm.ShortcutManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050045import android.os.Handler;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050046import android.os.RemoteException;
Julia Reynoldsc5356502020-06-08 16:14:58 -040047import android.os.UserHandle;
Evan Laird31ca5472020-04-08 17:45:24 -040048import android.provider.Settings;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050049import android.service.notification.StatusBarNotification;
50import android.text.TextUtils;
Julia Reynoldsa856e492020-03-18 17:30:06 -040051import android.transition.ChangeBounds;
52import android.transition.Fade;
53import android.transition.TransitionManager;
54import android.transition.TransitionSet;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050055import android.util.AttributeSet;
56import android.util.Log;
Evan Laird31ca5472020-04-08 17:45:24 -040057import android.view.LayoutInflater;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050058import android.view.View;
59import android.view.accessibility.AccessibilityEvent;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050060import android.widget.ImageView;
61import android.widget.LinearLayout;
62import android.widget.TextView;
63
64import com.android.internal.annotations.VisibleForTesting;
Julia Reynolds01c9da42020-02-14 14:17:58 -050065import com.android.settingslib.notification.ConversationIconFactory;
Evan Laird31ca5472020-04-08 17:45:24 -040066import com.android.systemui.Prefs;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050067import com.android.systemui.R;
Lyn Hanb5397972020-06-16 11:56:43 -070068import com.android.systemui.bubbles.BubbleController;
Steve Elliott6771f542020-05-26 13:31:10 -040069import com.android.systemui.dagger.qualifiers.Background;
70import com.android.systemui.dagger.qualifiers.Main;
Mady Mellor9adfe6a2020-03-30 17:23:26 -070071import com.android.systemui.statusbar.notification.NotificationChannelHelper;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050072import com.android.systemui.statusbar.notification.VisualStabilityManager;
73import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Steve Elliott6771f542020-05-26 13:31:10 -040074import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050075
76import java.lang.annotation.Retention;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050077
Evan Laird31ca5472020-04-08 17:45:24 -040078import javax.inject.Provider;
79
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050080/**
81 * The guts of a conversation notification revealed when performing a long press.
82 */
83public class NotificationConversationInfo extends LinearLayout implements
84 NotificationGuts.GutsContent {
85 private static final String TAG = "ConversationGuts";
86
87
88 private INotificationManager mINotificationManager;
Steve Elliott6771f542020-05-26 13:31:10 -040089 private ShortcutManager mShortcutManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050090 private PackageManager mPm;
Julia Reynolds01c9da42020-02-14 14:17:58 -050091 private ConversationIconFactory mIconFactory;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -040092 private VisualStabilityManager mVisualStabilityManager;
Steve Elliott6771f542020-05-26 13:31:10 -040093 private Handler mMainHandler;
94 private Handler mBgHandler;
Lyn Hanb5397972020-06-16 11:56:43 -070095 private BubbleController mBubbleController;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050096 private String mPackageName;
97 private String mAppName;
98 private int mAppUid;
99 private String mDelegatePkg;
100 private NotificationChannel mNotificationChannel;
101 private ShortcutInfo mShortcutInfo;
Steve Elliott6771f542020-05-26 13:31:10 -0400102 private NotificationEntry mEntry;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500103 private StatusBarNotification mSbn;
Evan Laird03c44452020-04-16 12:26:07 -0400104 @Nullable private Notification.BubbleMetadata mBubbleMetadata;
Evan Laird31ca5472020-04-08 17:45:24 -0400105 private Context mUserContext;
106 private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500107 private boolean mIsDeviceProvisioned;
Julia Reynolds8d257092020-04-15 15:57:21 -0400108 private int mAppBubble;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500109
Julia Reynoldsa856e492020-03-18 17:30:06 -0400110 private TextView mPriorityDescriptionView;
111 private TextView mDefaultDescriptionView;
112 private TextView mSilentDescriptionView;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400113
Julia Reynoldse6fed502020-02-07 14:41:02 -0500114 private @Action int mSelectedAction = -1;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400115 private boolean mPressedApply;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500116
117 private OnSnoozeClickListener mOnSnoozeClickListener;
118 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500119 private NotificationGuts mGutsContainer;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400120 private OnConversationSettingsClickListener mOnConversationSettingsClickListener;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500121
122 @VisibleForTesting
123 boolean mSkipPost = false;
Selim Cineka5a4ee42020-05-21 15:38:32 -0700124 private int mActualHeight;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500125
Julia Reynoldse6fed502020-02-07 14:41:02 -0500126 @Retention(SOURCE)
Julia Reynoldsa856e492020-03-18 17:30:06 -0400127 @IntDef({ACTION_DEFAULT, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
128 ACTION_SETTINGS})
Julia Reynoldse6fed502020-02-07 14:41:02 -0500129 private @interface Action {}
Julia Reynoldsa856e492020-03-18 17:30:06 -0400130 static final int ACTION_DEFAULT = 0;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500131 static final int ACTION_HOME = 1;
132 static final int ACTION_FAVORITE = 2;
133 static final int ACTION_SNOOZE = 3;
134 static final int ACTION_MUTE = 4;
135 static final int ACTION_SETTINGS = 5;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500136
Julia Reynoldsa856e492020-03-18 17:30:06 -0400137 // TODO: b/152050825
138 /*
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500139 private OnClickListener mOnHomeClick = v -> {
140 mSelectedAction = ACTION_HOME;
141 mShortcutManager.requestPinShortcut(mShortcutInfo, null);
Julia Reynoldse6fed502020-02-07 14:41:02 -0500142 mShadeController.animateCollapsePanels();
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400143 mGutsContainer.closeControls(v, true);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500144 };
145
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500146 private OnClickListener mOnSnoozeClick = v -> {
147 mSelectedAction = ACTION_SNOOZE;
148 mOnSnoozeClickListener.onClick(v, 1);
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400149 mGutsContainer.closeControls(v, true);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500150 };
Julia Reynoldsa856e492020-03-18 17:30:06 -0400151 */
152
153 private OnClickListener mOnFavoriteClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400154 setSelectedAction(ACTION_FAVORITE);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400155 updateToggleActions(mSelectedAction, true);
156 };
157
158 private OnClickListener mOnDefaultClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400159 setSelectedAction(ACTION_DEFAULT);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400160 updateToggleActions(mSelectedAction, true);
161 };
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500162
163 private OnClickListener mOnMuteClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400164 setSelectedAction(ACTION_MUTE);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400165 updateToggleActions(mSelectedAction, true);
166 };
167
168 private OnClickListener mOnDone = v -> {
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400169 mPressedApply = true;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400170 // If the user selected Priority, maybe show the priority onboarding
171 if (mSelectedAction == ACTION_FAVORITE && shouldShowPriorityOnboarding()) {
172 showPriorityOnboarding();
173 }
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400174 mGutsContainer.closeControls(v, true);
Julia Reynoldsdcd70d62020-01-15 10:33:43 -0500175 };
176
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500177 public NotificationConversationInfo(Context context, AttributeSet attrs) {
178 super(context, attrs);
179 }
180
181 public interface OnSettingsClickListener {
182 void onClick(View v, NotificationChannel channel, int appUid);
183 }
184
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400185 public interface OnConversationSettingsClickListener {
186 void onClick();
187 }
188
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500189 public interface OnAppSettingsClickListener {
190 void onClick(View v, Intent intent);
191 }
192
193 public interface OnSnoozeClickListener {
194 void onClick(View v, int hoursToSnooze);
195 }
196
Evan Laird31ca5472020-04-08 17:45:24 -0400197 @VisibleForTesting
198 void setSelectedAction(int selectedAction) {
199 if (mSelectedAction == selectedAction) {
200 return;
201 }
202
203 mSelectedAction = selectedAction;
Evan Laird31ca5472020-04-08 17:45:24 -0400204 }
205
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500206 public void bindNotification(
207 ShortcutManager shortcutManager,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500208 PackageManager pm,
209 INotificationManager iNotificationManager,
210 VisualStabilityManager visualStabilityManager,
211 String pkg,
212 NotificationChannel notificationChannel,
213 NotificationEntry entry,
Evan Laird03c44452020-04-16 12:26:07 -0400214 Notification.BubbleMetadata bubbleMetadata,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500215 OnSettingsClickListener onSettingsClick,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500216 OnSnoozeClickListener onSnoozeClickListener,
Julia Reynolds01c9da42020-02-14 14:17:58 -0500217 ConversationIconFactory conversationIconFactory,
Evan Laird31ca5472020-04-08 17:45:24 -0400218 Context userContext,
219 Provider<PriorityOnboardingDialogController.Builder> builderProvider,
Steve Elliott6771f542020-05-26 13:31:10 -0400220 boolean isDeviceProvisioned,
221 @Main Handler mainHandler,
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400222 @Background Handler bgHandler,
Lyn Hanb5397972020-06-16 11:56:43 -0700223 OnConversationSettingsClickListener onConversationSettingsClickListener,
224 BubbleController bubbleController) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500225 mSelectedAction = -1;
226 mINotificationManager = iNotificationManager;
227 mVisualStabilityManager = visualStabilityManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500228 mPackageName = pkg;
Steve Elliott6771f542020-05-26 13:31:10 -0400229 mEntry = entry;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500230 mSbn = entry.getSbn();
231 mPm = pm;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500232 mAppName = mPackageName;
233 mOnSettingsClickListener = onSettingsClick;
234 mNotificationChannel = notificationChannel;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500235 mAppUid = mSbn.getUid();
236 mDelegatePkg = mSbn.getOpPkg();
237 mIsDeviceProvisioned = isDeviceProvisioned;
238 mOnSnoozeClickListener = onSnoozeClickListener;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400239 mOnConversationSettingsClickListener = onConversationSettingsClickListener;
Julia Reynolds01c9da42020-02-14 14:17:58 -0500240 mIconFactory = conversationIconFactory;
Evan Laird31ca5472020-04-08 17:45:24 -0400241 mUserContext = userContext;
Evan Laird03c44452020-04-16 12:26:07 -0400242 mBubbleMetadata = bubbleMetadata;
Lyn Hanb5397972020-06-16 11:56:43 -0700243 mBubbleController = bubbleController;
Evan Laird31ca5472020-04-08 17:45:24 -0400244 mBuilderProvider = builderProvider;
Steve Elliott6771f542020-05-26 13:31:10 -0400245 mMainHandler = mainHandler;
246 mBgHandler = bgHandler;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500247 mShortcutManager = shortcutManager;
Julia Reynolds8582df52020-04-24 18:30:59 -0400248 mShortcutInfo = entry.getRanking().getShortcutInfo();
249 if (mShortcutInfo == null) {
Julia Reynolds7c267522020-01-16 11:26:41 -0500250 throw new IllegalArgumentException("Does not have required information");
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500251 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500252
Mady Mellor9adfe6a2020-03-30 17:23:26 -0700253 mNotificationChannel = NotificationChannelHelper.createConversationChannelIfNeeded(
254 getContext(), mINotificationManager, entry, mNotificationChannel);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500255
Julia Reynolds8d257092020-04-15 15:57:21 -0400256 try {
257 mAppBubble = mINotificationManager.getBubblePreferenceForPackage(mPackageName, mAppUid);
258 } catch (RemoteException e) {
Evan Laird31ca5472020-04-08 17:45:24 -0400259 Log.e(TAG, "can't reach OS", e);
Julia Reynolds8d257092020-04-15 15:57:21 -0400260 mAppBubble = BUBBLE_PREFERENCE_SELECTED;
261 }
262
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500263 bindHeader();
264 bindActions();
265
Julia Reynoldsa856e492020-03-18 17:30:06 -0400266 View done = findViewById(R.id.done);
267 done.setOnClickListener(mOnDone);
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400268 done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500269 }
270
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500271 private void bindActions() {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500272
Julia Reynoldsa856e492020-03-18 17:30:06 -0400273 // TODO: b/152050825
274 /*
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500275 Button home = findViewById(R.id.home);
276 home.setOnClickListener(mOnHomeClick);
Julia Reynoldse6fed502020-02-07 14:41:02 -0500277 home.setVisibility(mShortcutInfo != null
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500278 && mShortcutManager.isRequestPinShortcutSupported()
279 ? VISIBLE : GONE);
280
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500281 Button snooze = findViewById(R.id.snooze);
282 snooze.setOnClickListener(mOnSnoozeClick);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400283 */
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500284
Julia Reynolds8d257092020-04-15 15:57:21 -0400285 if (mAppBubble == BUBBLE_PREFERENCE_ALL) {
286 ((TextView) findViewById(R.id.default_summary)).setText(getResources().getString(
287 R.string.notification_channel_summary_default_with_bubbles, mAppName));
288 }
289
Julia Reynoldsa856e492020-03-18 17:30:06 -0400290 findViewById(R.id.priority).setOnClickListener(mOnFavoriteClick);
291 findViewById(R.id.default_behavior).setOnClickListener(mOnDefaultClick);
292 findViewById(R.id.silence).setOnClickListener(mOnMuteClick);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500293
Julia Reynoldse6fed502020-02-07 14:41:02 -0500294 final View settingsButton = findViewById(R.id.info);
295 settingsButton.setOnClickListener(getSettingsOnClickListener());
296 settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
297
Julia Reynoldsa856e492020-03-18 17:30:06 -0400298 updateToggleActions(getSelectedAction(), false);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500299 }
300
301 private void bindHeader() {
302 bindConversationDetails();
303
304 // Delegate
305 bindDelegate();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500306 }
307
308 private OnClickListener getSettingsOnClickListener() {
309 if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
310 final int appUidF = mAppUid;
311 return ((View view) -> {
312 mOnSettingsClickListener.onClick(view, mNotificationChannel, appUidF);
313 });
314 }
315 return null;
316 }
317
318 private void bindConversationDetails() {
319 final TextView channelName = findViewById(R.id.parent_channel_name);
320 channelName.setText(mNotificationChannel.getName());
321
322 bindGroup();
Julia Reynoldsf2acd602020-01-21 16:01:25 -0500323 // TODO: bring back when channel name does not include name
324 // bindName();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500325 bindPackage();
Julia Reynoldsa856e492020-03-18 17:30:06 -0400326 bindIcon(mNotificationChannel.isImportantConversation());
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500327 }
328
Julia Reynoldsa856e492020-03-18 17:30:06 -0400329 private void bindIcon(boolean important) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500330 ImageView image = findViewById(R.id.conversation_icon);
Julia Reynolds8582df52020-04-24 18:30:59 -0400331 image.setImageDrawable(mIconFactory.getConversationDrawable(
332 mShortcutInfo, mPackageName, mAppUid, important));
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500333 }
334
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500335 private void bindPackage() {
336 ApplicationInfo info;
337 try {
338 info = mPm.getApplicationInfo(
339 mPackageName,
340 PackageManager.MATCH_UNINSTALLED_PACKAGES
341 | PackageManager.MATCH_DISABLED_COMPONENTS
342 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
343 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
344 if (info != null) {
345 mAppName = String.valueOf(mPm.getApplicationLabel(info));
346 }
347 } catch (PackageManager.NameNotFoundException e) {
348 }
349 ((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
350 }
351
352 private void bindDelegate() {
353 TextView delegateView = findViewById(R.id.delegate_name);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500354
355 if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
356 // this notification was posted by a delegate!
357 delegateView.setVisibility(View.VISIBLE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500358 } else {
359 delegateView.setVisibility(View.GONE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500360 }
361 }
362
363 private void bindGroup() {
364 // Set group information if this channel has an associated group.
365 CharSequence groupName = null;
366 if (mNotificationChannel != null && mNotificationChannel.getGroup() != null) {
367 try {
368 final NotificationChannelGroup notificationChannelGroup =
369 mINotificationManager.getNotificationChannelGroupForPackage(
370 mNotificationChannel.getGroup(), mPackageName, mAppUid);
371 if (notificationChannelGroup != null) {
372 groupName = notificationChannelGroup.getName();
373 }
374 } catch (RemoteException e) {
375 }
376 }
377 TextView groupNameView = findViewById(R.id.group_name);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500378 if (groupName != null) {
379 groupNameView.setText(groupName);
380 groupNameView.setVisibility(VISIBLE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500381 } else {
382 groupNameView.setVisibility(GONE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500383 }
384 }
385
386 @Override
387 public boolean post(Runnable action) {
388 if (mSkipPost) {
389 action.run();
390 return true;
391 } else {
392 return super.post(action);
393 }
394 }
395
396 @Override
Julia Reynoldsa856e492020-03-18 17:30:06 -0400397 protected void onFinishInflate() {
398 super.onFinishInflate();
399
400 mPriorityDescriptionView = findViewById(R.id.priority_summary);
401 mDefaultDescriptionView = findViewById(R.id.default_summary);
402 mSilentDescriptionView = findViewById(R.id.silence_summary);
403 }
404
405 @Override
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500406 public void onFinishedClosing() {
407 // TODO: do we need to do anything here?
408 }
409
410 @Override
Julia Reynoldsbe371072020-05-28 11:32:01 -0400411 public boolean needsFalsingProtection() {
412 return true;
413 }
414
415 @Override
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500416 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
417 super.onInitializeAccessibilityEvent(event);
418 if (mGutsContainer != null &&
419 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
420 if (mGutsContainer.isExposed()) {
421 event.getText().add(mContext.getString(
422 R.string.notification_channel_controls_opened_accessibility, mAppName));
423 } else {
424 event.getText().add(mContext.getString(
425 R.string.notification_channel_controls_closed_accessibility, mAppName));
426 }
427 }
428 }
429
Julia Reynoldsa856e492020-03-18 17:30:06 -0400430 private void updateToggleActions(int selectedAction, boolean userTriggered) {
431 if (userTriggered) {
432 TransitionSet transition = new TransitionSet();
433 transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
434 transition.addTransition(new Fade(Fade.OUT))
435 .addTransition(new ChangeBounds())
436 .addTransition(
437 new Fade(Fade.IN)
438 .setStartDelay(150)
439 .setDuration(200)
440 .setInterpolator(FAST_OUT_SLOW_IN));
441 transition.setDuration(350);
442 transition.setInterpolator(FAST_OUT_SLOW_IN);
443 TransitionManager.beginDelayedTransition(this, transition);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500444 }
Julia Reynoldse6fed502020-02-07 14:41:02 -0500445
Julia Reynoldsa856e492020-03-18 17:30:06 -0400446 View priority = findViewById(R.id.priority);
447 View defaultBehavior = findViewById(R.id.default_behavior);
448 View silence = findViewById(R.id.silence);
449
450 switch (selectedAction) {
451 case ACTION_FAVORITE:
452 mPriorityDescriptionView.setVisibility(VISIBLE);
453 mDefaultDescriptionView.setVisibility(GONE);
454 mSilentDescriptionView.setVisibility(GONE);
455 post(() -> {
456 priority.setSelected(true);
457 defaultBehavior.setSelected(false);
458 silence.setSelected(false);
459 });
460 break;
461
462 case ACTION_MUTE:
463 mSilentDescriptionView.setVisibility(VISIBLE);
464 mDefaultDescriptionView.setVisibility(GONE);
465 mPriorityDescriptionView.setVisibility(GONE);
466 post(() -> {
467 priority.setSelected(false);
468 defaultBehavior.setSelected(false);
469 silence.setSelected(true);
470 });
471 break;
472
473 case ACTION_DEFAULT:
474 mDefaultDescriptionView.setVisibility(VISIBLE);
475 mSilentDescriptionView.setVisibility(GONE);
476 mPriorityDescriptionView.setVisibility(GONE);
477 post(() -> {
478 priority.setSelected(false);
479 defaultBehavior.setSelected(true);
480 silence.setSelected(false);
481 });
482 break;
483
484 default:
485 throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500486 }
Dan Sandlerb11f2de2020-02-19 13:18:24 -0500487
Julia Reynoldsa856e492020-03-18 17:30:06 -0400488 boolean isAChange = getSelectedAction() != selectedAction;
489 TextView done = findViewById(R.id.done);
490 done.setText(isAChange
491 ? R.string.inline_ok_button
492 : R.string.inline_done_button);
493
Dan Sandlerb11f2de2020-02-19 13:18:24 -0500494 // update icon in case importance has changed
Julia Reynoldsa856e492020-03-18 17:30:06 -0400495 bindIcon(selectedAction == ACTION_FAVORITE);
496 }
497
498 int getSelectedAction() {
499 if (mNotificationChannel.getImportance() <= IMPORTANCE_LOW
500 && mNotificationChannel.getImportance() > IMPORTANCE_UNSPECIFIED) {
501 return ACTION_MUTE;
502 } else {
503 if (mNotificationChannel.isImportantConversation()) {
504 return ACTION_FAVORITE;
505 }
506 }
507 return ACTION_DEFAULT;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500508 }
509
510 private void updateChannel() {
Steve Elliott6771f542020-05-26 13:31:10 -0400511 mBgHandler.post(
Julia Reynoldse6fed502020-02-07 14:41:02 -0500512 new UpdateChannelRunnable(mINotificationManager, mPackageName,
513 mAppUid, mSelectedAction, mNotificationChannel));
Steve Elliott8b4929d2020-06-02 13:38:04 -0400514 mEntry.markForUserTriggeredMovement(true);
515 mMainHandler.postDelayed(
516 mVisualStabilityManager::temporarilyAllowReordering,
517 StackStateAnimator.ANIMATION_DURATION_STANDARD);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500518 }
519
Evan Laird31ca5472020-04-08 17:45:24 -0400520 private boolean shouldShowPriorityOnboarding() {
521 return !Prefs.getBoolean(mUserContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING, false);
522 }
523
524 private void showPriorityOnboarding() {
525 View onboardingView = LayoutInflater.from(mContext)
526 .inflate(R.layout.priority_onboarding_half_shell, null);
527
528 boolean ignoreDnd = false;
529 try {
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400530 ignoreDnd = mINotificationManager
531 .getConsolidatedNotificationPolicy().priorityConversationSenders ==
532 NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
Evan Laird31ca5472020-04-08 17:45:24 -0400533 } catch (RemoteException e) {
534 Log.e(TAG, "Could not check conversation senders", e);
535 }
536
Evan Laird03c44452020-04-16 12:26:07 -0400537 boolean showAsBubble = mBubbleMetadata != null
538 && mBubbleMetadata.getAutoExpandBubble()
Evan Laird31ca5472020-04-08 17:45:24 -0400539 && Settings.Global.getInt(mContext.getContentResolver(),
540 NOTIFICATION_BUBBLES, 0) == 1;
541
542 PriorityOnboardingDialogController controller = mBuilderProvider.get()
543 .setContext(mUserContext)
544 .setView(onboardingView)
545 .setIgnoresDnd(ignoreDnd)
546 .setShowsAsBubble(showAsBubble)
Julia Reynoldsc5356502020-06-08 16:14:58 -0400547 .setIcon(mIconFactory.getBaseIconDrawable(mShortcutInfo))
548 .setBadge(mIconFactory.getAppBadge(
549 mPackageName, UserHandle.getUserId(mSbn.getUid())))
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400550 .setOnSettingsClick(mOnConversationSettingsClickListener)
Evan Laird31ca5472020-04-08 17:45:24 -0400551 .build();
552
553 controller.init();
554 controller.show();
555 }
556
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500557 @Override
558 public void setGutsParent(NotificationGuts guts) {
559 mGutsContainer = guts;
560 }
561
562 @Override
563 public boolean willBeRemoved() {
564 return false;
565 }
566
567 @Override
568 public boolean shouldBeSaved() {
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400569 return mPressedApply;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500570 }
571
572 @Override
573 public View getContentView() {
574 return this;
575 }
576
577 @Override
578 public boolean handleCloseControls(boolean save, boolean force) {
579 if (save && mSelectedAction > -1) {
Julia Reynoldse6fed502020-02-07 14:41:02 -0500580 updateChannel();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500581 }
582 return false;
583 }
584
585 @Override
586 public int getActualHeight() {
Selim Cineka5a4ee42020-05-21 15:38:32 -0700587 // Because we're animating the bounds, getHeight will return the small height at the
588 // beginning of the animation. Instead we'd want it to already return the end value
589 return mActualHeight;
590 }
591
592 @Override
593 protected void onLayout(boolean changed, int l, int t, int r, int b) {
594 super.onLayout(changed, l, t, r, b);
595 mActualHeight = getHeight();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500596 }
597
598 @VisibleForTesting
599 public boolean isAnimating() {
600 return false;
601 }
602
Julia Reynoldse6fed502020-02-07 14:41:02 -0500603 class UpdateChannelRunnable implements Runnable {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500604
605 private final INotificationManager mINotificationManager;
606 private final String mAppPkg;
607 private final int mAppUid;
608 private NotificationChannel mChannelToUpdate;
609 private final @Action int mAction;
610
611 public UpdateChannelRunnable(INotificationManager notificationManager,
612 String packageName, int appUid, @Action int action,
613 @NonNull NotificationChannel channelToUpdate) {
614 mINotificationManager = notificationManager;
615 mAppPkg = packageName;
616 mAppUid = appUid;
617 mChannelToUpdate = channelToUpdate;
618 mAction = action;
619 }
620
621 @Override
622 public void run() {
623 try {
624 switch (mAction) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500625 case ACTION_FAVORITE:
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400626 mChannelToUpdate.setImportantConversation(true);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400627 if (mChannelToUpdate.isImportantConversation()) {
Julia Reynolds908201e2020-02-17 21:53:49 -0500628 mChannelToUpdate.setAllowBubbles(true);
Julia Reynolds8d257092020-04-15 15:57:21 -0400629 if (mAppBubble == BUBBLE_PREFERENCE_NONE) {
Mady Mellora92268c2020-03-09 17:25:08 -0700630 mINotificationManager.setBubblesAllowed(mAppPkg, mAppUid,
631 BUBBLE_PREFERENCE_SELECTED);
632 }
Lyn Hanb5397972020-06-16 11:56:43 -0700633 post(() -> {
634 mBubbleController.onUserChangedImportance(mEntry);
635 });
Julia Reynolds908201e2020-02-17 21:53:49 -0500636 }
Julia Reynoldsa856e492020-03-18 17:30:06 -0400637 mChannelToUpdate.setImportance(Math.max(
638 mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
639 break;
640 case ACTION_DEFAULT:
641 mChannelToUpdate.setImportance(Math.max(
642 mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
643 if (mChannelToUpdate.isImportantConversation()) {
644 mChannelToUpdate.setImportantConversation(false);
645 mChannelToUpdate.setAllowBubbles(false);
646 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500647 break;
648 case ACTION_MUTE:
649 if (mChannelToUpdate.getImportance() == IMPORTANCE_UNSPECIFIED
650 || mChannelToUpdate.getImportance() >= IMPORTANCE_DEFAULT) {
651 mChannelToUpdate.setImportance(IMPORTANCE_LOW);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400652 }
653 if (mChannelToUpdate.isImportantConversation()) {
654 mChannelToUpdate.setImportantConversation(false);
655 mChannelToUpdate.setAllowBubbles(false);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500656 }
657 break;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500658 }
659
Julia Reynoldsa856e492020-03-18 17:30:06 -0400660 mINotificationManager.updateNotificationChannelForPackage(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500661 mAppPkg, mAppUid, mChannelToUpdate);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500662 } catch (RemoteException e) {
663 Log.e(TAG, "Unable to update notification channel", e);
664 }
665 }
666 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500667}