blob: 6279fdc4659990ee27f1fa8205013aa35506b120 [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 Reynolds3aedded2017-03-31 14:42:09 -040019import static android.app.NotificationManager.IMPORTANCE_NONE;
20
Julia Reynolds437cdb12018-01-03 12:27:24 -050021import android.animation.Animator;
22import android.animation.AnimatorListenerAdapter;
23import android.animation.AnimatorSet;
24import android.animation.ObjectAnimator;
Mady Mellor87d79452017-01-10 11:52:52 -080025import android.app.INotificationManager;
Julia Reynolds3aedded2017-03-31 14:42:09 -040026import android.app.Notification;
Mady Mellor87d79452017-01-10 11:52:52 -080027import android.app.NotificationChannel;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -050028import android.app.NotificationChannelGroup;
Mady Mellor87d79452017-01-10 11:52:52 -080029import android.content.Context;
Julia Reynolds3aedded2017-03-31 14:42:09 -040030import android.content.Intent;
31import android.content.pm.ActivityInfo;
Mady Mellor87d79452017-01-10 11:52:52 -080032import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageInfo;
34import 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;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -040042import android.view.accessibility.AccessibilityEvent;
Mady Mellor87d79452017-01-10 11:52:52 -080043import android.widget.ImageView;
44import android.widget.LinearLayout;
Mady Mellor87d79452017-01-10 11:52:52 -080045import android.widget.TextView;
46
47import com.android.internal.logging.MetricsLogger;
48import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
49import com.android.settingslib.Utils;
Julia Reynolds437cdb12018-01-03 12:27:24 -050050import com.android.systemui.Interpolators;
Mady Mellor87d79452017-01-10 11:52:52 -080051import com.android.systemui.R;
Mady Mellor87d79452017-01-10 11:52:52 -080052
Geoffrey Pitschd0856f02017-02-16 10:51:18 -050053import java.lang.IllegalArgumentException;
54import java.util.List;
Mady Mellor87d79452017-01-10 11:52:52 -080055import java.util.Set;
56
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;
74 private boolean mNonblockable;
75 private StatusBarNotification mSbn;
76 private AnimatorSet mExpandAnimation;
Mady Mellor87d79452017-01-10 11:52:52 -080077
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -040078 private CheckSaveListener mCheckSaveListener;
Julia Reynolds437cdb12018-01-03 12:27:24 -050079 private OnSettingsClickListener mOnSettingsClickListener;
Julia Reynolds3aedded2017-03-31 14:42:09 -040080 private OnAppSettingsClickListener mAppSettingsClickListener;
Mady Mellor95d743c2017-01-10 12:05:27 -080081 private NotificationGuts mGutsContainer;
Mady Mellor87d79452017-01-10 11:52:52 -080082
Julia Reynolds437cdb12018-01-03 12:27:24 -050083 private OnClickListener mOnKeepShowing = v -> {
84 closeControls(v);
85 };
86
87 private OnClickListener mOnStopNotifications = v -> {
88 swapContent(false);
89 };
90
91 private OnClickListener mOnUndo = v -> {
92 swapContent(true);
93 };
94
Mady Mellor87d79452017-01-10 11:52:52 -080095 public NotificationInfo(Context context, AttributeSet attrs) {
96 super(context, attrs);
97 }
98
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -040099 // Specify a CheckSaveListener to override when/if the user's changes are committed.
100 public interface CheckSaveListener {
101 // Invoked when importance has changed and the NotificationInfo wants to try to save it.
102 // Listener should run saveImportance unless the change should be canceled.
Eliot Courtney47098cb2017-10-18 17:30:30 +0900103 void checkSave(Runnable saveImportance, StatusBarNotification sbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400104 }
105
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500106 public interface OnSettingsClickListener {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500107 void onClick(View v, NotificationChannel channel, int appUid);
Mady Mellor87d79452017-01-10 11:52:52 -0800108 }
109
Julia Reynolds3aedded2017-03-31 14:42:09 -0400110 public interface OnAppSettingsClickListener {
111 void onClick(View v, Intent intent);
112 }
113
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500114 public void bindNotification(final PackageManager pm,
115 final INotificationManager iNotificationManager,
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500116 final String pkg,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500117 final NotificationChannel notificationChannel,
118 final int numChannels,
Julia Reynolds3aedded2017-03-31 14:42:09 -0400119 final StatusBarNotification sbn,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500120 final CheckSaveListener checkSaveListener,
121 final OnSettingsClickListener onSettingsClick,
122 final OnAppSettingsClickListener onAppSettingsClick,
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400123 final Set<String> nonBlockablePkgs)
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500124 throws RemoteException {
Mady Mellor87d79452017-01-10 11:52:52 -0800125 mINotificationManager = iNotificationManager;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500126 mPkg = pkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500127 mNumNotificationChannels = numChannels;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400128 mSbn = sbn;
129 mPm = pm;
130 mAppSettingsClickListener = onAppSettingsClick;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400131 mAppName = mPkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500132 mCheckSaveListener = checkSaveListener;
133 mOnSettingsClickListener = onSettingsClick;
134 mSingleNotificationChannel = notificationChannel;
135 mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500136
Julia Reynolds437cdb12018-01-03 12:27:24 -0500137 int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400138 pkg, mAppUid, false /* includeDeleted */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500139 if (mNumNotificationChannels == 0) {
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400140 throw new IllegalArgumentException("bindNotification requires at least one channel");
141 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500142 // Special behavior for the Default channel if no other channels have been defined.
143 mIsSingleDefaultChannel = mNumNotificationChannels == 1
144 && mSingleNotificationChannel.getId()
145 .equals(NotificationChannel.DEFAULT_CHANNEL_ID)
146 && numTotalChannels <= 1;
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400147 }
148
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400149 try {
150 final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
151 if (Utils.isSystemPackage(getResources(), pm, pkgInfo)) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500152 if (mSingleNotificationChannel != null
153 && !mSingleNotificationChannel.isBlockableSystem()) {
154 mNonblockable = true;
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400155 }
156 }
157 } catch (PackageManager.NameNotFoundException e) {
158 // unlikely.
159 }
160 if (nonBlockablePkgs != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500161 mNonblockable |= nonBlockablePkgs.contains(pkg);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400162 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500163 mNonblockable |= (mNumNotificationChannels > 1);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400164
Julia Reynolds437cdb12018-01-03 12:27:24 -0500165 bindHeader();
166 bindPrompt();
167 bindButtons();
168 }
169
170 private void bindHeader() throws RemoteException {
171 // Package name
172 Drawable pkgicon = null;
173 ApplicationInfo info;
174 try {
175 info = mPm.getApplicationInfo(mPkg,
176 PackageManager.MATCH_UNINSTALLED_PACKAGES
177 | PackageManager.MATCH_DISABLED_COMPONENTS
178 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
179 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
180 if (info != null) {
181 mAppUid = mSbn.getUid();
182 mAppName = String.valueOf(mPm.getApplicationLabel(info));
183 pkgicon = mPm.getApplicationIcon(info);
Geoffrey Pitschee8c81e2017-03-23 11:38:56 -0400184 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500185 } catch (PackageManager.NameNotFoundException e) {
186 // app is gone, just show package name and generic icon
187 pkgicon = mPm.getDefaultActivityIcon();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500188 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500189 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400190 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
Mady Mellor87d79452017-01-10 11:52:52 -0800191
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500192 // Set group information if this channel has an associated group.
193 CharSequence groupName = null;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500194 if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
195 final NotificationChannelGroup notificationChannelGroup =
Julia Reynolds437cdb12018-01-03 12:27:24 -0500196 mINotificationManager.getNotificationChannelGroupForPackage(
197 mSingleNotificationChannel.getGroup(), mPkg, mAppUid);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500198 if (notificationChannelGroup != null) {
199 groupName = notificationChannelGroup.getName();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500200 }
Mady Mellor87d79452017-01-10 11:52:52 -0800201 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500202 TextView groupNameView = findViewById(R.id.group_name);
203 TextView groupDividerView = findViewById(R.id.pkg_group_divider);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500204 if (groupName != null) {
205 groupNameView.setText(groupName);
206 groupNameView.setVisibility(View.VISIBLE);
207 groupDividerView.setVisibility(View.VISIBLE);
208 } else {
209 groupNameView.setVisibility(View.GONE);
210 groupDividerView.setVisibility(View.GONE);
211 }
Mady Mellor87d79452017-01-10 11:52:52 -0800212
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500213 // Settings button.
Julia Reynolds437cdb12018-01-03 12:27:24 -0500214 final View settingsButton = findViewById(R.id.info);
215 if (mAppUid >= 0 && mOnSettingsClickListener != null) {
Geoffrey Pitsch029a3fa2017-03-30 13:01:57 -0400216 settingsButton.setVisibility(View.VISIBLE);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500217 final int appUidF = mAppUid;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500218 settingsButton.setOnClickListener(
219 (View view) -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500220 mOnSettingsClickListener.onClick(view,
221 mNumNotificationChannels > 1 ? null : mSingleNotificationChannel,
222 appUidF);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500223 });
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500224 } else {
225 settingsButton.setVisibility(View.GONE);
226 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500227 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500228
Julia Reynolds437cdb12018-01-03 12:27:24 -0500229 private void bindPrompt() {
230 final TextView channelName = findViewById(R.id.channel_name);
231 final TextView blockPrompt = findViewById(R.id.block_prompt);
232 if (mNonblockable) {
233 if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
234 channelName.setVisibility(View.GONE);
235 } else {
236 channelName.setText(mSingleNotificationChannel.getName());
237 }
Julia Reynolds3aedded2017-03-31 14:42:09 -0400238
Julia Reynolds437cdb12018-01-03 12:27:24 -0500239 blockPrompt.setText(R.string.notification_unblockable_desc);
240 } else {
241 if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
242 channelName.setVisibility(View.GONE);
243 blockPrompt.setText(R.string.inline_keep_showing_app);
244 } else {
245 channelName.setText(mSingleNotificationChannel.getName());
246 blockPrompt.setText(R.string.inline_keep_showing);
247 }
248 }
Mady Mellor87d79452017-01-10 11:52:52 -0800249 }
250
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400251 private boolean hasImportanceChanged() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500252 return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
Mady Mellor87d79452017-01-10 11:52:52 -0800253 }
254
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500255 private void saveImportance() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500256 if (mNonblockable || !hasImportanceChanged()) {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500257 return;
258 }
Mady Mellor87d79452017-01-10 11:52:52 -0800259 MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500260 mChosenImportance - mStartingUserImportance);
261 mSingleNotificationChannel.setImportance(mChosenImportance);
Julia Reynolds8ceb5792017-04-11 11:32:44 -0400262 mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
Mady Mellor87d79452017-01-10 11:52:52 -0800263 try {
264 mINotificationManager.updateNotificationChannelForPackage(
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500265 mPkg, mAppUid, mSingleNotificationChannel);
Mady Mellor87d79452017-01-10 11:52:52 -0800266 } catch (RemoteException e) {
267 // :(
268 }
269 }
270
Julia Reynolds437cdb12018-01-03 12:27:24 -0500271 private void bindButtons() {
272 View block = findViewById(R.id.block);
273 block.setOnClickListener(mOnStopNotifications);
274 TextView keep = findViewById(R.id.keep);
275 keep.setOnClickListener(mOnKeepShowing);
276 findViewById(R.id.undo).setOnClickListener(mOnUndo);
277
278 if (mNonblockable) {
279 keep.setText(R.string.notification_done);
280 block.setVisibility(GONE);
281 }
282
283 // app settings link
284 TextView settingsLinkView = findViewById(R.id.app_settings);
285 Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
286 mSbn.getId(), mSbn.getTag());
287 if (settingsIntent != null
288 && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
289 settingsLinkView.setVisibility(View.VISIBLE);
290 settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
291 mSbn.getNotification().getSettingsText()));
292 settingsLinkView.setOnClickListener((View view) -> {
293 mAppSettingsClickListener.onClick(view, settingsIntent);
294 });
Mady Mellor87d79452017-01-10 11:52:52 -0800295 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500296 settingsLinkView.setVisibility(View.GONE);
Mady Mellor87d79452017-01-10 11:52:52 -0800297 }
298 }
299
Julia Reynolds437cdb12018-01-03 12:27:24 -0500300 private void swapContent(boolean showPrompt) {
301 if (mExpandAnimation != null) {
302 mExpandAnimation.cancel();
303 }
Mady Mellor87d79452017-01-10 11:52:52 -0800304
Julia Reynolds437cdb12018-01-03 12:27:24 -0500305 if (showPrompt) {
306 mChosenImportance = mStartingUserImportance;
307 } else {
308 mChosenImportance = IMPORTANCE_NONE;
309 }
310
311 View prompt = findViewById(R.id.prompt);
312 View confirmation = findViewById(R.id.confirmation);
313 ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
314 prompt.getAlpha(), showPrompt ? 1f : 0f);
315 promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
316 ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
317 confirmation.getAlpha(), showPrompt ? 0f : 1f);
318 confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
319
320 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
321 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
322
323 mExpandAnimation = new AnimatorSet();
324 mExpandAnimation.playTogether(promptAnim, confirmAnim);
325 mExpandAnimation.setDuration(150);
326 mExpandAnimation.addListener(new AnimatorListenerAdapter() {
327 boolean cancelled = false;
328
329 @Override
330 public void onAnimationCancel(Animator animation) {
331 cancelled = true;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500332 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500333
334 @Override
335 public void onAnimationEnd(Animator animation) {
336 if (!cancelled) {
337 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
338 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
339 }
340 }
Mady Mellor87d79452017-01-10 11:52:52 -0800341 });
Julia Reynolds437cdb12018-01-03 12:27:24 -0500342 mExpandAnimation.start();
Mady Mellor87d79452017-01-10 11:52:52 -0800343 }
344
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400345 @Override
346 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
347 super.onInitializeAccessibilityEvent(event);
348 if (mGutsContainer != null &&
349 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
350 if (mGutsContainer.isExposed()) {
351 event.getText().add(mContext.getString(
352 R.string.notification_channel_controls_opened_accessibility, mAppName));
353 } else {
354 event.getText().add(mContext.getString(
355 R.string.notification_channel_controls_closed_accessibility, mAppName));
356 }
357 }
358 }
359
Julia Reynolds3aedded2017-03-31 14:42:09 -0400360 private Intent getAppSettingsIntent(PackageManager pm, String packageName,
361 NotificationChannel channel, int id, String tag) {
362 Intent intent = new Intent(Intent.ACTION_MAIN)
363 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
364 .setPackage(packageName);
365 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
366 intent,
367 PackageManager.MATCH_DEFAULT_ONLY
368 );
369 if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
370 return null;
371 }
372 final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
373 intent.setClassName(activityInfo.packageName, activityInfo.name);
374 if (channel != null) {
375 intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
376 }
377 intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
378 intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
379 return intent;
380 }
381
Julia Reynolds437cdb12018-01-03 12:27:24 -0500382 private void closeControls(View v) {
383 int[] parentLoc = new int[2];
384 int[] targetLoc = new int[2];
385 mGutsContainer.getLocationOnScreen(parentLoc);
386 v.getLocationOnScreen(targetLoc);
387 final int centerX = v.getWidth() / 2;
388 final int centerY = v.getHeight() / 2;
389 final int x = targetLoc[0] - parentLoc[0] + centerX;
390 final int y = targetLoc[1] - parentLoc[1] + centerY;
391 mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
392 }
393
Mady Mellor87d79452017-01-10 11:52:52 -0800394 @Override
Mady Mellor95d743c2017-01-10 12:05:27 -0800395 public void setGutsParent(NotificationGuts guts) {
396 mGutsContainer = guts;
Mady Mellor87d79452017-01-10 11:52:52 -0800397 }
398
399 @Override
Mady Mellor434180c2017-02-13 11:29:42 -0800400 public boolean willBeRemoved() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500401 return hasImportanceChanged();
Mady Mellor434180c2017-02-13 11:29:42 -0800402 }
403
404 @Override
Mady Mellor87d79452017-01-10 11:52:52 -0800405 public View getContentView() {
406 return this;
407 }
408
409 @Override
Mady Mellorc2dbe492017-03-30 13:22:03 -0700410 public boolean handleCloseControls(boolean save, boolean force) {
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400411 if (save && hasImportanceChanged()) {
412 if (mCheckSaveListener != null) {
Eliot Courtney47098cb2017-10-18 17:30:30 +0900413 mCheckSaveListener.checkSave(this::saveImportance, mSbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400414 } else {
415 saveImportance();
416 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500417 }
Mady Mellor87d79452017-01-10 11:52:52 -0800418 return false;
419 }
Mady Mellore09fb702017-03-30 13:23:29 -0700420
421 @Override
422 public int getActualHeight() {
423 return getHeight();
424 }
Mady Mellor87d79452017-01-10 11:52:52 -0800425}