blob: b6948fc4bd1f254f1ae2a51b65ef9efc9448dc4a [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
Rohan Shah20790b82018-07-02 17:21:04 -070017package com.android.systemui.statusbar.notification.row;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -050018
Gus Prevas9abc5062018-10-31 16:11:04 -040019import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
20import static android.app.NotificationManager.IMPORTANCE_HIGH;
21import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynoldse0341482018-03-08 14:42:50 -050022import static android.app.NotificationManager.IMPORTANCE_MIN;
Julia Reynolds3aedded2017-03-31 14:42:09 -040023import static android.app.NotificationManager.IMPORTANCE_NONE;
24
Julia Reynolds437cdb12018-01-03 12:27:24 -050025import android.animation.Animator;
26import android.animation.AnimatorListenerAdapter;
27import android.animation.AnimatorSet;
28import android.animation.ObjectAnimator;
Gus Prevas9abc5062018-10-31 16:11:04 -040029import android.annotation.IntDef;
Rohan Shahca0447e2018-03-30 15:18:27 -070030import android.annotation.Nullable;
Mady Mellor87d79452017-01-10 11:52:52 -080031import android.app.INotificationManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040032import android.app.Notification;
Mady Mellor87d79452017-01-10 11:52:52 -080033import android.app.NotificationChannel;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -050034import android.app.NotificationChannelGroup;
Mady Mellor87d79452017-01-10 11:52:52 -080035import android.content.Context;
Julia Reynolds3aedded2017-03-31 14:42:09 -040036import android.content.Intent;
37import android.content.pm.ActivityInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080038import android.content.pm.ApplicationInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080039import android.content.pm.PackageManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040040import android.content.pm.ResolveInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080041import android.graphics.drawable.Drawable;
William Brockman75cf66a2018-12-21 13:25:01 -050042import android.metrics.LogMaker;
Rohan Shahca0447e2018-03-30 15:18:27 -070043import android.os.Handler;
Mady Mellor87d79452017-01-10 11:52:52 -080044import android.os.RemoteException;
Julia Reynolds3aedded2017-03-31 14:42:09 -040045import android.service.notification.StatusBarNotification;
46import android.text.TextUtils;
Mady Mellor87d79452017-01-10 11:52:52 -080047import android.util.AttributeSet;
Rohan Shahca0447e2018-03-30 15:18:27 -070048import android.util.Log;
Mady Mellor87d79452017-01-10 11:52:52 -080049import android.view.View;
Julia Reynoldse0341482018-03-08 14:42:50 -050050import android.view.ViewGroup;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040051import android.view.accessibility.AccessibilityEvent;
Mady Mellor87d79452017-01-10 11:52:52 -080052import android.widget.ImageView;
53import android.widget.LinearLayout;
Mady Mellor87d79452017-01-10 11:52:52 -080054import android.widget.TextView;
55
Rohan Shah524cf7b2018-03-15 14:40:02 -070056import com.android.internal.annotations.VisibleForTesting;
Mady Mellor87d79452017-01-10 11:52:52 -080057import com.android.internal.logging.MetricsLogger;
58import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Rohan Shah524cf7b2018-03-15 14:40:02 -070059import com.android.systemui.Dependency;
Julia Reynolds437cdb12018-01-03 12:27:24 -050060import com.android.systemui.Interpolators;
Mady Mellor87d79452017-01-10 11:52:52 -080061import com.android.systemui.R;
Gus Prevas9abc5062018-10-31 16:11:04 -040062import com.android.systemui.statusbar.notification.NotificationUtils;
Rohan Shah20790b82018-07-02 17:21:04 -070063import com.android.systemui.statusbar.notification.logging.NotificationCounters;
Mady Mellor87d79452017-01-10 11:52:52 -080064
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050065import java.util.List;
Mady Mellor87d79452017-01-10 11:52:52 -080066
67/**
Rohan Shahda5dcdd2018-04-27 17:21:50 -070068 * The guts of a notification revealed when performing a long press. This also houses the blocking
69 * helper affordance that allows a user to keep/stop notifications after swiping one away.
Mady Mellor87d79452017-01-10 11:52:52 -080070 */
Mady Mellor95d743c2017-01-10 12:05:27 -080071public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
Mady Mellor87d79452017-01-10 11:52:52 -080072 private static final String TAG = "InfoGuts";
73
Gus Prevas894d9152018-11-12 13:51:40 -050074 @IntDef(prefix = { "ACTION_" }, value = {
75 ACTION_NONE,
76 ACTION_UNDO,
77 ACTION_TOGGLE_SILENT,
78 ACTION_BLOCK,
Gus Prevas9abc5062018-10-31 16:11:04 -040079 })
Gus Prevas894d9152018-11-12 13:51:40 -050080 public @interface NotificationInfoAction {
81 }
Gus Prevas9abc5062018-10-31 16:11:04 -040082
Gus Prevas894d9152018-11-12 13:51:40 -050083 public static final int ACTION_NONE = 0;
84 public static final int ACTION_UNDO = 1;
85 public static final int ACTION_TOGGLE_SILENT = 2;
86 public static final int ACTION_BLOCK = 3;
Gus Prevas9abc5062018-10-31 16:11:04 -040087
Mady Mellor87d79452017-01-10 11:52:52 -080088 private INotificationManager mINotificationManager;
Julia Reynolds437cdb12018-01-03 12:27:24 -050089 private PackageManager mPm;
Rohan Shahda5dcdd2018-04-27 17:21:50 -070090 private MetricsLogger mMetricsLogger;
Julia Reynolds437cdb12018-01-03 12:27:24 -050091
Rohan Shahca0447e2018-03-30 15:18:27 -070092 private String mPackageName;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040093 private String mAppName;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050094 private int mAppUid;
Julia Reynolds268647a2018-10-25 16:54:27 -040095 private String mDelegatePkg;
Rohan Shahca0447e2018-03-30 15:18:27 -070096 private int mNumUniqueChannelsInRow;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050097 private NotificationChannel mSingleNotificationChannel;
Gus Prevas9abc5062018-10-31 16:11:04 -040098 private int mStartingChannelImportance;
Gus Prevascaed15c2019-01-18 14:19:51 -050099 private boolean mWasShownHighPriority;
100 /**
101 * The last importance level chosen by the user. Null if the user has not chosen an importance
102 * level; non-null once the user takes an action which indicates an explicit preference.
103 */
104 @Nullable private Integer mChosenImportance;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500105 private boolean mIsSingleDefaultChannel;
Rohan Shah63411fc2018-03-28 19:05:52 -0700106 private boolean mIsNonblockable;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500107 private StatusBarNotification mSbn;
108 private AnimatorSet mExpandAnimation;
Julia Reynoldse0341482018-03-08 14:42:50 -0500109 private boolean mIsForeground;
Julia Reynolds35765d82018-08-17 11:39:19 -0400110 private boolean mIsDeviceProvisioned;
Mady Mellor87d79452017-01-10 11:52:52 -0800111
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400112 private CheckSaveListener mCheckSaveListener;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500113 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400114 private OnAppSettingsClickListener mAppSettingsClickListener;
Mady Mellor95d743c2017-01-10 12:05:27 -0800115 private NotificationGuts mGutsContainer;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700116
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700117 /** Whether this view is being shown as part of the blocking helper. */
Rohan Shah524cf7b2018-03-15 14:40:02 -0700118 private boolean mIsForBlockingHelper;
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500119 private boolean mNegativeUserSentiment;
Mady Mellor87d79452017-01-10 11:52:52 -0800120
Rohan Shahdd588c72018-05-09 20:32:15 -0700121 /**
122 * String that describes how the user exit or quit out of this view, also used as a counter tag.
123 */
124 private String mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700125
126 private OnClickListener mOnKeepShowing = v -> {
Rohan Shahdd588c72018-05-09 20:32:15 -0700127 mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700128 closeControls(v);
Will Brockmana399f022019-01-30 10:59:36 -0500129 if (mIsForBlockingHelper) {
130 mMetricsLogger.write(getLogMaker().setCategory(
131 MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
132 .setType(MetricsEvent.TYPE_ACTION)
133 .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
134 }
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700135 };
Julia Reynolds437cdb12018-01-03 12:27:24 -0500136
Gus Prevas9abc5062018-10-31 16:11:04 -0400137 private OnClickListener mOnToggleSilent = v -> {
138 Runnable saveImportance = () -> {
Gus Prevas894d9152018-11-12 13:51:40 -0500139 swapContent(ACTION_TOGGLE_SILENT, true /* animate */);
Will Brockmana399f022019-01-30 10:59:36 -0500140 if (mIsForBlockingHelper) {
141 mMetricsLogger.write(getLogMaker()
142 .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
143 .setType(MetricsEvent.TYPE_ACTION)
144 .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME));
145 }
Gus Prevas9abc5062018-10-31 16:11:04 -0400146 };
147 if (mCheckSaveListener != null) {
148 mCheckSaveListener.checkSave(saveImportance, mSbn);
149 } else {
150 saveImportance.run();
151 }
152 };
153
Rohan Shahca0447e2018-03-30 15:18:27 -0700154 private OnClickListener mOnStopOrMinimizeNotifications = v -> {
Gus Prevas533836a2018-09-24 17:15:32 -0400155 Runnable saveImportance = () -> {
Gus Prevas894d9152018-11-12 13:51:40 -0500156 swapContent(ACTION_BLOCK, true /* animate */);
Will Brockmana399f022019-01-30 10:59:36 -0500157 if (mIsForBlockingHelper) {
158 mMetricsLogger.write(getLogMaker()
159 .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
160 .setType(MetricsEvent.TYPE_ACTION)
161 .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED));
162 }
Gus Prevas533836a2018-09-24 17:15:32 -0400163 };
164 if (mCheckSaveListener != null) {
165 mCheckSaveListener.checkSave(saveImportance, mSbn);
166 } else {
167 saveImportance.run();
168 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500169 };
170
171 private OnClickListener mOnUndo = v -> {
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700172 // Reset exit counter that we'll log and record an undo event separately (not an exit event)
Rohan Shahdd588c72018-05-09 20:32:15 -0700173 mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
Will Brockmana399f022019-01-30 10:59:36 -0500174 if (mIsForBlockingHelper) {
175 logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
176 mMetricsLogger.write(getLogMaker().setCategory(
177 MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
178 .setType(MetricsEvent.TYPE_DISMISS)
179 .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO));
180 } else {
181 mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
182 }
Gus Prevas894d9152018-11-12 13:51:40 -0500183 swapContent(ACTION_UNDO, true /* animate */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500184 };
185
Mady Mellor87d79452017-01-10 11:52:52 -0800186 public NotificationInfo(Context context, AttributeSet attrs) {
187 super(context, attrs);
188 }
189
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400190 // Specify a CheckSaveListener to override when/if the user's changes are committed.
191 public interface CheckSaveListener {
192 // Invoked when importance has changed and the NotificationInfo wants to try to save it.
193 // Listener should run saveImportance unless the change should be canceled.
Eliot Courtney47098cb2017-10-18 17:30:30 +0900194 void checkSave(Runnable saveImportance, StatusBarNotification sbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400195 }
196
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500197 public interface OnSettingsClickListener {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500198 void onClick(View v, NotificationChannel channel, int appUid);
Mady Mellor87d79452017-01-10 11:52:52 -0800199 }
200
Julia Reynolds3aedded2017-03-31 14:42:09 -0400201 public interface OnAppSettingsClickListener {
202 void onClick(View v, Intent intent);
203 }
204
Rohan Shah524cf7b2018-03-15 14:40:02 -0700205 @VisibleForTesting
206 void bindNotification(
207 final PackageManager pm,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500208 final INotificationManager iNotificationManager,
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500209 final String pkg,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500210 final NotificationChannel notificationChannel,
Rohan Shahca0447e2018-03-30 15:18:27 -0700211 final int numUniqueChannelsInRow,
Julia Reynolds3aedded2017-03-31 14:42:09 -0400212 final StatusBarNotification sbn,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500213 final CheckSaveListener checkSaveListener,
214 final OnSettingsClickListener onSettingsClick,
215 final OnAppSettingsClickListener onAppSettingsClick,
Julia Reynolds35765d82018-08-17 11:39:19 -0400216 boolean isDeviceProvisioned,
Gus Prevas9abc5062018-10-31 16:11:04 -0400217 boolean isNonblockable,
Gus Prevascaed15c2019-01-18 14:19:51 -0500218 int importance,
219 boolean wasShownHighPriority)
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500220 throws RemoteException {
Rohan Shahca0447e2018-03-30 15:18:27 -0700221 bindNotification(pm, iNotificationManager, pkg, notificationChannel,
222 numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
Julia Reynolds35765d82018-08-17 11:39:19 -0400223 onAppSettingsClick, isDeviceProvisioned, isNonblockable,
Gus Prevas82ad0592018-11-28 14:27:40 -0500224 false /* isBlockingHelper */, false /* isUserSentimentNegative */,
Gus Prevascaed15c2019-01-18 14:19:51 -0500225 importance, wasShownHighPriority);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500226 }
227
Rohan Shah524cf7b2018-03-15 14:40:02 -0700228 public void bindNotification(
229 PackageManager pm,
230 INotificationManager iNotificationManager,
231 String pkg,
232 NotificationChannel notificationChannel,
Rohan Shahca0447e2018-03-30 15:18:27 -0700233 int numUniqueChannelsInRow,
Rohan Shah524cf7b2018-03-15 14:40:02 -0700234 StatusBarNotification sbn,
235 CheckSaveListener checkSaveListener,
236 OnSettingsClickListener onSettingsClick,
237 OnAppSettingsClickListener onAppSettingsClick,
Julia Reynolds35765d82018-08-17 11:39:19 -0400238 boolean isDeviceProvisioned,
Rohan Shah63411fc2018-03-28 19:05:52 -0700239 boolean isNonblockable,
Rohan Shah524cf7b2018-03-15 14:40:02 -0700240 boolean isForBlockingHelper,
Gus Prevas9abc5062018-10-31 16:11:04 -0400241 boolean isUserSentimentNegative,
Gus Prevascaed15c2019-01-18 14:19:51 -0500242 int importance,
243 boolean wasShownHighPriority)
Rohan Shah524cf7b2018-03-15 14:40:02 -0700244 throws RemoteException {
Mady Mellor87d79452017-01-10 11:52:52 -0800245 mINotificationManager = iNotificationManager;
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700246 mMetricsLogger = Dependency.get(MetricsLogger.class);
Rohan Shahca0447e2018-03-30 15:18:27 -0700247 mPackageName = pkg;
248 mNumUniqueChannelsInRow = numUniqueChannelsInRow;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400249 mSbn = sbn;
250 mPm = pm;
251 mAppSettingsClickListener = onAppSettingsClick;
Rohan Shahca0447e2018-03-30 15:18:27 -0700252 mAppName = mPackageName;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500253 mCheckSaveListener = checkSaveListener;
254 mOnSettingsClickListener = onSettingsClick;
255 mSingleNotificationChannel = notificationChannel;
Gus Prevascaed15c2019-01-18 14:19:51 -0500256 mStartingChannelImportance = mSingleNotificationChannel.getImportance();
257 mWasShownHighPriority = wasShownHighPriority;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700258 mNegativeUserSentiment = isUserSentimentNegative;
Rohan Shah63411fc2018-03-28 19:05:52 -0700259 mIsNonblockable = isNonblockable;
Julia Reynoldse0341482018-03-08 14:42:50 -0500260 mIsForeground =
261 (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700262 mIsForBlockingHelper = isForBlockingHelper;
Rohan Shahdbd64e72018-03-28 14:46:50 -0700263 mAppUid = mSbn.getUid();
Julia Reynolds268647a2018-10-25 16:54:27 -0400264 mDelegatePkg = mSbn.getOpPkg();
Julia Reynolds35765d82018-08-17 11:39:19 -0400265 mIsDeviceProvisioned = isDeviceProvisioned;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500266
Julia Reynolds437cdb12018-01-03 12:27:24 -0500267 int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400268 pkg, mAppUid, false /* includeDeleted */);
Rohan Shahca0447e2018-03-30 15:18:27 -0700269 if (mNumUniqueChannelsInRow == 0) {
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400270 throw new IllegalArgumentException("bindNotification requires at least one channel");
271 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500272 // Special behavior for the Default channel if no other channels have been defined.
Rohan Shahca0447e2018-03-30 15:18:27 -0700273 mIsSingleDefaultChannel = mNumUniqueChannelsInRow == 1
Rohan Shahdbd64e72018-03-28 14:46:50 -0700274 && mSingleNotificationChannel.getId().equals(
275 NotificationChannel.DEFAULT_CHANNEL_ID)
276 && numTotalChannels == 1;
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400277 }
278
Julia Reynolds437cdb12018-01-03 12:27:24 -0500279 bindHeader();
280 bindPrompt();
281 bindButtons();
Eyal Posenera9cf9c72018-12-18 16:23:54 +0200282
Will Brockmana399f022019-01-30 10:59:36 -0500283 mMetricsLogger.write(notificationControlsLogMaker());
Julia Reynolds437cdb12018-01-03 12:27:24 -0500284 }
285
Will Brockmana399f022019-01-30 10:59:36 -0500286
287
Julia Reynolds437cdb12018-01-03 12:27:24 -0500288 private void bindHeader() throws RemoteException {
289 // Package name
290 Drawable pkgicon = null;
291 ApplicationInfo info;
292 try {
Rohan Shahca0447e2018-03-30 15:18:27 -0700293 info = mPm.getApplicationInfo(
294 mPackageName,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500295 PackageManager.MATCH_UNINSTALLED_PACKAGES
296 | PackageManager.MATCH_DISABLED_COMPONENTS
297 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
298 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
299 if (info != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500300 mAppName = String.valueOf(mPm.getApplicationLabel(info));
301 pkgicon = mPm.getApplicationIcon(info);
Geoffrey Pitschee8c81e2017-03-23 11:38:56 -0400302 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500303 } catch (PackageManager.NameNotFoundException e) {
304 // app is gone, just show package name and generic icon
305 pkgicon = mPm.getDefaultActivityIcon();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500306 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500307 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400308 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
Mady Mellor87d79452017-01-10 11:52:52 -0800309
Julia Reynolds268647a2018-10-25 16:54:27 -0400310 // Delegate
311 bindDelegate();
Daniel Sandlerd0a52b62018-10-31 20:13:22 +0000312
313 // Settings button.
314 final View settingsButton = findViewById(R.id.info);
315 if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
316 settingsButton.setVisibility(View.VISIBLE);
317 final int appUidF = mAppUid;
318 settingsButton.setOnClickListener(
319 (View view) -> {
320 logBlockingHelperCounter(
321 NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
322 mOnSettingsClickListener.onClick(view,
323 mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
324 appUidF);
325 });
326 } else {
327 settingsButton.setVisibility(View.GONE);
328 }
329 }
330
Julia Reynolds268647a2018-10-25 16:54:27 -0400331 private void bindPrompt() throws RemoteException {
Daniel Sandlerd0a52b62018-10-31 20:13:22 +0000332 final TextView blockPrompt = findViewById(R.id.block_prompt);
333 bindName();
Julia Reynolds268647a2018-10-25 16:54:27 -0400334 bindGroup();
Daniel Sandlerd0a52b62018-10-31 20:13:22 +0000335 if (mIsNonblockable) {
336 blockPrompt.setText(R.string.notification_unblockable_desc);
337 } else {
338 if (mNegativeUserSentiment) {
339 blockPrompt.setText(R.string.inline_blocking_helper);
340 } else if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
341 blockPrompt.setText(R.string.inline_keep_showing_app);
342 } else {
343 blockPrompt.setText(R.string.inline_keep_showing);
344 }
345 }
346 }
347
348 private void bindName() {
349 final TextView channelName = findViewById(R.id.channel_name);
350 if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
351 channelName.setVisibility(View.GONE);
352 } else {
353 channelName.setText(mSingleNotificationChannel.getName());
354 }
Julia Reynoldsac98aea2018-10-25 16:54:27 -0400355 }
356
Julia Reynolds268647a2018-10-25 16:54:27 -0400357 private void bindDelegate() {
358 TextView delegateView = findViewById(R.id.delegate_name);
359 TextView dividerView = findViewById(R.id.pkg_divider);
360
361 CharSequence delegatePkg = null;
362 if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
363 // this notification was posted by a delegate!
364 ApplicationInfo info;
365 try {
366 info = mPm.getApplicationInfo(
367 mDelegatePkg,
368 PackageManager.MATCH_UNINSTALLED_PACKAGES
369 | PackageManager.MATCH_DISABLED_COMPONENTS
370 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
371 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
372 if (info != null) {
373 delegatePkg = String.valueOf(mPm.getApplicationLabel(info));
374 }
375 } catch (PackageManager.NameNotFoundException e) { }
376 }
377 if (delegatePkg != null) {
378 delegateView.setText(mContext.getResources().getString(
379 R.string.notification_delegate_header, delegatePkg));
380 delegateView.setVisibility(View.VISIBLE);
381 dividerView.setVisibility(View.VISIBLE);
382 } else {
383 delegateView.setVisibility(View.GONE);
384 dividerView.setVisibility(View.GONE);
385 }
386 }
387
388 private void bindGroup() throws RemoteException {
389 // Set group information if this channel has an associated group.
390 CharSequence groupName = null;
391 if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
392 final NotificationChannelGroup notificationChannelGroup =
393 mINotificationManager.getNotificationChannelGroupForPackage(
394 mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
395 if (notificationChannelGroup != null) {
396 groupName = notificationChannelGroup.getName();
397 }
398 }
399 TextView groupNameView = findViewById(R.id.group_name);
400 TextView groupDividerView = findViewById(R.id.pkg_group_divider);
401 if (groupName != null) {
402 groupNameView.setText(groupName);
403 groupNameView.setVisibility(View.VISIBLE);
404 groupDividerView.setVisibility(View.VISIBLE);
405 } else {
406 groupNameView.setVisibility(View.GONE);
407 groupDividerView.setVisibility(View.GONE);
408 }
409 }
410
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700411 @VisibleForTesting
412 void logBlockingHelperCounter(String counterTag) {
413 if (mIsForBlockingHelper) {
414 mMetricsLogger.count(counterTag, 1);
415 }
416 }
417
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400418 private boolean hasImportanceChanged() {
Gus Prevas9abc5062018-10-31 16:11:04 -0400419 return mSingleNotificationChannel != null
Gus Prevascaed15c2019-01-18 14:19:51 -0500420 && mChosenImportance != null
421 && (mStartingChannelImportance != mChosenImportance
422 || (mWasShownHighPriority && mChosenImportance < IMPORTANCE_DEFAULT)
423 || (!mWasShownHighPriority && mChosenImportance >= IMPORTANCE_DEFAULT));
Mady Mellor87d79452017-01-10 11:52:52 -0800424 }
425
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500426 private void saveImportance() {
Gus Prevas894d9152018-11-12 13:51:40 -0500427 if (!mIsNonblockable
428 || mExitReason != NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS) {
Gus Prevascaed15c2019-01-18 14:19:51 -0500429 if (mChosenImportance == null) {
430 mChosenImportance = mStartingChannelImportance;
431 }
Gus Prevas533836a2018-09-24 17:15:32 -0400432 updateImportance();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500433 }
Rohan Shahca0447e2018-03-30 15:18:27 -0700434 }
435
436 /**
437 * Commits the updated importance values on the background thread.
438 */
439 private void updateImportance() {
Gus Prevascaed15c2019-01-18 14:19:51 -0500440 if (mChosenImportance != null) {
441 mMetricsLogger.write(importanceChangeLogMaker());
Rohan Shahca0447e2018-03-30 15:18:27 -0700442
Gus Prevascaed15c2019-01-18 14:19:51 -0500443 Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
444 bgHandler.post(
445 new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
446 mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
447 mStartingChannelImportance, mChosenImportance));
448 }
Mady Mellor87d79452017-01-10 11:52:52 -0800449 }
450
Julia Reynolds437cdb12018-01-03 12:27:24 -0500451 private void bindButtons() {
Rohan Shah524cf7b2018-03-15 14:40:02 -0700452 findViewById(R.id.undo).setOnClickListener(mOnUndo);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500453
Gus Prevas82ad0592018-11-28 14:27:40 -0500454 boolean showInterruptivenessSettings =
455 !mIsNonblockable
456 && !mIsForeground
457 && !mIsForBlockingHelper
458 && NotificationUtils.useNewInterruptionModel(mContext);
459 if (showInterruptivenessSettings) {
460 findViewById(R.id.block_or_minimize).setVisibility(GONE);
461 findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE);
462 View block = findViewById(R.id.int_block);
463 TextView silent = findViewById(R.id.int_silent);
464 TextView alert = findViewById(R.id.int_alert);
465
Gus Prevas82ad0592018-11-28 14:27:40 -0500466 block.setOnClickListener(mOnStopOrMinimizeNotifications);
Gus Prevascaed15c2019-01-18 14:19:51 -0500467 if (mWasShownHighPriority) {
Gus Prevas82ad0592018-11-28 14:27:40 -0500468 silent.setOnClickListener(mOnToggleSilent);
469 silent.setText(R.string.inline_silent_button_silent);
470 alert.setOnClickListener(mOnKeepShowing);
471 alert.setText(R.string.inline_silent_button_keep_alerting);
472 } else {
473 silent.setOnClickListener(mOnKeepShowing);
474 silent.setText(R.string.inline_silent_button_stay_silent);
475 alert.setOnClickListener(mOnToggleSilent);
476 alert.setText(R.string.inline_silent_button_alert);
477 }
Mady Mellor87d79452017-01-10 11:52:52 -0800478 } else {
Gus Prevas82ad0592018-11-28 14:27:40 -0500479 findViewById(R.id.block_or_minimize).setVisibility(VISIBLE);
480 findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
481 View block = findViewById(R.id.block);
482 TextView keep = findViewById(R.id.keep);
483 View minimize = findViewById(R.id.minimize);
484
485 block.setOnClickListener(mOnStopOrMinimizeNotifications);
486 keep.setOnClickListener(mOnKeepShowing);
487 minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
488
489 if (mIsNonblockable) {
490 keep.setText(android.R.string.ok);
491 block.setVisibility(GONE);
492 minimize.setVisibility(GONE);
493 } else if (mIsForeground) {
494 block.setVisibility(GONE);
495 minimize.setVisibility(VISIBLE);
496 } else {
497 block.setVisibility(VISIBLE);
498 minimize.setVisibility(GONE);
499 }
500
501 // Set up app settings link (i.e. Customize)
502 TextView settingsLinkView = findViewById(R.id.app_settings);
503 Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName,
504 mSingleNotificationChannel,
505 mSbn.getId(), mSbn.getTag());
506 if (!mIsForBlockingHelper
507 && settingsIntent != null
508 && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
509 settingsLinkView.setVisibility(VISIBLE);
510 settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
511 settingsLinkView.setOnClickListener((View view) -> {
512 mAppSettingsClickListener.onClick(view, settingsIntent);
513 });
514 } else {
515 settingsLinkView.setVisibility(View.GONE);
516 }
Mady Mellor87d79452017-01-10 11:52:52 -0800517 }
518 }
519
Gus Prevas894d9152018-11-12 13:51:40 -0500520 private void swapContent(@NotificationInfoAction int action, boolean animate) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500521 if (mExpandAnimation != null) {
522 mExpandAnimation.cancel();
523 }
Mady Mellor87d79452017-01-10 11:52:52 -0800524
Julia Reynoldse0341482018-03-08 14:42:50 -0500525 View prompt = findViewById(R.id.prompt);
526 ViewGroup confirmation = findViewById(R.id.confirmation);
527 TextView confirmationText = findViewById(R.id.confirmation_text);
528 View header = findViewById(R.id.header);
529
Gus Prevas9abc5062018-10-31 16:11:04 -0400530 switch (action) {
Gus Prevas894d9152018-11-12 13:51:40 -0500531 case ACTION_UNDO:
Gus Prevas9abc5062018-10-31 16:11:04 -0400532 mChosenImportance = mStartingChannelImportance;
533 break;
Gus Prevas894d9152018-11-12 13:51:40 -0500534 case ACTION_TOGGLE_SILENT:
535 mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
Gus Prevascaed15c2019-01-18 14:19:51 -0500536 if (mWasShownHighPriority) {
Gus Prevas9abc5062018-10-31 16:11:04 -0400537 mChosenImportance = IMPORTANCE_LOW;
538 confirmationText.setText(R.string.notification_channel_silenced);
539 } else {
540 mChosenImportance = IMPORTANCE_HIGH;
541 confirmationText.setText(R.string.notification_channel_unsilenced);
542 }
543 break;
Gus Prevas894d9152018-11-12 13:51:40 -0500544 case ACTION_BLOCK:
545 mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
Gus Prevas9abc5062018-10-31 16:11:04 -0400546 if (mIsForeground) {
547 mChosenImportance = IMPORTANCE_MIN;
548 confirmationText.setText(R.string.notification_channel_minimized);
549 } else {
550 mChosenImportance = IMPORTANCE_NONE;
551 confirmationText.setText(R.string.notification_channel_disabled);
552 }
553 break;
554 default:
555 throw new IllegalArgumentException();
Julia Reynolds437cdb12018-01-03 12:27:24 -0500556 }
557
Gus Prevas894d9152018-11-12 13:51:40 -0500558 boolean isUndo = action == ACTION_UNDO;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500559
Gus Prevas9abc5062018-10-31 16:11:04 -0400560 prompt.setVisibility(isUndo ? VISIBLE : GONE);
561 confirmation.setVisibility(isUndo ? GONE : VISIBLE);
562 header.setVisibility(isUndo ? VISIBLE : GONE);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500563
Gus Prevas894d9152018-11-12 13:51:40 -0500564 if (animate) {
565 ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
566 prompt.getAlpha(), isUndo ? 1f : 0f);
567 promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
568 ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
569 confirmation.getAlpha(), isUndo ? 0f : 1f);
570 confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500571
Gus Prevas894d9152018-11-12 13:51:40 -0500572 mExpandAnimation = new AnimatorSet();
573 mExpandAnimation.playTogether(promptAnim, confirmAnim);
574 mExpandAnimation.setDuration(150);
575 mExpandAnimation.addListener(new AnimatorListenerAdapter() {
576 boolean mCancelled = false;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500577
Gus Prevas894d9152018-11-12 13:51:40 -0500578 @Override
579 public void onAnimationCancel(Animator animation) {
580 mCancelled = true;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500581 }
Gus Prevas894d9152018-11-12 13:51:40 -0500582
583 @Override
584 public void onAnimationEnd(Animator animation) {
585 if (!mCancelled) {
586 prompt.setVisibility(isUndo ? VISIBLE : GONE);
587 confirmation.setVisibility(isUndo ? GONE : VISIBLE);
588 }
589 }
590 });
591 mExpandAnimation.start();
592 }
Rohan Shah142e2da2018-06-14 13:14:18 -0700593
594 // Since we're swapping/update the content, reset the timeout so the UI can't close
595 // immediately after the update.
596 if (mGutsContainer != null) {
597 mGutsContainer.resetFalsingCheck();
598 }
Mady Mellor87d79452017-01-10 11:52:52 -0800599 }
600
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400601 @Override
Gus Prevas9abc5062018-10-31 16:11:04 -0400602 public void onFinishedClosing() {
Gus Prevascaed15c2019-01-18 14:19:51 -0500603 if (mChosenImportance != null) {
604 mStartingChannelImportance = mChosenImportance;
Gus Prevas9abc5062018-10-31 16:11:04 -0400605 }
606 mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
607
608 View prompt = findViewById(R.id.prompt);
609 ViewGroup confirmation = findViewById(R.id.confirmation);
610 View header = findViewById(R.id.header);
611 prompt.setVisibility(VISIBLE);
612 prompt.setAlpha(1f);
613 confirmation.setVisibility(GONE);
614 confirmation.setAlpha(1f);
615 header.setVisibility(VISIBLE);
616 header.setAlpha(1f);
Will Brockmana399f022019-01-30 10:59:36 -0500617
618 mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE));
Gus Prevas9abc5062018-10-31 16:11:04 -0400619 }
620
621 @Override
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400622 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
623 super.onInitializeAccessibilityEvent(event);
624 if (mGutsContainer != null &&
625 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
626 if (mGutsContainer.isExposed()) {
627 event.getText().add(mContext.getString(
628 R.string.notification_channel_controls_opened_accessibility, mAppName));
629 } else {
630 event.getText().add(mContext.getString(
631 R.string.notification_channel_controls_closed_accessibility, mAppName));
632 }
633 }
634 }
635
Julia Reynolds3aedded2017-03-31 14:42:09 -0400636 private Intent getAppSettingsIntent(PackageManager pm, String packageName,
637 NotificationChannel channel, int id, String tag) {
638 Intent intent = new Intent(Intent.ACTION_MAIN)
639 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
640 .setPackage(packageName);
641 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
642 intent,
643 PackageManager.MATCH_DEFAULT_ONLY
644 );
645 if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
646 return null;
647 }
648 final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
649 intent.setClassName(activityInfo.packageName, activityInfo.name);
650 if (channel != null) {
651 intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
652 }
653 intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
654 intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
655 return intent;
656 }
657
Rohan Shahca0447e2018-03-30 15:18:27 -0700658 /**
659 * Closes the controls and commits the updated importance values (indirectly). If this view is
660 * being used to show the blocking helper, this will immediately dismiss the blocking helper and
661 * commit the updated importance.
662 *
663 * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
664 * user does not have the ability to undo the action anymore. See {@link #swapContent(boolean)}
665 * for where undo is handled.
666 */
Rohan Shah524cf7b2018-03-15 14:40:02 -0700667 @VisibleForTesting
668 void closeControls(View v) {
Rohan Shahda5dcdd2018-04-27 17:21:50 -0700669 int[] parentLoc = new int[2];
670 int[] targetLoc = new int[2];
671 mGutsContainer.getLocationOnScreen(parentLoc);
672 v.getLocationOnScreen(targetLoc);
673 final int centerX = v.getWidth() / 2;
674 final int centerY = v.getHeight() / 2;
675 final int x = targetLoc[0] - parentLoc[0] + centerX;
676 final int y = targetLoc[1] - parentLoc[1] + centerY;
677 mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500678 }
679
Mady Mellor87d79452017-01-10 11:52:52 -0800680 @Override
Mady Mellor95d743c2017-01-10 12:05:27 -0800681 public void setGutsParent(NotificationGuts guts) {
682 mGutsContainer = guts;
Mady Mellor87d79452017-01-10 11:52:52 -0800683 }
684
685 @Override
Mady Mellor434180c2017-02-13 11:29:42 -0800686 public boolean willBeRemoved() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500687 return hasImportanceChanged();
Mady Mellor434180c2017-02-13 11:29:42 -0800688 }
689
690 @Override
Lucas Dupin9b08c012018-05-16 19:53:32 -0700691 public boolean shouldBeSaved() {
692 return hasImportanceChanged();
693 }
694
695 @Override
Mady Mellor87d79452017-01-10 11:52:52 -0800696 public View getContentView() {
697 return this;
698 }
699
700 @Override
Mady Mellorc2dbe492017-03-30 13:22:03 -0700701 public boolean handleCloseControls(boolean save, boolean force) {
Julia Reynoldsc65656a2018-02-12 09:55:14 -0500702 // Save regardless of the importance so we can lock the importance field if the user wants
703 // to keep getting notifications
704 if (save) {
Rohan Shahca0447e2018-03-30 15:18:27 -0700705 saveImportance();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500706 }
Rohan Shahdd588c72018-05-09 20:32:15 -0700707 logBlockingHelperCounter(mExitReason);
Mady Mellor87d79452017-01-10 11:52:52 -0800708 return false;
709 }
Mady Mellore09fb702017-03-30 13:23:29 -0700710
711 @Override
712 public int getActualHeight() {
713 return getHeight();
714 }
Rohan Shahca0447e2018-03-30 15:18:27 -0700715
Gus Prevas533836a2018-09-24 17:15:32 -0400716 @VisibleForTesting
717 public boolean isAnimating() {
718 return mExpandAnimation != null && mExpandAnimation.isRunning();
719 }
720
Rohan Shahca0447e2018-03-30 15:18:27 -0700721 /**
722 * Runnable to either update the given channel (with a new importance value) or, if no channel
723 * is provided, update notifications enabled state for the package.
724 */
725 private static class UpdateImportanceRunnable implements Runnable {
726 private final INotificationManager mINotificationManager;
727 private final String mPackageName;
728 private final int mAppUid;
729 private final @Nullable NotificationChannel mChannelToUpdate;
730 private final int mCurrentImportance;
731 private final int mNewImportance;
732
733
734 public UpdateImportanceRunnable(INotificationManager notificationManager,
735 String packageName, int appUid, @Nullable NotificationChannel channelToUpdate,
736 int currentImportance, int newImportance) {
737 mINotificationManager = notificationManager;
738 mPackageName = packageName;
739 mAppUid = appUid;
740 mChannelToUpdate = channelToUpdate;
741 mCurrentImportance = currentImportance;
742 mNewImportance = newImportance;
743 }
744
745 @Override
746 public void run() {
747 try {
748 if (mChannelToUpdate != null) {
749 mChannelToUpdate.setImportance(mNewImportance);
750 mChannelToUpdate.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
751 mINotificationManager.updateNotificationChannelForPackage(
752 mPackageName, mAppUid, mChannelToUpdate);
753 } else {
754 // For notifications with more than one channel, update notification enabled
755 // state. If the importance was lowered, we disable notifications.
Rohan Shah590e1b22018-04-10 23:48:47 -0400756 mINotificationManager.setNotificationsEnabledWithImportanceLockForPackage(
Rohan Shahca0447e2018-03-30 15:18:27 -0700757 mPackageName, mAppUid, mNewImportance >= mCurrentImportance);
758 }
759 } catch (RemoteException e) {
760 Log.e(TAG, "Unable to update notification importance", e);
761 }
762 }
763 }
Eyal Posenera9cf9c72018-12-18 16:23:54 +0200764
Will Brockmana399f022019-01-30 10:59:36 -0500765 /**
766 * Returns a LogMaker with all available notification information.
767 * Caller should set category, type, and maybe subtype, before passing it to mMetricsLogger.
768 * @return LogMaker
769 */
Eyal Posenera9cf9c72018-12-18 16:23:54 +0200770 private LogMaker getLogMaker() {
Will Brockmana399f022019-01-30 10:59:36 -0500771 // The constructor requires a category, so also do it in the other branch for consistency.
772 return mSbn == null ? new LogMaker(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
773 : mSbn.getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
774 }
775
776 /**
777 * Returns an initialized LogMaker for logging importance changes.
778 * The caller may override the type before passing it to mMetricsLogger.
779 * @return LogMaker
780 */
781 private LogMaker importanceChangeLogMaker() {
782 Integer chosenImportance =
783 mChosenImportance != null ? mChosenImportance : mStartingChannelImportance;
784 return getLogMaker().setCategory(MetricsEvent.ACTION_SAVE_IMPORTANCE)
785 .setType(MetricsEvent.TYPE_ACTION)
786 .setSubtype(chosenImportance - mStartingChannelImportance);
787 }
788
789 /**
790 * Returns an initialized LogMaker for logging open/close of the info display.
791 * The caller may override the type before passing it to mMetricsLogger.
792 * @return LogMaker
793 */
794 private LogMaker notificationControlsLogMaker() {
795 return getLogMaker().setCategory(MetricsEvent.ACTION_NOTE_CONTROLS)
796 .setType(MetricsEvent.TYPE_OPEN)
797 .setSubtype(mIsForBlockingHelper ? MetricsEvent.BLOCKING_HELPER_DISPLAY
798 : MetricsEvent.BLOCKING_HELPER_UNKNOWN);
Eyal Posenera9cf9c72018-12-18 16:23:54 +0200799 }
Mady Mellor87d79452017-01-10 11:52:52 -0800800}