blob: bee2f7002823b614870c4637fb4978bb06b7c411 [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;
Steve Elliott6771f542020-05-26 13:31:10 -040068import com.android.systemui.dagger.qualifiers.Background;
69import com.android.systemui.dagger.qualifiers.Main;
Mady Mellor9adfe6a2020-03-30 17:23:26 -070070import com.android.systemui.statusbar.notification.NotificationChannelHelper;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050071import com.android.systemui.statusbar.notification.VisualStabilityManager;
72import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Steve Elliott6771f542020-05-26 13:31:10 -040073import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050074
75import java.lang.annotation.Retention;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050076
Evan Laird31ca5472020-04-08 17:45:24 -040077import javax.inject.Provider;
78
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050079/**
80 * The guts of a conversation notification revealed when performing a long press.
81 */
82public class NotificationConversationInfo extends LinearLayout implements
83 NotificationGuts.GutsContent {
84 private static final String TAG = "ConversationGuts";
85
86
87 private INotificationManager mINotificationManager;
Steve Elliott6771f542020-05-26 13:31:10 -040088 private ShortcutManager mShortcutManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050089 private PackageManager mPm;
Julia Reynolds01c9da42020-02-14 14:17:58 -050090 private ConversationIconFactory mIconFactory;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -040091 private VisualStabilityManager mVisualStabilityManager;
Steve Elliott6771f542020-05-26 13:31:10 -040092 private Handler mMainHandler;
93 private Handler mBgHandler;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -050094
95 private String mPackageName;
96 private String mAppName;
97 private int mAppUid;
98 private String mDelegatePkg;
99 private NotificationChannel mNotificationChannel;
100 private ShortcutInfo mShortcutInfo;
Steve Elliott6771f542020-05-26 13:31:10 -0400101 private NotificationEntry mEntry;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500102 private StatusBarNotification mSbn;
Evan Laird03c44452020-04-16 12:26:07 -0400103 @Nullable private Notification.BubbleMetadata mBubbleMetadata;
Evan Laird31ca5472020-04-08 17:45:24 -0400104 private Context mUserContext;
105 private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500106 private boolean mIsDeviceProvisioned;
Julia Reynolds8d257092020-04-15 15:57:21 -0400107 private int mAppBubble;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500108
Julia Reynoldsa856e492020-03-18 17:30:06 -0400109 private TextView mPriorityDescriptionView;
110 private TextView mDefaultDescriptionView;
111 private TextView mSilentDescriptionView;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400112
Julia Reynoldse6fed502020-02-07 14:41:02 -0500113 private @Action int mSelectedAction = -1;
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400114 private boolean mPressedApply;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500115
116 private OnSnoozeClickListener mOnSnoozeClickListener;
117 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500118 private NotificationGuts mGutsContainer;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400119 private OnConversationSettingsClickListener mOnConversationSettingsClickListener;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500120
121 @VisibleForTesting
122 boolean mSkipPost = false;
Selim Cineka5a4ee42020-05-21 15:38:32 -0700123 private int mActualHeight;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500124
Julia Reynoldse6fed502020-02-07 14:41:02 -0500125 @Retention(SOURCE)
Julia Reynoldsa856e492020-03-18 17:30:06 -0400126 @IntDef({ACTION_DEFAULT, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
127 ACTION_SETTINGS})
Julia Reynoldse6fed502020-02-07 14:41:02 -0500128 private @interface Action {}
Julia Reynoldsa856e492020-03-18 17:30:06 -0400129 static final int ACTION_DEFAULT = 0;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500130 static final int ACTION_HOME = 1;
131 static final int ACTION_FAVORITE = 2;
132 static final int ACTION_SNOOZE = 3;
133 static final int ACTION_MUTE = 4;
134 static final int ACTION_SETTINGS = 5;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500135
Julia Reynoldsa856e492020-03-18 17:30:06 -0400136 // TODO: b/152050825
137 /*
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500138 private OnClickListener mOnHomeClick = v -> {
139 mSelectedAction = ACTION_HOME;
140 mShortcutManager.requestPinShortcut(mShortcutInfo, null);
Julia Reynoldse6fed502020-02-07 14:41:02 -0500141 mShadeController.animateCollapsePanels();
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400142 mGutsContainer.closeControls(v, true);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500143 };
144
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500145 private OnClickListener mOnSnoozeClick = v -> {
146 mSelectedAction = ACTION_SNOOZE;
147 mOnSnoozeClickListener.onClick(v, 1);
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400148 mGutsContainer.closeControls(v, true);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500149 };
Julia Reynoldsa856e492020-03-18 17:30:06 -0400150 */
151
152 private OnClickListener mOnFavoriteClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400153 setSelectedAction(ACTION_FAVORITE);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400154 updateToggleActions(mSelectedAction, true);
155 };
156
157 private OnClickListener mOnDefaultClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400158 setSelectedAction(ACTION_DEFAULT);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400159 updateToggleActions(mSelectedAction, true);
160 };
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500161
162 private OnClickListener mOnMuteClick = v -> {
Evan Laird31ca5472020-04-08 17:45:24 -0400163 setSelectedAction(ACTION_MUTE);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400164 updateToggleActions(mSelectedAction, true);
165 };
166
167 private OnClickListener mOnDone = v -> {
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400168 mPressedApply = true;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400169 // If the user selected Priority, maybe show the priority onboarding
170 if (mSelectedAction == ACTION_FAVORITE && shouldShowPriorityOnboarding()) {
171 showPriorityOnboarding();
172 }
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400173 mGutsContainer.closeControls(v, true);
Julia Reynoldsdcd70d62020-01-15 10:33:43 -0500174 };
175
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500176 public NotificationConversationInfo(Context context, AttributeSet attrs) {
177 super(context, attrs);
178 }
179
180 public interface OnSettingsClickListener {
181 void onClick(View v, NotificationChannel channel, int appUid);
182 }
183
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400184 public interface OnConversationSettingsClickListener {
185 void onClick();
186 }
187
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500188 public interface OnAppSettingsClickListener {
189 void onClick(View v, Intent intent);
190 }
191
192 public interface OnSnoozeClickListener {
193 void onClick(View v, int hoursToSnooze);
194 }
195
Evan Laird31ca5472020-04-08 17:45:24 -0400196 @VisibleForTesting
197 void setSelectedAction(int selectedAction) {
198 if (mSelectedAction == selectedAction) {
199 return;
200 }
201
202 mSelectedAction = selectedAction;
Evan Laird31ca5472020-04-08 17:45:24 -0400203 }
204
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500205 public void bindNotification(
206 ShortcutManager shortcutManager,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500207 PackageManager pm,
208 INotificationManager iNotificationManager,
209 VisualStabilityManager visualStabilityManager,
210 String pkg,
211 NotificationChannel notificationChannel,
212 NotificationEntry entry,
Evan Laird03c44452020-04-16 12:26:07 -0400213 Notification.BubbleMetadata bubbleMetadata,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500214 OnSettingsClickListener onSettingsClick,
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500215 OnSnoozeClickListener onSnoozeClickListener,
Julia Reynolds01c9da42020-02-14 14:17:58 -0500216 ConversationIconFactory conversationIconFactory,
Evan Laird31ca5472020-04-08 17:45:24 -0400217 Context userContext,
218 Provider<PriorityOnboardingDialogController.Builder> builderProvider,
Steve Elliott6771f542020-05-26 13:31:10 -0400219 boolean isDeviceProvisioned,
220 @Main Handler mainHandler,
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400221 @Background Handler bgHandler,
222 OnConversationSettingsClickListener onConversationSettingsClickListener) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500223 mSelectedAction = -1;
224 mINotificationManager = iNotificationManager;
225 mVisualStabilityManager = visualStabilityManager;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500226 mPackageName = pkg;
Steve Elliott6771f542020-05-26 13:31:10 -0400227 mEntry = entry;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500228 mSbn = entry.getSbn();
229 mPm = pm;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500230 mAppName = mPackageName;
231 mOnSettingsClickListener = onSettingsClick;
232 mNotificationChannel = notificationChannel;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500233 mAppUid = mSbn.getUid();
234 mDelegatePkg = mSbn.getOpPkg();
235 mIsDeviceProvisioned = isDeviceProvisioned;
236 mOnSnoozeClickListener = onSnoozeClickListener;
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400237 mOnConversationSettingsClickListener = onConversationSettingsClickListener;
Julia Reynolds01c9da42020-02-14 14:17:58 -0500238 mIconFactory = conversationIconFactory;
Evan Laird31ca5472020-04-08 17:45:24 -0400239 mUserContext = userContext;
Evan Laird03c44452020-04-16 12:26:07 -0400240 mBubbleMetadata = bubbleMetadata;
Evan Laird31ca5472020-04-08 17:45:24 -0400241 mBuilderProvider = builderProvider;
Steve Elliott6771f542020-05-26 13:31:10 -0400242 mMainHandler = mainHandler;
243 mBgHandler = bgHandler;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500244 mShortcutManager = shortcutManager;
Julia Reynolds8582df52020-04-24 18:30:59 -0400245 mShortcutInfo = entry.getRanking().getShortcutInfo();
246 if (mShortcutInfo == null) {
Julia Reynolds7c267522020-01-16 11:26:41 -0500247 throw new IllegalArgumentException("Does not have required information");
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500248 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500249
Mady Mellor9adfe6a2020-03-30 17:23:26 -0700250 mNotificationChannel = NotificationChannelHelper.createConversationChannelIfNeeded(
251 getContext(), mINotificationManager, entry, mNotificationChannel);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500252
Julia Reynolds8d257092020-04-15 15:57:21 -0400253 try {
254 mAppBubble = mINotificationManager.getBubblePreferenceForPackage(mPackageName, mAppUid);
255 } catch (RemoteException e) {
Evan Laird31ca5472020-04-08 17:45:24 -0400256 Log.e(TAG, "can't reach OS", e);
Julia Reynolds8d257092020-04-15 15:57:21 -0400257 mAppBubble = BUBBLE_PREFERENCE_SELECTED;
258 }
259
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500260 bindHeader();
261 bindActions();
262
Julia Reynoldsa856e492020-03-18 17:30:06 -0400263 View done = findViewById(R.id.done);
264 done.setOnClickListener(mOnDone);
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400265 done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500266 }
267
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500268 private void bindActions() {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500269
Julia Reynoldsa856e492020-03-18 17:30:06 -0400270 // TODO: b/152050825
271 /*
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500272 Button home = findViewById(R.id.home);
273 home.setOnClickListener(mOnHomeClick);
Julia Reynoldse6fed502020-02-07 14:41:02 -0500274 home.setVisibility(mShortcutInfo != null
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500275 && mShortcutManager.isRequestPinShortcutSupported()
276 ? VISIBLE : GONE);
277
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500278 Button snooze = findViewById(R.id.snooze);
279 snooze.setOnClickListener(mOnSnoozeClick);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400280 */
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500281
Julia Reynolds8d257092020-04-15 15:57:21 -0400282 if (mAppBubble == BUBBLE_PREFERENCE_ALL) {
283 ((TextView) findViewById(R.id.default_summary)).setText(getResources().getString(
284 R.string.notification_channel_summary_default_with_bubbles, mAppName));
285 }
286
Julia Reynoldsa856e492020-03-18 17:30:06 -0400287 findViewById(R.id.priority).setOnClickListener(mOnFavoriteClick);
288 findViewById(R.id.default_behavior).setOnClickListener(mOnDefaultClick);
289 findViewById(R.id.silence).setOnClickListener(mOnMuteClick);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500290
Julia Reynoldse6fed502020-02-07 14:41:02 -0500291 final View settingsButton = findViewById(R.id.info);
292 settingsButton.setOnClickListener(getSettingsOnClickListener());
293 settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
294
Julia Reynoldsa856e492020-03-18 17:30:06 -0400295 updateToggleActions(getSelectedAction(), false);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500296 }
297
298 private void bindHeader() {
299 bindConversationDetails();
300
301 // Delegate
302 bindDelegate();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500303 }
304
305 private OnClickListener getSettingsOnClickListener() {
306 if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
307 final int appUidF = mAppUid;
308 return ((View view) -> {
309 mOnSettingsClickListener.onClick(view, mNotificationChannel, appUidF);
310 });
311 }
312 return null;
313 }
314
315 private void bindConversationDetails() {
316 final TextView channelName = findViewById(R.id.parent_channel_name);
317 channelName.setText(mNotificationChannel.getName());
318
319 bindGroup();
Julia Reynoldsf2acd602020-01-21 16:01:25 -0500320 // TODO: bring back when channel name does not include name
321 // bindName();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500322 bindPackage();
Julia Reynoldsa856e492020-03-18 17:30:06 -0400323 bindIcon(mNotificationChannel.isImportantConversation());
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500324 }
325
Julia Reynoldsa856e492020-03-18 17:30:06 -0400326 private void bindIcon(boolean important) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500327 ImageView image = findViewById(R.id.conversation_icon);
Julia Reynolds8582df52020-04-24 18:30:59 -0400328 image.setImageDrawable(mIconFactory.getConversationDrawable(
329 mShortcutInfo, mPackageName, mAppUid, important));
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500330 }
331
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500332 private void bindPackage() {
333 ApplicationInfo info;
334 try {
335 info = mPm.getApplicationInfo(
336 mPackageName,
337 PackageManager.MATCH_UNINSTALLED_PACKAGES
338 | PackageManager.MATCH_DISABLED_COMPONENTS
339 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
340 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
341 if (info != null) {
342 mAppName = String.valueOf(mPm.getApplicationLabel(info));
343 }
344 } catch (PackageManager.NameNotFoundException e) {
345 }
346 ((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
347 }
348
349 private void bindDelegate() {
350 TextView delegateView = findViewById(R.id.delegate_name);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500351
352 if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
353 // this notification was posted by a delegate!
354 delegateView.setVisibility(View.VISIBLE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500355 } else {
356 delegateView.setVisibility(View.GONE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500357 }
358 }
359
360 private void bindGroup() {
361 // Set group information if this channel has an associated group.
362 CharSequence groupName = null;
363 if (mNotificationChannel != null && mNotificationChannel.getGroup() != null) {
364 try {
365 final NotificationChannelGroup notificationChannelGroup =
366 mINotificationManager.getNotificationChannelGroupForPackage(
367 mNotificationChannel.getGroup(), mPackageName, mAppUid);
368 if (notificationChannelGroup != null) {
369 groupName = notificationChannelGroup.getName();
370 }
371 } catch (RemoteException e) {
372 }
373 }
374 TextView groupNameView = findViewById(R.id.group_name);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500375 if (groupName != null) {
376 groupNameView.setText(groupName);
377 groupNameView.setVisibility(VISIBLE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500378 } else {
379 groupNameView.setVisibility(GONE);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500380 }
381 }
382
383 @Override
384 public boolean post(Runnable action) {
385 if (mSkipPost) {
386 action.run();
387 return true;
388 } else {
389 return super.post(action);
390 }
391 }
392
393 @Override
Julia Reynoldsa856e492020-03-18 17:30:06 -0400394 protected void onFinishInflate() {
395 super.onFinishInflate();
396
397 mPriorityDescriptionView = findViewById(R.id.priority_summary);
398 mDefaultDescriptionView = findViewById(R.id.default_summary);
399 mSilentDescriptionView = findViewById(R.id.silence_summary);
400 }
401
402 @Override
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500403 public void onFinishedClosing() {
404 // TODO: do we need to do anything here?
405 }
406
407 @Override
Julia Reynoldsbe371072020-05-28 11:32:01 -0400408 public boolean needsFalsingProtection() {
409 return true;
410 }
411
412 @Override
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500413 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
414 super.onInitializeAccessibilityEvent(event);
415 if (mGutsContainer != null &&
416 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
417 if (mGutsContainer.isExposed()) {
418 event.getText().add(mContext.getString(
419 R.string.notification_channel_controls_opened_accessibility, mAppName));
420 } else {
421 event.getText().add(mContext.getString(
422 R.string.notification_channel_controls_closed_accessibility, mAppName));
423 }
424 }
425 }
426
Julia Reynoldsa856e492020-03-18 17:30:06 -0400427 private void updateToggleActions(int selectedAction, boolean userTriggered) {
428 if (userTriggered) {
429 TransitionSet transition = new TransitionSet();
430 transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
431 transition.addTransition(new Fade(Fade.OUT))
432 .addTransition(new ChangeBounds())
433 .addTransition(
434 new Fade(Fade.IN)
435 .setStartDelay(150)
436 .setDuration(200)
437 .setInterpolator(FAST_OUT_SLOW_IN));
438 transition.setDuration(350);
439 transition.setInterpolator(FAST_OUT_SLOW_IN);
440 TransitionManager.beginDelayedTransition(this, transition);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500441 }
Julia Reynoldse6fed502020-02-07 14:41:02 -0500442
Julia Reynoldsa856e492020-03-18 17:30:06 -0400443 View priority = findViewById(R.id.priority);
444 View defaultBehavior = findViewById(R.id.default_behavior);
445 View silence = findViewById(R.id.silence);
446
447 switch (selectedAction) {
448 case ACTION_FAVORITE:
449 mPriorityDescriptionView.setVisibility(VISIBLE);
450 mDefaultDescriptionView.setVisibility(GONE);
451 mSilentDescriptionView.setVisibility(GONE);
452 post(() -> {
453 priority.setSelected(true);
454 defaultBehavior.setSelected(false);
455 silence.setSelected(false);
456 });
457 break;
458
459 case ACTION_MUTE:
460 mSilentDescriptionView.setVisibility(VISIBLE);
461 mDefaultDescriptionView.setVisibility(GONE);
462 mPriorityDescriptionView.setVisibility(GONE);
463 post(() -> {
464 priority.setSelected(false);
465 defaultBehavior.setSelected(false);
466 silence.setSelected(true);
467 });
468 break;
469
470 case ACTION_DEFAULT:
471 mDefaultDescriptionView.setVisibility(VISIBLE);
472 mSilentDescriptionView.setVisibility(GONE);
473 mPriorityDescriptionView.setVisibility(GONE);
474 post(() -> {
475 priority.setSelected(false);
476 defaultBehavior.setSelected(true);
477 silence.setSelected(false);
478 });
479 break;
480
481 default:
482 throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500483 }
Dan Sandlerb11f2de2020-02-19 13:18:24 -0500484
Julia Reynoldsa856e492020-03-18 17:30:06 -0400485 boolean isAChange = getSelectedAction() != selectedAction;
486 TextView done = findViewById(R.id.done);
487 done.setText(isAChange
488 ? R.string.inline_ok_button
489 : R.string.inline_done_button);
490
Dan Sandlerb11f2de2020-02-19 13:18:24 -0500491 // update icon in case importance has changed
Julia Reynoldsa856e492020-03-18 17:30:06 -0400492 bindIcon(selectedAction == ACTION_FAVORITE);
493 }
494
495 int getSelectedAction() {
496 if (mNotificationChannel.getImportance() <= IMPORTANCE_LOW
497 && mNotificationChannel.getImportance() > IMPORTANCE_UNSPECIFIED) {
498 return ACTION_MUTE;
499 } else {
500 if (mNotificationChannel.isImportantConversation()) {
501 return ACTION_FAVORITE;
502 }
503 }
504 return ACTION_DEFAULT;
Julia Reynoldse6fed502020-02-07 14:41:02 -0500505 }
506
507 private void updateChannel() {
Steve Elliott6771f542020-05-26 13:31:10 -0400508 mBgHandler.post(
Julia Reynoldse6fed502020-02-07 14:41:02 -0500509 new UpdateChannelRunnable(mINotificationManager, mPackageName,
510 mAppUid, mSelectedAction, mNotificationChannel));
Steve Elliott8b4929d2020-06-02 13:38:04 -0400511 mEntry.markForUserTriggeredMovement(true);
512 mMainHandler.postDelayed(
513 mVisualStabilityManager::temporarilyAllowReordering,
514 StackStateAnimator.ANIMATION_DURATION_STANDARD);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500515 }
516
Evan Laird31ca5472020-04-08 17:45:24 -0400517 private boolean shouldShowPriorityOnboarding() {
518 return !Prefs.getBoolean(mUserContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING, false);
519 }
520
521 private void showPriorityOnboarding() {
522 View onboardingView = LayoutInflater.from(mContext)
523 .inflate(R.layout.priority_onboarding_half_shell, null);
524
525 boolean ignoreDnd = false;
526 try {
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400527 ignoreDnd = mINotificationManager
528 .getConsolidatedNotificationPolicy().priorityConversationSenders ==
529 NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
Evan Laird31ca5472020-04-08 17:45:24 -0400530 } catch (RemoteException e) {
531 Log.e(TAG, "Could not check conversation senders", e);
532 }
533
Evan Laird03c44452020-04-16 12:26:07 -0400534 boolean showAsBubble = mBubbleMetadata != null
535 && mBubbleMetadata.getAutoExpandBubble()
Evan Laird31ca5472020-04-08 17:45:24 -0400536 && Settings.Global.getInt(mContext.getContentResolver(),
537 NOTIFICATION_BUBBLES, 0) == 1;
538
539 PriorityOnboardingDialogController controller = mBuilderProvider.get()
540 .setContext(mUserContext)
541 .setView(onboardingView)
542 .setIgnoresDnd(ignoreDnd)
543 .setShowsAsBubble(showAsBubble)
Julia Reynoldsc5356502020-06-08 16:14:58 -0400544 .setIcon(mIconFactory.getBaseIconDrawable(mShortcutInfo))
545 .setBadge(mIconFactory.getAppBadge(
546 mPackageName, UserHandle.getUserId(mSbn.getUid())))
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400547 .setOnSettingsClick(mOnConversationSettingsClickListener)
Evan Laird31ca5472020-04-08 17:45:24 -0400548 .build();
549
550 controller.init();
551 controller.show();
552 }
553
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500554 @Override
555 public void setGutsParent(NotificationGuts guts) {
556 mGutsContainer = guts;
557 }
558
559 @Override
560 public boolean willBeRemoved() {
561 return false;
562 }
563
564 @Override
565 public boolean shouldBeSaved() {
Julia Reynoldsd5cc0ea2020-04-24 11:30:29 -0400566 return mPressedApply;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500567 }
568
569 @Override
570 public View getContentView() {
571 return this;
572 }
573
574 @Override
575 public boolean handleCloseControls(boolean save, boolean force) {
576 if (save && mSelectedAction > -1) {
Julia Reynoldse6fed502020-02-07 14:41:02 -0500577 updateChannel();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500578 }
579 return false;
580 }
581
582 @Override
583 public int getActualHeight() {
Selim Cineka5a4ee42020-05-21 15:38:32 -0700584 // Because we're animating the bounds, getHeight will return the small height at the
585 // beginning of the animation. Instead we'd want it to already return the end value
586 return mActualHeight;
587 }
588
589 @Override
590 protected void onLayout(boolean changed, int l, int t, int r, int b) {
591 super.onLayout(changed, l, t, r, b);
592 mActualHeight = getHeight();
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500593 }
594
595 @VisibleForTesting
596 public boolean isAnimating() {
597 return false;
598 }
599
Julia Reynoldse6fed502020-02-07 14:41:02 -0500600 class UpdateChannelRunnable implements Runnable {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500601
602 private final INotificationManager mINotificationManager;
603 private final String mAppPkg;
604 private final int mAppUid;
605 private NotificationChannel mChannelToUpdate;
606 private final @Action int mAction;
607
608 public UpdateChannelRunnable(INotificationManager notificationManager,
609 String packageName, int appUid, @Action int action,
610 @NonNull NotificationChannel channelToUpdate) {
611 mINotificationManager = notificationManager;
612 mAppPkg = packageName;
613 mAppUid = appUid;
614 mChannelToUpdate = channelToUpdate;
615 mAction = action;
616 }
617
618 @Override
619 public void run() {
620 try {
621 switch (mAction) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500622 case ACTION_FAVORITE:
Julia Reynoldse03aa8f2020-06-02 11:21:38 -0400623 mChannelToUpdate.setImportantConversation(true);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400624 if (mChannelToUpdate.isImportantConversation()) {
Julia Reynolds908201e2020-02-17 21:53:49 -0500625 mChannelToUpdate.setAllowBubbles(true);
Julia Reynolds8d257092020-04-15 15:57:21 -0400626 if (mAppBubble == BUBBLE_PREFERENCE_NONE) {
Mady Mellora92268c2020-03-09 17:25:08 -0700627 mINotificationManager.setBubblesAllowed(mAppPkg, mAppUid,
628 BUBBLE_PREFERENCE_SELECTED);
629 }
Julia Reynolds908201e2020-02-17 21:53:49 -0500630 }
Julia Reynoldsa856e492020-03-18 17:30:06 -0400631 mChannelToUpdate.setImportance(Math.max(
632 mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
633 break;
634 case ACTION_DEFAULT:
635 mChannelToUpdate.setImportance(Math.max(
636 mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
637 if (mChannelToUpdate.isImportantConversation()) {
638 mChannelToUpdate.setImportantConversation(false);
639 mChannelToUpdate.setAllowBubbles(false);
640 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500641 break;
642 case ACTION_MUTE:
643 if (mChannelToUpdate.getImportance() == IMPORTANCE_UNSPECIFIED
644 || mChannelToUpdate.getImportance() >= IMPORTANCE_DEFAULT) {
645 mChannelToUpdate.setImportance(IMPORTANCE_LOW);
Julia Reynoldsa856e492020-03-18 17:30:06 -0400646 }
647 if (mChannelToUpdate.isImportantConversation()) {
648 mChannelToUpdate.setImportantConversation(false);
649 mChannelToUpdate.setAllowBubbles(false);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500650 }
651 break;
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500652 }
653
Julia Reynoldsa856e492020-03-18 17:30:06 -0400654 mINotificationManager.updateNotificationChannelForPackage(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500655 mAppPkg, mAppUid, mChannelToUpdate);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500656 } catch (RemoteException e) {
657 Log.e(TAG, "Unable to update notification channel", e);
658 }
659 }
660 }
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500661}