blob: a93be00ba080ffdd204e4c4e0567de0c7534a3fe [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;
Mady Mellor87d79452017-01-10 11:52:52 -080034import android.content.pm.PackageManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040035import android.content.pm.ResolveInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080036import android.graphics.drawable.Drawable;
Mady Mellor87d79452017-01-10 11:52:52 -080037import android.os.RemoteException;
Julia Reynolds3aedded2017-03-31 14:42:09 -040038import android.service.notification.StatusBarNotification;
39import android.text.TextUtils;
Mady Mellor87d79452017-01-10 11:52:52 -080040import android.util.AttributeSet;
Mady Mellor87d79452017-01-10 11:52:52 -080041import android.view.View;
Julia Reynoldse0341482018-03-08 14:42:50 -050042import android.view.ViewGroup;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040043import android.view.accessibility.AccessibilityEvent;
Mady Mellor87d79452017-01-10 11:52:52 -080044import android.widget.ImageView;
45import android.widget.LinearLayout;
Mady Mellor87d79452017-01-10 11:52:52 -080046import android.widget.TextView;
47
Rohan Shah524cf7b2018-03-15 14:40:02 -070048import com.android.internal.annotations.VisibleForTesting;
Mady Mellor87d79452017-01-10 11:52:52 -080049import com.android.internal.logging.MetricsLogger;
50import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Rohan Shah524cf7b2018-03-15 14:40:02 -070051import com.android.systemui.Dependency;
Julia Reynolds437cdb12018-01-03 12:27:24 -050052import com.android.systemui.Interpolators;
Mady Mellor87d79452017-01-10 11:52:52 -080053import com.android.systemui.R;
Mady Mellor87d79452017-01-10 11:52:52 -080054
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050055import java.util.List;
Mady Mellor87d79452017-01-10 11:52:52 -080056
57/**
58 * The guts of a notification revealed when performing a long press.
59 */
Mady Mellor95d743c2017-01-10 12:05:27 -080060public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
Mady Mellor87d79452017-01-10 11:52:52 -080061 private static final String TAG = "InfoGuts";
62
63 private INotificationManager mINotificationManager;
Julia Reynolds437cdb12018-01-03 12:27:24 -050064 private PackageManager mPm;
65
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050066 private String mPkg;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040067 private String mAppName;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050068 private int mAppUid;
Julia Reynolds437cdb12018-01-03 12:27:24 -050069 private int mNumNotificationChannels;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050070 private NotificationChannel mSingleNotificationChannel;
Mady Mellor87d79452017-01-10 11:52:52 -080071 private int mStartingUserImportance;
Julia Reynolds437cdb12018-01-03 12:27:24 -050072 private int mChosenImportance;
73 private boolean mIsSingleDefaultChannel;
Rohan Shah63411fc2018-03-28 19:05:52 -070074 private boolean mIsNonblockable;
Julia Reynolds437cdb12018-01-03 12:27:24 -050075 private StatusBarNotification mSbn;
76 private AnimatorSet mExpandAnimation;
Julia Reynoldse0341482018-03-08 14:42:50 -050077 private boolean mIsForeground;
Mady Mellor87d79452017-01-10 11:52:52 -080078
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -040079 private CheckSaveListener mCheckSaveListener;
Julia Reynolds437cdb12018-01-03 12:27:24 -050080 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds3aedded2017-03-31 14:42:09 -040081 private OnAppSettingsClickListener mAppSettingsClickListener;
Mady Mellor95d743c2017-01-10 12:05:27 -080082 private NotificationGuts mGutsContainer;
Rohan Shah524cf7b2018-03-15 14:40:02 -070083
84 /** Whether this view is being shown as part of the blocking helper */
85 private boolean mIsForBlockingHelper;
Julia Reynolds0ef7d842018-01-24 17:50:31 -050086 private boolean mNegativeUserSentiment;
Mady Mellor87d79452017-01-10 11:52:52 -080087
Rohan Shah524cf7b2018-03-15 14:40:02 -070088 private OnClickListener mOnKeepShowing = this::closeControls;
Julia Reynolds437cdb12018-01-03 12:27:24 -050089
Julia Reynoldse0341482018-03-08 14:42:50 -050090 private OnClickListener mOnStopMinNotifications = v -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -050091 swapContent(false);
92 };
93
94 private OnClickListener mOnUndo = v -> {
95 swapContent(true);
96 };
97
Mady Mellor87d79452017-01-10 11:52:52 -080098 public NotificationInfo(Context context, AttributeSet attrs) {
99 super(context, attrs);
100 }
101
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400102 // Specify a CheckSaveListener to override when/if the user's changes are committed.
103 public interface CheckSaveListener {
104 // Invoked when importance has changed and the NotificationInfo wants to try to save it.
105 // Listener should run saveImportance unless the change should be canceled.
Eliot Courtney47098cb2017-10-18 17:30:30 +0900106 void checkSave(Runnable saveImportance, StatusBarNotification sbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400107 }
108
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500109 public interface OnSettingsClickListener {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500110 void onClick(View v, NotificationChannel channel, int appUid);
Mady Mellor87d79452017-01-10 11:52:52 -0800111 }
112
Julia Reynolds3aedded2017-03-31 14:42:09 -0400113 public interface OnAppSettingsClickListener {
114 void onClick(View v, Intent intent);
115 }
116
Rohan Shah524cf7b2018-03-15 14:40:02 -0700117 @VisibleForTesting
118 void bindNotification(
119 final PackageManager pm,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500120 final INotificationManager iNotificationManager,
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500121 final String pkg,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500122 final NotificationChannel notificationChannel,
123 final int numChannels,
Julia Reynolds3aedded2017-03-31 14:42:09 -0400124 final StatusBarNotification sbn,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500125 final CheckSaveListener checkSaveListener,
126 final OnSettingsClickListener onSettingsClick,
127 final OnAppSettingsClickListener onAppSettingsClick,
Rohan Shah63411fc2018-03-28 19:05:52 -0700128 boolean isNonblockable)
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500129 throws RemoteException {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500130 bindNotification(pm, iNotificationManager, pkg, notificationChannel, numChannels, sbn,
Rohan Shah63411fc2018-03-28 19:05:52 -0700131 checkSaveListener, onSettingsClick, onAppSettingsClick, isNonblockable,
Rohan Shah524cf7b2018-03-15 14:40:02 -0700132 false /* isBlockingHelper */,
133 false /* isUserSentimentNegative */);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500134 }
135
Rohan Shah524cf7b2018-03-15 14:40:02 -0700136 public void bindNotification(
137 PackageManager pm,
138 INotificationManager iNotificationManager,
139 String pkg,
140 NotificationChannel notificationChannel,
141 int numChannels,
142 StatusBarNotification sbn,
143 CheckSaveListener checkSaveListener,
144 OnSettingsClickListener onSettingsClick,
145 OnAppSettingsClickListener onAppSettingsClick,
Rohan Shah63411fc2018-03-28 19:05:52 -0700146 boolean isNonblockable,
Rohan Shah524cf7b2018-03-15 14:40:02 -0700147 boolean isForBlockingHelper,
148 boolean isUserSentimentNegative)
149 throws RemoteException {
Mady Mellor87d79452017-01-10 11:52:52 -0800150 mINotificationManager = iNotificationManager;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500151 mPkg = pkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500152 mNumNotificationChannels = numChannels;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400153 mSbn = sbn;
154 mPm = pm;
155 mAppSettingsClickListener = onAppSettingsClick;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400156 mAppName = mPkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500157 mCheckSaveListener = checkSaveListener;
158 mOnSettingsClickListener = onSettingsClick;
159 mSingleNotificationChannel = notificationChannel;
160 mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
Rohan Shah524cf7b2018-03-15 14:40:02 -0700161 mNegativeUserSentiment = isUserSentimentNegative;
Rohan Shah63411fc2018-03-28 19:05:52 -0700162 mIsNonblockable = isNonblockable;
Julia Reynoldse0341482018-03-08 14:42:50 -0500163 mIsForeground =
164 (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700165 mIsForBlockingHelper = isForBlockingHelper;
Rohan Shahdbd64e72018-03-28 14:46:50 -0700166 mAppUid = mSbn.getUid();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500167
Julia Reynolds437cdb12018-01-03 12:27:24 -0500168 int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400169 pkg, mAppUid, false /* includeDeleted */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500170 if (mNumNotificationChannels == 0) {
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400171 throw new IllegalArgumentException("bindNotification requires at least one channel");
172 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500173 // Special behavior for the Default channel if no other channels have been defined.
174 mIsSingleDefaultChannel = mNumNotificationChannels == 1
Rohan Shahdbd64e72018-03-28 14:46:50 -0700175 && mSingleNotificationChannel.getId().equals(
176 NotificationChannel.DEFAULT_CHANNEL_ID)
177 && numTotalChannels == 1;
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400178 }
179
Julia Reynolds437cdb12018-01-03 12:27:24 -0500180 bindHeader();
181 bindPrompt();
182 bindButtons();
183 }
184
185 private void bindHeader() throws RemoteException {
186 // Package name
187 Drawable pkgicon = null;
188 ApplicationInfo info;
189 try {
190 info = mPm.getApplicationInfo(mPkg,
191 PackageManager.MATCH_UNINSTALLED_PACKAGES
192 | PackageManager.MATCH_DISABLED_COMPONENTS
193 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
194 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
195 if (info != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500196 mAppName = String.valueOf(mPm.getApplicationLabel(info));
197 pkgicon = mPm.getApplicationIcon(info);
Geoffrey Pitschee8c81e2017-03-23 11:38:56 -0400198 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500199 } catch (PackageManager.NameNotFoundException e) {
200 // app is gone, just show package name and generic icon
201 pkgicon = mPm.getDefaultActivityIcon();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500202 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500203 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400204 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
Mady Mellor87d79452017-01-10 11:52:52 -0800205
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500206 // Set group information if this channel has an associated group.
207 CharSequence groupName = null;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500208 if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
209 final NotificationChannelGroup notificationChannelGroup =
Julia Reynolds437cdb12018-01-03 12:27:24 -0500210 mINotificationManager.getNotificationChannelGroupForPackage(
211 mSingleNotificationChannel.getGroup(), mPkg, mAppUid);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500212 if (notificationChannelGroup != null) {
213 groupName = notificationChannelGroup.getName();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500214 }
Mady Mellor87d79452017-01-10 11:52:52 -0800215 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500216 TextView groupNameView = findViewById(R.id.group_name);
217 TextView groupDividerView = findViewById(R.id.pkg_group_divider);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500218 if (groupName != null) {
219 groupNameView.setText(groupName);
220 groupNameView.setVisibility(View.VISIBLE);
221 groupDividerView.setVisibility(View.VISIBLE);
222 } else {
223 groupNameView.setVisibility(View.GONE);
224 groupDividerView.setVisibility(View.GONE);
225 }
Mady Mellor87d79452017-01-10 11:52:52 -0800226
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500227 // Settings button.
Julia Reynolds437cdb12018-01-03 12:27:24 -0500228 final View settingsButton = findViewById(R.id.info);
229 if (mAppUid >= 0 && mOnSettingsClickListener != null) {
Geoffrey Pitsch029a3fa2017-03-30 13:01:57 -0400230 settingsButton.setVisibility(View.VISIBLE);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500231 final int appUidF = mAppUid;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500232 settingsButton.setOnClickListener(
233 (View view) -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500234 mOnSettingsClickListener.onClick(view,
235 mNumNotificationChannels > 1 ? null : mSingleNotificationChannel,
236 appUidF);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500237 });
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500238 } else {
239 settingsButton.setVisibility(View.GONE);
240 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500241 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500242
Julia Reynolds437cdb12018-01-03 12:27:24 -0500243 private void bindPrompt() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500244 final TextView blockPrompt = findViewById(R.id.block_prompt);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500245 bindName();
Rohan Shah63411fc2018-03-28 19:05:52 -0700246 if (mIsNonblockable) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500247 blockPrompt.setText(R.string.notification_unblockable_desc);
248 } else {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500249 if (mNegativeUserSentiment) {
250 blockPrompt.setText(R.string.inline_blocking_helper);
251 } else if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500252 blockPrompt.setText(R.string.inline_keep_showing_app);
253 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500254 blockPrompt.setText(R.string.inline_keep_showing);
255 }
256 }
Mady Mellor87d79452017-01-10 11:52:52 -0800257 }
258
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500259 private void bindName() {
260 final TextView channelName = findViewById(R.id.channel_name);
261 if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
262 channelName.setVisibility(View.GONE);
263 } else {
264 channelName.setText(mSingleNotificationChannel.getName());
265 }
266 }
267
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400268 private boolean hasImportanceChanged() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500269 return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
Mady Mellor87d79452017-01-10 11:52:52 -0800270 }
271
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500272 private void saveImportance() {
Rohan Shah63411fc2018-03-28 19:05:52 -0700273 if (mIsNonblockable) {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500274 return;
275 }
Mady Mellor87d79452017-01-10 11:52:52 -0800276 MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500277 mChosenImportance - mStartingUserImportance);
278 mSingleNotificationChannel.setImportance(mChosenImportance);
Julia Reynolds8ceb5792017-04-11 11:32:44 -0400279 mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
Mady Mellor87d79452017-01-10 11:52:52 -0800280 try {
281 mINotificationManager.updateNotificationChannelForPackage(
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500282 mPkg, mAppUid, mSingleNotificationChannel);
Mady Mellor87d79452017-01-10 11:52:52 -0800283 } catch (RemoteException e) {
284 // :(
285 }
286 }
287
Julia Reynolds437cdb12018-01-03 12:27:24 -0500288 private void bindButtons() {
Rohan Shah524cf7b2018-03-15 14:40:02 -0700289 // Set up stay-in-notification actions
Julia Reynolds437cdb12018-01-03 12:27:24 -0500290 View block = findViewById(R.id.block);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500291 TextView keep = findViewById(R.id.keep);
Julia Reynoldse0341482018-03-08 14:42:50 -0500292 View minimize = findViewById(R.id.minimize);
Rohan Shah524cf7b2018-03-15 14:40:02 -0700293
294 findViewById(R.id.undo).setOnClickListener(mOnUndo);
295 block.setOnClickListener(mOnStopMinNotifications);
296 keep.setOnClickListener(mOnKeepShowing);
Julia Reynoldse0341482018-03-08 14:42:50 -0500297 minimize.setOnClickListener(mOnStopMinNotifications);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500298
Rohan Shah63411fc2018-03-28 19:05:52 -0700299 if (mIsNonblockable) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500300 keep.setText(R.string.notification_done);
301 block.setVisibility(GONE);
Julia Reynoldse0341482018-03-08 14:42:50 -0500302 minimize.setVisibility(GONE);
303 } else if (mIsForeground) {
304 block.setVisibility(GONE);
305 minimize.setVisibility(VISIBLE);
306 } else if (!mIsForeground) {
307 block.setVisibility(VISIBLE);
308 minimize.setVisibility(GONE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500309 }
310
Rohan Shah524cf7b2018-03-15 14:40:02 -0700311 // Set up app settings link
Julia Reynolds437cdb12018-01-03 12:27:24 -0500312 TextView settingsLinkView = findViewById(R.id.app_settings);
313 Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
314 mSbn.getId(), mSbn.getTag());
315 if (settingsIntent != null
316 && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
Julia Reynoldse0341482018-03-08 14:42:50 -0500317 settingsLinkView.setVisibility(VISIBLE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500318 settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
319 mSbn.getNotification().getSettingsText()));
320 settingsLinkView.setOnClickListener((View view) -> {
321 mAppSettingsClickListener.onClick(view, settingsIntent);
322 });
Mady Mellor87d79452017-01-10 11:52:52 -0800323 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500324 settingsLinkView.setVisibility(View.GONE);
Mady Mellor87d79452017-01-10 11:52:52 -0800325 }
326 }
327
Julia Reynolds437cdb12018-01-03 12:27:24 -0500328 private void swapContent(boolean showPrompt) {
329 if (mExpandAnimation != null) {
330 mExpandAnimation.cancel();
331 }
Mady Mellor87d79452017-01-10 11:52:52 -0800332
Julia Reynoldse0341482018-03-08 14:42:50 -0500333 View prompt = findViewById(R.id.prompt);
334 ViewGroup confirmation = findViewById(R.id.confirmation);
335 TextView confirmationText = findViewById(R.id.confirmation_text);
336 View header = findViewById(R.id.header);
337
Julia Reynolds437cdb12018-01-03 12:27:24 -0500338 if (showPrompt) {
339 mChosenImportance = mStartingUserImportance;
Julia Reynoldse0341482018-03-08 14:42:50 -0500340 } else if (mIsForeground) {
341 mChosenImportance = IMPORTANCE_MIN;
342 confirmationText.setText(R.string.notification_channel_minimized);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500343 } else {
344 mChosenImportance = IMPORTANCE_NONE;
Julia Reynoldse0341482018-03-08 14:42:50 -0500345 confirmationText.setText(R.string.notification_channel_disabled);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500346 }
347
Julia Reynolds437cdb12018-01-03 12:27:24 -0500348 ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
349 prompt.getAlpha(), showPrompt ? 1f : 0f);
350 promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
351 ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
352 confirmation.getAlpha(), showPrompt ? 0f : 1f);
353 confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
354
355 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
356 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
Julia Reynoldse0341482018-03-08 14:42:50 -0500357 header.setVisibility(showPrompt ? VISIBLE : GONE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500358
359 mExpandAnimation = new AnimatorSet();
360 mExpandAnimation.playTogether(promptAnim, confirmAnim);
361 mExpandAnimation.setDuration(150);
362 mExpandAnimation.addListener(new AnimatorListenerAdapter() {
363 boolean cancelled = false;
364
365 @Override
366 public void onAnimationCancel(Animator animation) {
367 cancelled = true;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500368 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500369
370 @Override
371 public void onAnimationEnd(Animator animation) {
372 if (!cancelled) {
373 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
374 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
375 }
376 }
Mady Mellor87d79452017-01-10 11:52:52 -0800377 });
Julia Reynolds437cdb12018-01-03 12:27:24 -0500378 mExpandAnimation.start();
Mady Mellor87d79452017-01-10 11:52:52 -0800379 }
380
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400381 @Override
382 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
383 super.onInitializeAccessibilityEvent(event);
384 if (mGutsContainer != null &&
385 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
386 if (mGutsContainer.isExposed()) {
387 event.getText().add(mContext.getString(
388 R.string.notification_channel_controls_opened_accessibility, mAppName));
389 } else {
390 event.getText().add(mContext.getString(
391 R.string.notification_channel_controls_closed_accessibility, mAppName));
392 }
393 }
394 }
395
Julia Reynolds3aedded2017-03-31 14:42:09 -0400396 private Intent getAppSettingsIntent(PackageManager pm, String packageName,
397 NotificationChannel channel, int id, String tag) {
398 Intent intent = new Intent(Intent.ACTION_MAIN)
399 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
400 .setPackage(packageName);
401 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
402 intent,
403 PackageManager.MATCH_DEFAULT_ONLY
404 );
405 if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
406 return null;
407 }
408 final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
409 intent.setClassName(activityInfo.packageName, activityInfo.name);
410 if (channel != null) {
411 intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
412 }
413 intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
414 intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
415 return intent;
416 }
417
Rohan Shah524cf7b2018-03-15 14:40:02 -0700418 @VisibleForTesting
419 void closeControls(View v) {
420 if (mIsForBlockingHelper) {
421 NotificationBlockingHelperManager manager =
422 Dependency.get(NotificationBlockingHelperManager.class);
423 manager.dismissCurrentBlockingHelper();
424 } else {
425 int[] parentLoc = new int[2];
426 int[] targetLoc = new int[2];
427 mGutsContainer.getLocationOnScreen(parentLoc);
428 v.getLocationOnScreen(targetLoc);
429 final int centerX = v.getWidth() / 2;
430 final int centerY = v.getHeight() / 2;
431 final int x = targetLoc[0] - parentLoc[0] + centerX;
432 final int y = targetLoc[1] - parentLoc[1] + centerY;
433 mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
434 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500435 }
436
Mady Mellor87d79452017-01-10 11:52:52 -0800437 @Override
Mady Mellor95d743c2017-01-10 12:05:27 -0800438 public void setGutsParent(NotificationGuts guts) {
439 mGutsContainer = guts;
Mady Mellor87d79452017-01-10 11:52:52 -0800440 }
441
442 @Override
Mady Mellor434180c2017-02-13 11:29:42 -0800443 public boolean willBeRemoved() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500444 return hasImportanceChanged();
Mady Mellor434180c2017-02-13 11:29:42 -0800445 }
446
447 @Override
Mady Mellor87d79452017-01-10 11:52:52 -0800448 public View getContentView() {
449 return this;
450 }
451
452 @Override
Mady Mellorc2dbe492017-03-30 13:22:03 -0700453 public boolean handleCloseControls(boolean save, boolean force) {
Julia Reynoldsc65656a2018-02-12 09:55:14 -0500454 // Save regardless of the importance so we can lock the importance field if the user wants
455 // to keep getting notifications
456 if (save) {
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400457 if (mCheckSaveListener != null) {
Eliot Courtney47098cb2017-10-18 17:30:30 +0900458 mCheckSaveListener.checkSave(this::saveImportance, mSbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400459 } else {
460 saveImportance();
461 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500462 }
Mady Mellor87d79452017-01-10 11:52:52 -0800463 return false;
464 }
Mady Mellore09fb702017-03-30 13:23:29 -0700465
466 @Override
467 public int getActualHeight() {
468 return getHeight();
469 }
Mady Mellor87d79452017-01-10 11:52:52 -0800470}