blob: 735f4fd82dec7faab5d21fa13f0e4ea4d60ae62f [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;
Julia Reynolds0ef7d842018-01-24 17:50:31 -050082 private boolean mNegativeUserSentiment;
Mady Mellor87d79452017-01-10 11:52:52 -080083
Julia Reynolds437cdb12018-01-03 12:27:24 -050084 private OnClickListener mOnKeepShowing = v -> {
85 closeControls(v);
86 };
87
88 private OnClickListener mOnStopNotifications = v -> {
89 swapContent(false);
90 };
91
92 private OnClickListener mOnUndo = v -> {
93 swapContent(true);
94 };
95
Mady Mellor87d79452017-01-10 11:52:52 -080096 public NotificationInfo(Context context, AttributeSet attrs) {
97 super(context, attrs);
98 }
99
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400100 // Specify a CheckSaveListener to override when/if the user's changes are committed.
101 public interface CheckSaveListener {
102 // Invoked when importance has changed and the NotificationInfo wants to try to save it.
103 // Listener should run saveImportance unless the change should be canceled.
Eliot Courtney47098cb2017-10-18 17:30:30 +0900104 void checkSave(Runnable saveImportance, StatusBarNotification sbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400105 }
106
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500107 public interface OnSettingsClickListener {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500108 void onClick(View v, NotificationChannel channel, int appUid);
Mady Mellor87d79452017-01-10 11:52:52 -0800109 }
110
Julia Reynolds3aedded2017-03-31 14:42:09 -0400111 public interface OnAppSettingsClickListener {
112 void onClick(View v, Intent intent);
113 }
114
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500115 public void bindNotification(final PackageManager pm,
116 final INotificationManager iNotificationManager,
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500117 final String pkg,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500118 final NotificationChannel notificationChannel,
119 final int numChannels,
Julia Reynolds3aedded2017-03-31 14:42:09 -0400120 final StatusBarNotification sbn,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500121 final CheckSaveListener checkSaveListener,
122 final OnSettingsClickListener onSettingsClick,
123 final OnAppSettingsClickListener onAppSettingsClick,
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400124 final Set<String> nonBlockablePkgs)
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500125 throws RemoteException {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500126 bindNotification(pm, iNotificationManager, pkg, notificationChannel, numChannels, sbn,
127 checkSaveListener, onSettingsClick, onAppSettingsClick, nonBlockablePkgs,
128 false /* negative sentiment */);
129 }
130
131 public void bindNotification(final PackageManager pm,
132 final INotificationManager iNotificationManager,
133 final String pkg,
134 final NotificationChannel notificationChannel,
135 final int numChannels,
136 final StatusBarNotification sbn,
137 final CheckSaveListener checkSaveListener,
138 final OnSettingsClickListener onSettingsClick,
139 final OnAppSettingsClickListener onAppSettingsClick,
140 final Set<String> nonBlockablePkgs,
141 boolean negativeUserSentiment) throws RemoteException {
Mady Mellor87d79452017-01-10 11:52:52 -0800142 mINotificationManager = iNotificationManager;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500143 mPkg = pkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500144 mNumNotificationChannels = numChannels;
Julia Reynolds3aedded2017-03-31 14:42:09 -0400145 mSbn = sbn;
146 mPm = pm;
147 mAppSettingsClickListener = onAppSettingsClick;
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400148 mAppName = mPkg;
Julia Reynolds437cdb12018-01-03 12:27:24 -0500149 mCheckSaveListener = checkSaveListener;
150 mOnSettingsClickListener = onSettingsClick;
151 mSingleNotificationChannel = notificationChannel;
152 mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500153 mNegativeUserSentiment = negativeUserSentiment;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500154
Julia Reynolds437cdb12018-01-03 12:27:24 -0500155 int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400156 pkg, mAppUid, false /* includeDeleted */);
Julia Reynolds437cdb12018-01-03 12:27:24 -0500157 if (mNumNotificationChannels == 0) {
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400158 throw new IllegalArgumentException("bindNotification requires at least one channel");
159 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500160 // Special behavior for the Default channel if no other channels have been defined.
161 mIsSingleDefaultChannel = mNumNotificationChannels == 1
162 && mSingleNotificationChannel.getId()
163 .equals(NotificationChannel.DEFAULT_CHANNEL_ID)
164 && numTotalChannels <= 1;
Geoffrey Pitschd034d292017-05-12 11:59:20 -0400165 }
166
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400167 try {
168 final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
169 if (Utils.isSystemPackage(getResources(), pm, pkgInfo)) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500170 if (mSingleNotificationChannel != null
171 && !mSingleNotificationChannel.isBlockableSystem()) {
172 mNonblockable = true;
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400173 }
174 }
175 } catch (PackageManager.NameNotFoundException e) {
176 // unlikely.
177 }
178 if (nonBlockablePkgs != null) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500179 mNonblockable |= nonBlockablePkgs.contains(pkg);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400180 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500181 mNonblockable |= (mNumNotificationChannels > 1);
Geoffrey Pitschb43486a2017-06-01 13:45:59 -0400182
Julia Reynolds437cdb12018-01-03 12:27:24 -0500183 bindHeader();
184 bindPrompt();
185 bindButtons();
186 }
187
188 private void bindHeader() throws RemoteException {
189 // Package name
190 Drawable pkgicon = null;
191 ApplicationInfo info;
192 try {
193 info = mPm.getApplicationInfo(mPkg,
194 PackageManager.MATCH_UNINSTALLED_PACKAGES
195 | PackageManager.MATCH_DISABLED_COMPONENTS
196 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
197 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
198 if (info != null) {
199 mAppUid = mSbn.getUid();
200 mAppName = String.valueOf(mPm.getApplicationLabel(info));
201 pkgicon = mPm.getApplicationIcon(info);
Geoffrey Pitschee8c81e2017-03-23 11:38:56 -0400202 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500203 } catch (PackageManager.NameNotFoundException e) {
204 // app is gone, just show package name and generic icon
205 pkgicon = mPm.getDefaultActivityIcon();
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500206 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500207 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400208 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
Mady Mellor87d79452017-01-10 11:52:52 -0800209
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500210 // Set group information if this channel has an associated group.
211 CharSequence groupName = null;
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500212 if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
213 final NotificationChannelGroup notificationChannelGroup =
Julia Reynolds437cdb12018-01-03 12:27:24 -0500214 mINotificationManager.getNotificationChannelGroupForPackage(
215 mSingleNotificationChannel.getGroup(), mPkg, mAppUid);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500216 if (notificationChannelGroup != null) {
217 groupName = notificationChannelGroup.getName();
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500218 }
Mady Mellor87d79452017-01-10 11:52:52 -0800219 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500220 TextView groupNameView = findViewById(R.id.group_name);
221 TextView groupDividerView = findViewById(R.id.pkg_group_divider);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500222 if (groupName != null) {
223 groupNameView.setText(groupName);
224 groupNameView.setVisibility(View.VISIBLE);
225 groupDividerView.setVisibility(View.VISIBLE);
226 } else {
227 groupNameView.setVisibility(View.GONE);
228 groupDividerView.setVisibility(View.GONE);
229 }
Mady Mellor87d79452017-01-10 11:52:52 -0800230
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500231 // Settings button.
Julia Reynolds437cdb12018-01-03 12:27:24 -0500232 final View settingsButton = findViewById(R.id.info);
233 if (mAppUid >= 0 && mOnSettingsClickListener != null) {
Geoffrey Pitsch029a3fa2017-03-30 13:01:57 -0400234 settingsButton.setVisibility(View.VISIBLE);
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500235 final int appUidF = mAppUid;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500236 settingsButton.setOnClickListener(
237 (View view) -> {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500238 mOnSettingsClickListener.onClick(view,
239 mNumNotificationChannels > 1 ? null : mSingleNotificationChannel,
240 appUidF);
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500241 });
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500242 } else {
243 settingsButton.setVisibility(View.GONE);
244 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500245 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500246
Julia Reynolds437cdb12018-01-03 12:27:24 -0500247 private void bindPrompt() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500248 final TextView blockPrompt = findViewById(R.id.block_prompt);
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500249 bindName();
Julia Reynolds437cdb12018-01-03 12:27:24 -0500250 if (mNonblockable) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500251 blockPrompt.setText(R.string.notification_unblockable_desc);
252 } else {
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500253 if (mNegativeUserSentiment) {
254 blockPrompt.setText(R.string.inline_blocking_helper);
255 } else if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500256 blockPrompt.setText(R.string.inline_keep_showing_app);
257 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500258 blockPrompt.setText(R.string.inline_keep_showing);
259 }
260 }
Mady Mellor87d79452017-01-10 11:52:52 -0800261 }
262
Julia Reynolds0ef7d842018-01-24 17:50:31 -0500263 private void bindName() {
264 final TextView channelName = findViewById(R.id.channel_name);
265 if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
266 channelName.setVisibility(View.GONE);
267 } else {
268 channelName.setText(mSingleNotificationChannel.getName());
269 }
270 }
271
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400272 private boolean hasImportanceChanged() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500273 return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
Mady Mellor87d79452017-01-10 11:52:52 -0800274 }
275
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500276 private void saveImportance() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500277 if (mNonblockable || !hasImportanceChanged()) {
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500278 return;
279 }
Mady Mellor87d79452017-01-10 11:52:52 -0800280 MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
Julia Reynolds437cdb12018-01-03 12:27:24 -0500281 mChosenImportance - mStartingUserImportance);
282 mSingleNotificationChannel.setImportance(mChosenImportance);
Julia Reynolds8ceb5792017-04-11 11:32:44 -0400283 mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
Mady Mellor87d79452017-01-10 11:52:52 -0800284 try {
285 mINotificationManager.updateNotificationChannelForPackage(
Geoffrey Pitschd0856f02017-02-16 10:51:18 -0500286 mPkg, mAppUid, mSingleNotificationChannel);
Mady Mellor87d79452017-01-10 11:52:52 -0800287 } catch (RemoteException e) {
288 // :(
289 }
290 }
291
Julia Reynolds437cdb12018-01-03 12:27:24 -0500292 private void bindButtons() {
293 View block = findViewById(R.id.block);
294 block.setOnClickListener(mOnStopNotifications);
295 TextView keep = findViewById(R.id.keep);
296 keep.setOnClickListener(mOnKeepShowing);
297 findViewById(R.id.undo).setOnClickListener(mOnUndo);
298
299 if (mNonblockable) {
300 keep.setText(R.string.notification_done);
301 block.setVisibility(GONE);
302 }
303
304 // app settings link
305 TextView settingsLinkView = findViewById(R.id.app_settings);
306 Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
307 mSbn.getId(), mSbn.getTag());
308 if (settingsIntent != null
309 && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
310 settingsLinkView.setVisibility(View.VISIBLE);
311 settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
312 mSbn.getNotification().getSettingsText()));
313 settingsLinkView.setOnClickListener((View view) -> {
314 mAppSettingsClickListener.onClick(view, settingsIntent);
315 });
Mady Mellor87d79452017-01-10 11:52:52 -0800316 } else {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500317 settingsLinkView.setVisibility(View.GONE);
Mady Mellor87d79452017-01-10 11:52:52 -0800318 }
319 }
320
Julia Reynolds437cdb12018-01-03 12:27:24 -0500321 private void swapContent(boolean showPrompt) {
322 if (mExpandAnimation != null) {
323 mExpandAnimation.cancel();
324 }
Mady Mellor87d79452017-01-10 11:52:52 -0800325
Julia Reynolds437cdb12018-01-03 12:27:24 -0500326 if (showPrompt) {
327 mChosenImportance = mStartingUserImportance;
328 } else {
329 mChosenImportance = IMPORTANCE_NONE;
330 }
331
332 View prompt = findViewById(R.id.prompt);
333 View confirmation = findViewById(R.id.confirmation);
334 ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
335 prompt.getAlpha(), showPrompt ? 1f : 0f);
336 promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
337 ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
338 confirmation.getAlpha(), showPrompt ? 0f : 1f);
339 confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
340
341 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
342 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
343
344 mExpandAnimation = new AnimatorSet();
345 mExpandAnimation.playTogether(promptAnim, confirmAnim);
346 mExpandAnimation.setDuration(150);
347 mExpandAnimation.addListener(new AnimatorListenerAdapter() {
348 boolean cancelled = false;
349
350 @Override
351 public void onAnimationCancel(Animator animation) {
352 cancelled = true;
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500353 }
Julia Reynolds437cdb12018-01-03 12:27:24 -0500354
355 @Override
356 public void onAnimationEnd(Animator animation) {
357 if (!cancelled) {
358 prompt.setVisibility(showPrompt ? VISIBLE : GONE);
359 confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
360 }
361 }
Mady Mellor87d79452017-01-10 11:52:52 -0800362 });
Julia Reynolds437cdb12018-01-03 12:27:24 -0500363 mExpandAnimation.start();
Mady Mellor87d79452017-01-10 11:52:52 -0800364 }
365
Geoffrey Pitschd94e7882017-04-06 09:52:11 -0400366 @Override
367 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
368 super.onInitializeAccessibilityEvent(event);
369 if (mGutsContainer != null &&
370 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
371 if (mGutsContainer.isExposed()) {
372 event.getText().add(mContext.getString(
373 R.string.notification_channel_controls_opened_accessibility, mAppName));
374 } else {
375 event.getText().add(mContext.getString(
376 R.string.notification_channel_controls_closed_accessibility, mAppName));
377 }
378 }
379 }
380
Julia Reynolds3aedded2017-03-31 14:42:09 -0400381 private Intent getAppSettingsIntent(PackageManager pm, String packageName,
382 NotificationChannel channel, int id, String tag) {
383 Intent intent = new Intent(Intent.ACTION_MAIN)
384 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
385 .setPackage(packageName);
386 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
387 intent,
388 PackageManager.MATCH_DEFAULT_ONLY
389 );
390 if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
391 return null;
392 }
393 final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
394 intent.setClassName(activityInfo.packageName, activityInfo.name);
395 if (channel != null) {
396 intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
397 }
398 intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
399 intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
400 return intent;
401 }
402
Julia Reynolds437cdb12018-01-03 12:27:24 -0500403 private void closeControls(View v) {
404 int[] parentLoc = new int[2];
405 int[] targetLoc = new int[2];
406 mGutsContainer.getLocationOnScreen(parentLoc);
407 v.getLocationOnScreen(targetLoc);
408 final int centerX = v.getWidth() / 2;
409 final int centerY = v.getHeight() / 2;
410 final int x = targetLoc[0] - parentLoc[0] + centerX;
411 final int y = targetLoc[1] - parentLoc[1] + centerY;
412 mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
413 }
414
Mady Mellor87d79452017-01-10 11:52:52 -0800415 @Override
Mady Mellor95d743c2017-01-10 12:05:27 -0800416 public void setGutsParent(NotificationGuts guts) {
417 mGutsContainer = guts;
Mady Mellor87d79452017-01-10 11:52:52 -0800418 }
419
420 @Override
Mady Mellor434180c2017-02-13 11:29:42 -0800421 public boolean willBeRemoved() {
Julia Reynolds437cdb12018-01-03 12:27:24 -0500422 return hasImportanceChanged();
Mady Mellor434180c2017-02-13 11:29:42 -0800423 }
424
425 @Override
Mady Mellor87d79452017-01-10 11:52:52 -0800426 public View getContentView() {
427 return this;
428 }
429
430 @Override
Mady Mellorc2dbe492017-03-30 13:22:03 -0700431 public boolean handleCloseControls(boolean save, boolean force) {
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400432 if (save && hasImportanceChanged()) {
433 if (mCheckSaveListener != null) {
Eliot Courtney47098cb2017-10-18 17:30:30 +0900434 mCheckSaveListener.checkSave(this::saveImportance, mSbn);
Geoffrey Pitsch5278d3d2017-03-29 13:39:10 -0400435 } else {
436 saveImportance();
437 }
Geoffrey Pitschdf44b602017-02-03 13:31:50 -0500438 }
Mady Mellor87d79452017-01-10 11:52:52 -0800439 return false;
440 }
Mady Mellore09fb702017-03-30 13:23:29 -0700441
442 @Override
443 public int getActualHeight() {
444 return getHeight();
445 }
Mady Mellor87d79452017-01-10 11:52:52 -0800446}