blob: 82ad74e26f0c6b147053f633aebac0b1502d0a74 [file] [log] [blame]
Mady Mellor87d79452017-01-10 11:52:52 -08001/*
2 * Copyright (C) 2017 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
Geoffrey Pitschdf44b602017-02-03 13:31:50 -050017package com.android.systemui.statusbar;
18
Julia Reynoldse0341482018-03-08 14:42:50 -050019import static android.app.NotificationManager.IMPORTANCE_MIN;
Julia Reynolds3aedded2017-03-31 14:42:09 -040020import static android.app.NotificationManager.IMPORTANCE_NONE;
21
Julia Reynolds437cdb12018-01-03 12:27:24 -050022import android.animation.Animator;
23import android.animation.AnimatorListenerAdapter;
24import android.animation.AnimatorSet;
25import android.animation.ObjectAnimator;
Mady Mellor87d79452017-01-10 11:52:52 -080026import android.app.INotificationManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040027import android.app.Notification;
Mady Mellor87d79452017-01-10 11:52:52 -080028import android.app.NotificationChannel;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -050029import android.app.NotificationChannelGroup;
Mady Mellor87d79452017-01-10 11:52:52 -080030import android.content.Context;
Julia Reynolds3aedded2017-03-31 14:42:09 -040031import android.content.Intent;
32import android.content.pm.ActivityInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080033import android.content.pm.ApplicationInfo;
34import android.content.pm.PackageInfo;
35import android.content.pm.PackageManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040036import android.content.pm.ResolveInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080037import android.graphics.drawable.Drawable;
Mady Mellor87d79452017-01-10 11:52:52 -080038import android.os.RemoteException;
Julia Reynolds3aedded2017-03-31 14:42:09 -040039import android.service.notification.StatusBarNotification;
40import android.text.TextUtils;
Mady Mellor87d79452017-01-10 11:52:52 -080041import android.util.AttributeSet;
Mady Mellor87d79452017-01-10 11:52:52 -080042import android.view.View;
Julia Reynoldse0341482018-03-08 14:42:50 -050043import android.view.ViewGroup;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040044import android.view.accessibility.AccessibilityEvent;
Mady Mellor87d79452017-01-10 11:52:52 -080045import android.widget.ImageView;
46import android.widget.LinearLayout;
Mady Mellor87d79452017-01-10 11:52:52 -080047import android.widget.TextView;
48
Rohan Shah524cf7b2018-03-15 14:40:02 -070049import com.android.internal.annotations.VisibleForTesting;
Mady Mellor87d79452017-01-10 11:52:52 -080050import com.android.internal.logging.MetricsLogger;
51import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
52import com.android.settingslib.Utils;
Rohan Shah524cf7b2018-03-15 14:40:02 -070053import com.android.systemui.Dependency;
Julia Reynolds437cdb12018-01-03 12:27:24 -050054import com.android.systemui.Interpolators;
Mady Mellor87d79452017-01-10 11:52:52 -080055import com.android.systemui.R;
Mady Mellor87d79452017-01-10 11:52:52 -080056
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050057import java.util.List;
Mady Mellor87d79452017-01-10 11:52:52 -080058import java.util.Set;
59
60/**
61 * The guts of a notification revealed when performing a long press.
62 */
Mady Mellor95d743c2017-01-10 12:05:27 -080063public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
Mady Mellor87d79452017-01-10 11:52:52 -080064 private static final String TAG = "InfoGuts";
65
66 private INotificationManager mINotificationManager;
Julia Reynolds437cdb12018-01-03 12:27:24 -050067 private PackageManager mPm;
68
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050069 private String mPkg;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040070 private String mAppName;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050071 private int mAppUid;
Julia Reynolds437cdb12018-01-03 12:27:24 -050072 private int mNumNotificationChannels;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050073 private NotificationChannel mSingleNotificationChannel;
Mady Mellor87d79452017-01-10 11:52:52 -080074 private int mStartingUserImportance;
Julia Reynolds437cdb12018-01-03 12:27:24 -050075 private int mChosenImportance;
76 private boolean mIsSingleDefaultChannel;
77 private boolean mNonblockable;
78 private StatusBarNotification mSbn;
79 private AnimatorSet mExpandAnimation;
Julia Reynoldse0341482018-03-08 14:42:50 -050080 private boolean mIsForeground;
Mady Mellor87d79452017-01-10 11:52:52 -080081
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -040082 private CheckSaveListener mCheckSaveListener;
Julia Reynolds437cdb12018-01-03 12:27:24 -050083 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds3aedded2017-03-31 14:42:09 -040084 private OnAppSettingsClickListener mAppSettingsClickListener;
Mady Mellor95d743c2017-01-10 12:05:27 -080085 private NotificationGuts mGutsContainer;
Rohan Shah524cf7b2018-03-15 14:40:02 -070086
87 /** Whether this view is being shown as part of the blocking helper */
88 private boolean mIsForBlockingHelper;
Julia Reynolds0ef7d842018-01-24 17:50:31 -050089 private boolean mNegativeUserSentiment;
Mady Mellor87d79452017-01-10 11:52:52 -080090
Rohan Shah524cf7b2018-03-15 14:40:02 -070091 private OnClickListener mOnKeepShowing = this::closeControls;
Julia Reynolds437cdb12018-01-03 12:27:24 -050092
Julia Reynoldse0341482018-03-08 14:42:50 -050093 private OnClickListener mOnStopMinNotifications = v -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -050094 swapContent(false);
95 };
96
97 private OnClickListener mOnUndo = v -> {
98 swapContent(true);
99 };
100
Mady Mellor87d79452017-01-10 11:52:52 -0800101 public NotificationInfo(Context context, AttributeSet attrs) {
102 super(context, attrs);
103 }
104
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400105 // Specify a CheckSaveListener to override when/if the user's changes are committed.
106 public interface CheckSaveListener {
107 // Invoked when importance has changed and the NotificationInfo wants to try to save it.
108 // Listener should run saveImportance unless the change should be canceled.
Eliot Courtney47098cb2017-10-18 17:30:30 +0900109 void checkSave(Runnable saveImportance, StatusBarNotification sbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400110 }
111
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500112 public interface OnSettingsClickListener {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500113 void onClick(View v, NotificationChannel channel, int appUid);
Mady Mellor87d79452017-01-10 11:52:52 -0800114 }
115
Julia Reynolds3aedded2017-03-31 14:42:09 -0400116 public interface OnAppSettingsClickListener {
117 void onClick(View v, Intent intent);
118 }
119
Rohan Shah524cf7b2018-03-15 14:40:02 -0700120 @VisibleForTesting
121 void bindNotification(
122 final PackageManager pm,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500123 final INotificationManager iNotificationManager,
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500124 final String pkg,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500125 final NotificationChannel notificationChannel,
126 final int numChannels,
Julia Reynolds3aedded2017-03-31 14:42:09 -0400127 final StatusBarNotification sbn,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500128 final CheckSaveListener checkSaveListener,
129 final OnSettingsClickListener onSettingsClick,
130 final OnAppSettingsClickListener onAppSettingsClick,
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400131 final Set<String> nonBlockablePkgs)
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500132 throws RemoteException {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500133 bindNotification(pm, iNotificationManager, pkg, notificationChannel, numChannels, sbn,
134 checkSaveListener, onSettingsClick, onAppSettingsClick, nonBlockablePkgs,
Rohan Shah524cf7b2018-03-15 14:40:02 -0700135 false /* isBlockingHelper */,
136 false /* isUserSentimentNegative */);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500137 }
138
Rohan Shah524cf7b2018-03-15 14:40:02 -0700139 public void bindNotification(
140 PackageManager pm,
141 INotificationManager iNotificationManager,
142 String pkg,
143 NotificationChannel notificationChannel,
144 int numChannels,
145 StatusBarNotification sbn,
146 CheckSaveListener checkSaveListener,
147 OnSettingsClickListener onSettingsClick,
148 OnAppSettingsClickListener onAppSettingsClick,
149 Set<String> nonBlockablePkgs,
150 boolean isForBlockingHelper,
151 boolean isUserSentimentNegative)
152 throws RemoteException {
Mady Mellor87d79452017-01-10 11:52:52 -0800153 mINotificationManager = iNotificationManager;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500154 mPkg = pkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500155 mNumNotificationChannels = numChannels;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400156 mSbn = sbn;
157 mPm = pm;
158 mAppSettingsClickListener = onAppSettingsClick;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400159 mAppName = mPkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500160 mCheckSaveListener = checkSaveListener;
161 mOnSettingsClickListener = onSettingsClick;
162 mSingleNotificationChannel = notificationChannel;
163 mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
Rohan Shah524cf7b2018-03-15 14:40:02 -0700164 mNegativeUserSentiment = isUserSentimentNegative;
Julia Reynoldse0341482018-03-08 14:42:50 -0500165 mIsForeground =
166 (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700167 mIsForBlockingHelper = isForBlockingHelper;
Rohan Shahdbd64e72018-03-28 14:46:50 -0700168 mAppUid = mSbn.getUid();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500169
Julia Reynolds437cdb12018-01-03 12:27:24 -0500170 int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400171 pkg, mAppUid, false /* includeDeleted */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500172 if (mNumNotificationChannels == 0) {
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400173 throw new IllegalArgumentException("bindNotification requires at least one channel");
174 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500175 // Special behavior for the Default channel if no other channels have been defined.
176 mIsSingleDefaultChannel = mNumNotificationChannels == 1
Rohan Shahdbd64e72018-03-28 14:46:50 -0700177 && mSingleNotificationChannel.getId().equals(
178 NotificationChannel.DEFAULT_CHANNEL_ID)
179 && numTotalChannels == 1;
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400180 }
181
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400182 try {
183 final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
184 if (Utils.isSystemPackage(getResources(), pm, pkgInfo)) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500185 if (mSingleNotificationChannel != null
186 && !mSingleNotificationChannel.isBlockableSystem()) {
187 mNonblockable = true;
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400188 }
189 }
190 } catch (PackageManager.NameNotFoundException e) {
191 // unlikely.
192 }
193 if (nonBlockablePkgs != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500194 mNonblockable |= nonBlockablePkgs.contains(pkg);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400195 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500196 mNonblockable |= (mNumNotificationChannels > 1);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400197
Julia Reynolds437cdb12018-01-03 12:27:24 -0500198 bindHeader();
199 bindPrompt();
200 bindButtons();
201 }
202
203 private void bindHeader() throws RemoteException {
204 // Package name
205 Drawable pkgicon = null;
206 ApplicationInfo info;
207 try {
208 info = mPm.getApplicationInfo(mPkg,
209 PackageManager.MATCH_UNINSTALLED_PACKAGES
210 | PackageManager.MATCH_DISABLED_COMPONENTS
211 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
212 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
213 if (info != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500214 mAppName = String.valueOf(mPm.getApplicationLabel(info));
215 pkgicon = mPm.getApplicationIcon(info);
Geoffrey Pitschee8c81e2017-03-23 11:38:56 -0400216 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500217 } catch (PackageManager.NameNotFoundException e) {
218 // app is gone, just show package name and generic icon
219 pkgicon = mPm.getDefaultActivityIcon();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500220 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500221 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400222 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
Mady Mellor87d79452017-01-10 11:52:52 -0800223
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500224 // Set group information if this channel has an associated group.
225 CharSequence groupName = null;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500226 if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
227 final NotificationChannelGroup notificationChannelGroup =
Julia Reynolds437cdb12018-01-03 12:27:24 -0500228 mINotificationManager.getNotificationChannelGroupForPackage(
229 mSingleNotificationChannel.getGroup(), mPkg, mAppUid);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500230 if (notificationChannelGroup != null) {
231 groupName = notificationChannelGroup.getName();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500232 }
Mady Mellor87d79452017-01-10 11:52:52 -0800233 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500234 TextView groupNameView = findViewById(R.id.group_name);
235 TextView groupDividerView = findViewById(R.id.pkg_group_divider);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500236 if (groupName != null) {
237 groupNameView.setText(groupName);
238 groupNameView.setVisibility(View.VISIBLE);
239 groupDividerView.setVisibility(View.VISIBLE);
240 } else {
241 groupNameView.setVisibility(View.GONE);
242 groupDividerView.setVisibility(View.GONE);
243 }
Mady Mellor87d79452017-01-10 11:52:52 -0800244
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500245 // Settings button.
Julia Reynolds437cdb12018-01-03 12:27:24 -0500246 final View settingsButton = findViewById(R.id.info);
247 if (mAppUid >= 0 && mOnSettingsClickListener != null) {
Geoffrey Pitsch029a3fa2017-03-30 13:01:57 -0400248 settingsButton.setVisibility(View.VISIBLE);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500249 final int appUidF = mAppUid;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500250 settingsButton.setOnClickListener(
251 (View view) -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500252 mOnSettingsClickListener.onClick(view,
253 mNumNotificationChannels > 1 ? null : mSingleNotificationChannel,
254 appUidF);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500255 });
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500256 } else {
257 settingsButton.setVisibility(View.GONE);
258 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500259 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500260
Julia Reynolds437cdb12018-01-03 12:27:24 -0500261 private void bindPrompt() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500262 final TextView blockPrompt = findViewById(R.id.block_prompt);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500263 bindName();
Julia Reynolds437cdb12018-01-03 12:27:24 -0500264 if (mNonblockable) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500265 blockPrompt.setText(R.string.notification_unblockable_desc);
266 } else {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500267 if (mNegativeUserSentiment) {
268 blockPrompt.setText(R.string.inline_blocking_helper);
269 } else if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500270 blockPrompt.setText(R.string.inline_keep_showing_app);
271 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500272 blockPrompt.setText(R.string.inline_keep_showing);
273 }
274 }
Mady Mellor87d79452017-01-10 11:52:52 -0800275 }
276
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500277 private void bindName() {
278 final TextView channelName = findViewById(R.id.channel_name);
279 if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
280 channelName.setVisibility(View.GONE);
281 } else {
282 channelName.setText(mSingleNotificationChannel.getName());
283 }
284 }
285
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400286 private boolean hasImportanceChanged() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500287 return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
Mady Mellor87d79452017-01-10 11:52:52 -0800288 }
289
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500290 private void saveImportance() {
Julia Reynoldsc65656a2018-02-12 09:55:14 -0500291 if (mNonblockable) {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500292 return;
293 }
Mady Mellor87d79452017-01-10 11:52:52 -0800294 MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500295 mChosenImportance - mStartingUserImportance);
296 mSingleNotificationChannel.setImportance(mChosenImportance);
Julia Reynolds8ceb5792017-04-11 11:32:44 -0400297 mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
Mady Mellor87d79452017-01-10 11:52:52 -0800298 try {
299 mINotificationManager.updateNotificationChannelForPackage(
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500300 mPkg, mAppUid, mSingleNotificationChannel);
Mady Mellor87d79452017-01-10 11:52:52 -0800301 } catch (RemoteException e) {
302 // :(
303 }
304 }
305
Julia Reynolds437cdb12018-01-03 12:27:24 -0500306 private void bindButtons() {
Rohan Shah524cf7b2018-03-15 14:40:02 -0700307 // Set up stay-in-notification actions
Julia Reynolds437cdb12018-01-03 12:27:24 -0500308 View block = findViewById(R.id.block);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500309 TextView keep = findViewById(R.id.keep);
Julia Reynoldse0341482018-03-08 14:42:50 -0500310 View minimize = findViewById(R.id.minimize);
Rohan Shah524cf7b2018-03-15 14:40:02 -0700311
312 findViewById(R.id.undo).setOnClickListener(mOnUndo);
313 block.setOnClickListener(mOnStopMinNotifications);
314 keep.setOnClickListener(mOnKeepShowing);
Julia Reynoldse0341482018-03-08 14:42:50 -0500315 minimize.setOnClickListener(mOnStopMinNotifications);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500316
317 if (mNonblockable) {
318 keep.setText(R.string.notification_done);
319 block.setVisibility(GONE);
Julia Reynoldse0341482018-03-08 14:42:50 -0500320 minimize.setVisibility(GONE);
321 } else if (mIsForeground) {
322 block.setVisibility(GONE);
323 minimize.setVisibility(VISIBLE);
324 } else if (!mIsForeground) {
325 block.setVisibility(VISIBLE);
326 minimize.setVisibility(GONE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500327 }
328
Rohan Shah524cf7b2018-03-15 14:40:02 -0700329 // Set up app settings link
Julia Reynolds437cdb12018-01-03 12:27:24 -0500330 TextView settingsLinkView = findViewById(R.id.app_settings);
331 Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
332 mSbn.getId(), mSbn.getTag());
333 if (settingsIntent != null
334 && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
Julia Reynoldse0341482018-03-08 14:42:50 -0500335 settingsLinkView.setVisibility(VISIBLE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500336 settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
337 mSbn.getNotification().getSettingsText()));
338 settingsLinkView.setOnClickListener((View view) -> {
339 mAppSettingsClickListener.onClick(view, settingsIntent);
340 });
Mady Mellor87d79452017-01-10 11:52:52 -0800341 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500342 settingsLinkView.setVisibility(View.GONE);
Mady Mellor87d79452017-01-10 11:52:52 -0800343 }
344 }
345
Julia Reynolds437cdb12018-01-03 12:27:24 -0500346 private void swapContent(boolean showPrompt) {
347 if (mExpandAnimation != null) {
348 mExpandAnimation.cancel();
349 }
Mady Mellor87d79452017-01-10 11:52:52 -0800350
Julia Reynoldse0341482018-03-08 14:42:50 -0500351 View prompt = findViewById(R.id.prompt);
352 ViewGroup confirmation = findViewById(R.id.confirmation);
353 TextView confirmationText = findViewById(R.id.confirmation_text);
354 View header = findViewById(R.id.header);
355
Julia Reynolds437cdb12018-01-03 12:27:24 -0500356 if (showPrompt) {
357 mChosenImportance = mStartingUserImportance;
Julia Reynoldse0341482018-03-08 14:42:50 -0500358 } else if (mIsForeground) {
359 mChosenImportance = IMPORTANCE_MIN;
360 confirmationText.setText(R.string.notification_channel_minimized);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500361 } else {
362 mChosenImportance = IMPORTANCE_NONE;
Julia Reynoldse0341482018-03-08 14:42:50 -0500363 confirmationText.setText(R.string.notification_channel_disabled);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500364 }
365
Julia Reynolds437cdb12018-01-03 12:27:24 -0500366 ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
367 prompt.getAlpha(), showPrompt ? 1f : 0f);
368 promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
369 ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
370 confirmation.getAlpha(), showPrompt ? 0f : 1f);
371 confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
372
373 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
374 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
Julia Reynoldse0341482018-03-08 14:42:50 -0500375 header.setVisibility(showPrompt ? VISIBLE : GONE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500376
377 mExpandAnimation = new AnimatorSet();
378 mExpandAnimation.playTogether(promptAnim, confirmAnim);
379 mExpandAnimation.setDuration(150);
380 mExpandAnimation.addListener(new AnimatorListenerAdapter() {
381 boolean cancelled = false;
382
383 @Override
384 public void onAnimationCancel(Animator animation) {
385 cancelled = true;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500386 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500387
388 @Override
389 public void onAnimationEnd(Animator animation) {
390 if (!cancelled) {
391 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
392 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
393 }
394 }
Mady Mellor87d79452017-01-10 11:52:52 -0800395 });
Julia Reynolds437cdb12018-01-03 12:27:24 -0500396 mExpandAnimation.start();
Mady Mellor87d79452017-01-10 11:52:52 -0800397 }
398
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400399 @Override
400 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
401 super.onInitializeAccessibilityEvent(event);
402 if (mGutsContainer != null &&
403 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
404 if (mGutsContainer.isExposed()) {
405 event.getText().add(mContext.getString(
406 R.string.notification_channel_controls_opened_accessibility, mAppName));
407 } else {
408 event.getText().add(mContext.getString(
409 R.string.notification_channel_controls_closed_accessibility, mAppName));
410 }
411 }
412 }
413
Julia Reynolds3aedded2017-03-31 14:42:09 -0400414 private Intent getAppSettingsIntent(PackageManager pm, String packageName,
415 NotificationChannel channel, int id, String tag) {
416 Intent intent = new Intent(Intent.ACTION_MAIN)
417 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
418 .setPackage(packageName);
419 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
420 intent,
421 PackageManager.MATCH_DEFAULT_ONLY
422 );
423 if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
424 return null;
425 }
426 final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
427 intent.setClassName(activityInfo.packageName, activityInfo.name);
428 if (channel != null) {
429 intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
430 }
431 intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
432 intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
433 return intent;
434 }
435
Rohan Shah524cf7b2018-03-15 14:40:02 -0700436 @VisibleForTesting
437 void closeControls(View v) {
438 if (mIsForBlockingHelper) {
439 NotificationBlockingHelperManager manager =
440 Dependency.get(NotificationBlockingHelperManager.class);
441 manager.dismissCurrentBlockingHelper();
442 } else {
443 int[] parentLoc = new int[2];
444 int[] targetLoc = new int[2];
445 mGutsContainer.getLocationOnScreen(parentLoc);
446 v.getLocationOnScreen(targetLoc);
447 final int centerX = v.getWidth() / 2;
448 final int centerY = v.getHeight() / 2;
449 final int x = targetLoc[0] - parentLoc[0] + centerX;
450 final int y = targetLoc[1] - parentLoc[1] + centerY;
451 mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
452 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500453 }
454
Mady Mellor87d79452017-01-10 11:52:52 -0800455 @Override
Mady Mellor95d743c2017-01-10 12:05:27 -0800456 public void setGutsParent(NotificationGuts guts) {
457 mGutsContainer = guts;
Mady Mellor87d79452017-01-10 11:52:52 -0800458 }
459
460 @Override
Mady Mellor434180c2017-02-13 11:29:42 -0800461 public boolean willBeRemoved() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500462 return hasImportanceChanged();
Mady Mellor434180c2017-02-13 11:29:42 -0800463 }
464
465 @Override
Mady Mellor87d79452017-01-10 11:52:52 -0800466 public View getContentView() {
467 return this;
468 }
469
470 @Override
Mady Mellorc2dbe492017-03-30 13:22:03 -0700471 public boolean handleCloseControls(boolean save, boolean force) {
Julia Reynoldsc65656a2018-02-12 09:55:14 -0500472 // Save regardless of the importance so we can lock the importance field if the user wants
473 // to keep getting notifications
474 if (save) {
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400475 if (mCheckSaveListener != null) {
Eliot Courtney47098cb2017-10-18 17:30:30 +0900476 mCheckSaveListener.checkSave(this::saveImportance, mSbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400477 } else {
478 saveImportance();
479 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500480 }
Mady Mellor87d79452017-01-10 11:52:52 -0800481 return false;
482 }
Mady Mellore09fb702017-03-30 13:23:29 -0700483
484 @Override
485 public int getActualHeight() {
486 return getHeight();
487 }
Mady Mellor87d79452017-01-10 11:52:52 -0800488}