diff options
| author | 2017-02-13 17:47:30 +0000 | |
|---|---|---|
| committer | 2017-02-13 17:47:33 +0000 | |
| commit | 7c4f39b856b34ea138857ab1a0c7edb5f40450e3 (patch) | |
| tree | e683a5bad8708c9922a4b09979d1d6887c4a2d8c | |
| parent | 7517e27793e1e9236eef82743c148665c0c0cda6 (diff) | |
| parent | df44b606f357bb67e7a3b44e58f551c1c731ce42 (diff) | |
Merge "Updated Inline Notification Controls"
15 files changed, 351 insertions, 308 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index cc6f6e12710b..5ab767ba9676 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -20,6 +20,7 @@ package android.app; import android.app.ITransientNotification; import android.app.Notification; import android.app.NotificationChannel; +import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.ComponentName; import android.content.Intent; @@ -57,12 +58,14 @@ interface INotificationManager void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted); + NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid); void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel); NotificationChannel getNotificationChannel(String pkg, String channelId); NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted); void deleteNotificationChannel(String pkg, String channelId); ParceledListSlice getNotificationChannels(String pkg); ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); + int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java index 93ba39cbba9d..41a0907c3228 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java @@ -39,7 +39,7 @@ public interface NotificationMenuRowProvider extends Plugin { public View getContentView(); - public boolean handleCloseControls(); + public boolean handleCloseControls(boolean save); } public interface SnoozeGutsContent extends GutsContent { diff --git a/packages/SystemUI/res/layout/notification_guts_importance_text.xml b/packages/SystemUI/res/layout/notification_guts_importance_text.xml deleted file mode 100644 index 5df4e0a96ba6..000000000000 --- a/packages/SystemUI/res/layout/notification_guts_importance_text.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright 2016, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="@dimen/notification_inline_importance_height" - android:paddingTop="4dp" - android:orientation="vertical"> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:ellipsize="end" - android:textAlignment="viewStart" - android:singleLine="true" - android:text="@string/high_importance" - android:textAppearance="@style/TextAppearance.NotificationGuts.Primary" /> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:ellipsize="end" - android:textAlignment="viewStart" - android:singleLine="true" - android:text="@string/notification_importance_high" - android:textAppearance="@style/TextAppearance.NotificationGuts.Secondary" /> -</LinearLayout> diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml index 9770eccfd2c1..31bd8b9e415b 100644 --- a/packages/SystemUI/res/layout/notification_info.xml +++ b/packages/SystemUI/res/layout/notification_info.xml @@ -28,89 +28,73 @@ android:background="@color/notification_guts_bg_color" android:theme="@*android:style/Theme.DeviceDefault.Light"> - <!-- header --> - <RelativeLayout + <!-- Package Info --> + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="20dp" - android:paddingEnd="8dp" - android:paddingBottom="15dp" - android:id="@+id/notification_guts_header"> + android:orientation="horizontal" + android:paddingTop="16dp" + android:paddingBottom="16dp" > + <ImageView + android:id="@+id/pkgicon" + android:layout_width="18dp" + android:layout_height="18dp" + android:layout_marginEnd="6dp" + android:contentDescription="@null" + android:scaleType="fitCenter" /> <TextView android:id="@+id/pkgname" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentStart="true" style="@style/TextAppearance.NotificationGuts.Secondary" /> <TextView - android:id="@+id/channel_name" + android:id="@+id/pkg_group_divider" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentStart="true" - android:layout_below="@id/pkgname" - style="@style/TextAppearance.NotificationGuts.Header" /> - <Switch - android:id="@+id/channel_enabled_switch" + android:layout_marginStart="2dp" + android:layout_marginEnd="2dp" + android:text="@string/notification_header_divider_symbol_with_spaces"/> + <TextView + android:id="@+id/group_name" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_centerVertical="true" - android:background="@null" /> - </RelativeLayout> - <!-- Importance radio buttons --> + style="@style/TextAppearance.NotificationGuts.Secondary" /> + </LinearLayout> + + <!-- Channel Info --> <LinearLayout - android:id="@+id/importance" android:layout_width="match_parent" android:layout_height="wrap_content" + android:paddingBottom="8dp" android:orientation="horizontal"> - <RadioGroup - android:id="@+id/importance_buttons" + <TextView + android:id="@+id/channel_name" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingEnd="@*android:dimen/notification_content_margin_end"> - <RadioButton - android:id="@+id/high_importance" - android:layout_width="wrap_content" - android:layout_height="@dimen/notification_inline_importance_height" - style="@style/TextAppearance.NotificationGuts.Radio" - android:buttonTint="@color/notification_guts_buttons" /> - <RadioButton - android:id="@+id/default_importance" - android:layout_width="wrap_content" - android:layout_height="@dimen/notification_inline_importance_height" - style="@style/TextAppearance.NotificationGuts.Radio" - android:buttonTint="@color/notification_guts_buttons" /> - <RadioButton - android:id="@+id/low_importance" - android:layout_width="wrap_content" - android:layout_height="@dimen/notification_inline_importance_height" - style="@style/TextAppearance.NotificationGuts.Radio" - android:buttonTint="@color/notification_guts_buttons" /> - <RadioButton - android:id="@+id/min_importance" - android:layout_width="wrap_content" - android:layout_height="@dimen/notification_inline_importance_height" - style="@style/TextAppearance.NotificationGuts.Radio" - android:buttonTint="@color/notification_guts_buttons" /> - </RadioGroup> - <LinearLayout - android:id="@+id/importance_buttons_text" - android:layout_width="match_parent" + android:layout_below="@id/pkgname" + style="@style/TextAppearance.NotificationGuts.Header" /> + <Switch + android:id="@+id/channel_enabled_switch" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical"> - <include layout="@layout/notification_guts_importance_text"/> - <include layout="@layout/notification_guts_importance_text"/> - <include layout="@layout/notification_guts_importance_text"/> - <include layout="@layout/notification_guts_importance_text"/> - </LinearLayout> + android:layout_gravity="end" + android:layout_weight="1" + android:background="@null" /> </LinearLayout> - <!-- Channel Disabled Text --> + + <!-- Secondary Text - only one shows at a time --> <TextView android:id="@+id/channel_disabled" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/notification_channel_disabled" + style="@style/TextAppearance.NotificationGuts.SecondaryWarning" /> + <TextView + android:id="@+id/num_channels_desc" + android:layout_width="match_parent" + android:layout_height="wrap_content" style="@style/TextAppearance.NotificationGuts.Secondary" /> + <!-- Settings and Done buttons --> <LinearLayout android:layout_width="match_parent" diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 1249f44cfabf..7f30c8307682 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -96,10 +96,6 @@ <!-- The "inside" of a notification, reached via longpress --> <color name="notification_guts_bg_color">#eeeeee</color> - <color name="notification_guts_disabled_slider_color">@*android:color/material_grey_300</color> - <color name="notification_guts_secondary_slider_color">#858383</color> - <color name="notification_guts_icon_tint">#8a000000</color> - <color name="notification_guts_disabled_icon_tint">#4d000000</color> <!-- Colors of the snooze menu reached via snooze icon behind a notification --> <color name="snooze_snackbar_bg">#FF4A4A4A</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e69c4a3ed22b..e737d2d6f007 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -317,9 +317,6 @@ <!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups --> <dimen name="notification_divider_height_increased">6dp</dimen> - <!-- The height of an importance selection in the inline notification controls --> - <dimen name="notification_inline_importance_height">55dp</dimen> - <!-- The minimum amount of top overscroll to go to the quick settings. --> <dimen name="min_top_overscroll_to_qs">36dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f7cf444d2350..67def4fa8ee0 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1335,37 +1335,23 @@ <!-- Notification Inline Controls: Header for apps that are not yet using notification channels. --> <string name="notification_header_default_channel">Notifications</string> + <!-- The divider symbol between different parts of the notification header including spaces. not translatable [CHAR LIMIT=3] --> + <string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string> + <!-- Notification Inline Controls: Shown when a channel's notifications are currently blocked --> <string name="notification_channel_disabled">You won\'t get these notifications anymore.</string> - <!-- Notification Inline Controls: Header text for describing from which app this notification - originates. The line below this in the layout will display the channel name. - Note for localization: For languages in which the two separate lines cannot be a continuous - sentence, translate this as a separate statement: "[Calendar] notifications" --> - <string name="notification_importance_header_app"><xliff:g id="app" example="Calendar">%s</xliff:g> notifications for</string> - - <!-- Notification importance title, min status--> - <string name="min_importance">Low</string> - <!-- Notification importance title, low status--> - <string name="low_importance">Medium</string> - <!-- Notification importance title, normal status--> - <string name="default_importance">High</string> - <!-- Notification importance title, high status--> - <string name="high_importance">Urgent</string> - - <!-- [CHAR LIMIT=100] Notification Importance slider: min importance level description --> - <string name="notification_importance_min">No sound or visual interruption</string> - - <!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description --> - <string name="notification_importance_low">Show silently</string> - - <!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description --> - <string name="notification_importance_default">Make sound</string> - - <!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description --> - <string name="notification_importance_high">Make sound and pop on screen</string> - - <!-- Notification: Control panel: Label for button that launches notification settings. [CHAR LIMIT=NONE] --> + <!-- Notification: Control panel: Label that shows how many channels this application has + defined, describing the current notification channel as "1 out of n". --> + <plurals name="notification_num_channels_desc"> + <item quantity="one">1 out of <xliff:g id="number">%d</xliff:g> category from this app</item> + <item quantity="other">1 out of <xliff:g id="number">%d</xliff:g> categories from this app</item> + </plurals> + <!-- Notification: Control panel: Label for button that launches notification settings. Used + when this app has defined more than a single channel for notifications. --> + <string name="notification_all_categories">All Categories</string> + <!-- Notification: Control panel: Label for button that launches notification settings. Used + when this app has only defined a single channel for notifications. --> <string name="notification_more_settings">More settings</string> <!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] --> <string name="notification_done">Done</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index c5a5518226d9..48b76648e7a3 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -362,17 +362,12 @@ <style name="TextAppearance.NotificationGuts.Secondary"> <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:alpha">.38</item> <item name="android:textSize">12sp</item> </style> - <style name="TextAppearance.NotificationGuts.Primary"> - <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:textSize">16sp</item> - </style> - - <style name="TextAppearance.NotificationGuts.Radio"> - <item name="android:textColor">?android:attr/textColorPrimary</item> + <style name="TextAppearance.NotificationGuts.SecondaryWarning"> + <item name="android:textColor">@color/system_warning_color</item> + <item name="android:textSize">12sp</item> </style> <style name="TextAppearance.NotificationGuts.Button"> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index f6056ddab093..b36cfdca1a46 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -39,12 +39,9 @@ import android.util.Log; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; -import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.RadioButton; -import android.widget.RadioGroup; import android.widget.SeekBar; import android.widget.Switch; import android.widget.TextView; @@ -170,14 +167,14 @@ public class NotificationGuts extends FrameLayout void onClick(View v, int appUid); } - public void closeControls(int x, int y, boolean saveImportance) { + public void closeControls(int x, int y, boolean save) { if (getWindowToken() == null) { if (mListener != null) { mListener.onGutsClosed(this); } return; } - if (mGutsContent == null || !mGutsContent.handleCloseControls()) { + if (mGutsContent == null || !mGutsContent.handleCloseControls(save)) { animateClose(x, y); } setExposed(false, mNeedsFalsingProtection); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java index bdbc9b32cbce..cfaa9e6238e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java @@ -1,5 +1,3 @@ -package com.android.systemui.statusbar; - /* * Copyright (C) 2017 The Android Open Source Project * @@ -16,15 +14,19 @@ package com.android.systemui.statusbar; * limitations under the License */ +package com.android.systemui.statusbar; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.INotificationManager; import android.app.NotificationChannel; +import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -43,8 +45,6 @@ import android.view.View.OnClickListener; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.RadioButton; -import android.widget.RadioGroup; import android.widget.SeekBar; import android.widget.Switch; import android.widget.TextView; @@ -77,13 +77,9 @@ public class NotificationInfo extends LinearLayout implements GutsContent { private TextView mImportanceTitle; private boolean mAuto; - private View mImportanceGroup; - private View mChannelDisabled; + private TextView mNumChannelsView; + private View mChannelDisabledView; private Switch mChannelEnabledSwitch; - private RadioButton mMinImportanceButton; - private RadioButton mLowImportanceButton; - private RadioButton mDefaultImportanceButton; - private RadioButton mHighImportanceButton; private GutsInteractionListener mGutsInteractionListener; @@ -124,6 +120,19 @@ public class NotificationInfo extends LinearLayout implements GutsContent { // app is gone, just show package name and generic icon pkgicon = pm.getDefaultActivityIcon(); } + ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon); + + int numChannels = 1; + try { + numChannels = iNotificationManager.getNumNotificationChannelsForPackage( + pkg, appUid, false /* includeDeleted */); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + + mNumChannelsView = (TextView) (findViewById(R.id.num_channels_desc)); + mNumChannelsView.setText(String.format(mContext.getResources().getQuantityString( + R.plurals.notification_num_channels_desc, numChannels), numChannels)); // If this is the placeholder channel, don't use our channel-specific text. String appNameText; @@ -138,24 +147,31 @@ public class NotificationInfo extends LinearLayout implements GutsContent { ((TextView) findViewById(R.id.pkgname)).setText(appNameText); ((TextView) findViewById(R.id.channel_name)).setText(channelNameText); - // Settings button. - final TextView settingsButton = (TextView) findViewById(R.id.more_settings); - if (appUid >= 0 && onSettingsClick != null) { - final int appUidF = appUid; - settingsButton.setOnClickListener( - (View view) -> { - onSettingsClick.onClick(view, appUidF); - }); - settingsButton.setText(R.string.notification_more_settings); + // Set group information if this channel has an associated group. + CharSequence groupName = null; + if (channel.getGroup() != null) { + try { + final NotificationChannelGroup notificationChannelGroup = + iNotificationManager.getNotificationChannelGroupForPackage( + channel.getGroup(), pkg, appUid); + if (notificationChannelGroup != null) { + groupName = notificationChannelGroup.getName(); + } + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } + TextView groupNameView = ((TextView) findViewById(R.id.group_name)); + TextView groupDividerView = ((TextView) findViewById(R.id.pkg_group_divider)); + if (groupName != null) { + groupNameView.setText(groupName); + groupNameView.setVisibility(View.VISIBLE); + groupDividerView.setVisibility(View.VISIBLE); } else { - settingsButton.setVisibility(View.GONE); + groupNameView.setVisibility(View.GONE); + groupDividerView.setVisibility(View.GONE); } - // Done button. - final TextView doneButton = (TextView) findViewById(R.id.done); - doneButton.setText(R.string.notification_done); - doneButton.setOnClickListener(onDoneClick); - boolean nonBlockable = false; try { final PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); @@ -167,53 +183,41 @@ public class NotificationInfo extends LinearLayout implements GutsContent { nonBlockable |= nonBlockablePkgs.contains(pkg); } - final View importanceButtons = findViewById(R.id.importance_buttons); - bindToggles(importanceButtons, mStartingUserImportance, nonBlockable); - - // Importance Text (hardcoded to 4 importance levels) - final ViewGroup importanceTextGroup = (ViewGroup) findViewById( - R.id.importance_buttons_text); - final int size = importanceTextGroup.getChildCount(); - for (int i = 0; i < size; i++) { - int importanceNameResId = 0; - int importanceDescResId = 0; - switch (i) { - case 0: - importanceNameResId = R.string.high_importance; - importanceDescResId = R.string.notification_importance_high; - break; - case 1: - importanceNameResId = R.string.default_importance; - importanceDescResId = R.string.notification_importance_default; - break; - case 2: - importanceNameResId = R.string.low_importance; - importanceDescResId = R.string.notification_importance_low; - break; - case 3: - importanceNameResId = R.string.min_importance; - importanceDescResId = R.string.notification_importance_min; - break; - default: - Log.e(TAG, "Too many importance groups in this layout."); - break; + bindButtons(nonBlockable); + + // Top-level importance group + mChannelDisabledView = findViewById(R.id.channel_disabled); + updateImportanceDisplay(); + + // Settings button. + final TextView settingsButton = (TextView) findViewById(R.id.more_settings); + if (appUid >= 0 && onSettingsClick != null) { + final int appUidF = appUid; + settingsButton.setOnClickListener( + (View view) -> { + onSettingsClick.onClick(view, appUidF); + }); + if (numChannels > 1) { + settingsButton.setText(R.string.notification_all_categories); + } else { + settingsButton.setText(R.string.notification_more_settings); } - final ViewGroup importanceChildGroup = (ViewGroup) importanceTextGroup.getChildAt(i); - ((TextView) importanceChildGroup.getChildAt(0)).setText(importanceNameResId); - ((TextView) importanceChildGroup.getChildAt(1)).setText(importanceDescResId); + + } else { + settingsButton.setVisibility(View.GONE); } - // Top-level importance group - mImportanceGroup = findViewById(R.id.importance); - mChannelDisabled = findViewById(R.id.channel_disabled); - updateImportanceGroup(); + // Done button. + final TextView doneButton = (TextView) findViewById(R.id.done); + doneButton.setText(R.string.notification_done); + doneButton.setOnClickListener(onDoneClick); } public boolean hasImportanceChanged() { return mStartingUserImportance != getSelectedImportance(); } - public void saveImportance() { + private void saveImportance() { int selectedImportance = getSelectedImportance(); if (selectedImportance == mStartingUserImportance) { return; @@ -233,73 +237,37 @@ public class NotificationInfo extends LinearLayout implements GutsContent { private int getSelectedImportance() { if (!mChannelEnabledSwitch.isChecked()) { return NotificationManager.IMPORTANCE_NONE; - } else if (mMinImportanceButton.isChecked()) { - return NotificationManager.IMPORTANCE_MIN; - } else if (mLowImportanceButton.isChecked()) { - return NotificationManager.IMPORTANCE_LOW; - } else if (mDefaultImportanceButton.isChecked()) { - return NotificationManager.IMPORTANCE_DEFAULT; - } else if (mHighImportanceButton.isChecked()) { - return NotificationManager.IMPORTANCE_HIGH; } else { - return NotificationManager.IMPORTANCE_UNSPECIFIED; + return mStartingUserImportance; } } - private void bindToggles(final View importanceButtons, final int importance, - final boolean nonBlockable) { + private void bindButtons(final boolean nonBlockable) { // Enabled Switch mChannelEnabledSwitch = (Switch) findViewById(R.id.channel_enabled_switch); - mChannelEnabledSwitch.setChecked(importance != NotificationManager.IMPORTANCE_NONE); + mChannelEnabledSwitch.setChecked( + mStartingUserImportance != NotificationManager.IMPORTANCE_NONE); mChannelEnabledSwitch.setVisibility(nonBlockable ? View.INVISIBLE : View.VISIBLE); - // Importance Buttons - mMinImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.min_importance); - mLowImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.low_importance); - mDefaultImportanceButton = (RadioButton) importanceButtons - .findViewById(R.id.default_importance); - mHighImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.high_importance); - - // Set to current importance setting - switch (importance) { - case NotificationManager.IMPORTANCE_UNSPECIFIED: - case NotificationManager.IMPORTANCE_NONE: - break; - case NotificationManager.IMPORTANCE_MIN: - mMinImportanceButton.setChecked(true); - break; - case NotificationManager.IMPORTANCE_LOW: - mLowImportanceButton.setChecked(true); - break; - case NotificationManager.IMPORTANCE_DEFAULT: - mDefaultImportanceButton.setChecked(true); - break; - case NotificationManager.IMPORTANCE_HIGH: - case NotificationManager.IMPORTANCE_MAX: - mHighImportanceButton.setChecked(true); - break; - } - // Callback when checked. mChannelEnabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { - mGutsInteractionListener.onInteraction(NotificationInfo.this); - updateImportanceGroup(); + if (mGutsInteractionListener != null) { + mGutsInteractionListener.onInteraction(NotificationInfo.this); + } + updateImportanceDisplay(); }); - ((RadioGroup) importanceButtons).setOnCheckedChangeListener( - (buttonView, isChecked) -> { - mGutsInteractionListener.onInteraction(NotificationInfo.this); - }); } - private void updateImportanceGroup() { + private void updateImportanceDisplay() { final boolean disabled = getSelectedImportance() == NotificationManager.IMPORTANCE_NONE; - mImportanceGroup.setVisibility(disabled ? View.GONE : View.VISIBLE); - mChannelDisabled.setVisibility(disabled ? View.VISIBLE : View.GONE); - } - - public void closeControls() { - if (mGutsInteractionListener != null) { - mGutsInteractionListener.closeGuts(this); + mChannelDisabledView.setVisibility(disabled ? View.VISIBLE : View.GONE); + if (disabled) { + // To be replaced by disabled text. + mNumChannelsView.setVisibility(View.GONE); + } else if (mNotificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) { + mNumChannelsView.setVisibility(View.INVISIBLE); + } else { + mNumChannelsView.setVisibility(View.VISIBLE); } } @@ -314,7 +282,10 @@ public class NotificationInfo extends LinearLayout implements GutsContent { } @Override - public boolean handleCloseControls() { + public boolean handleCloseControls(boolean save) { + if (save) { + saveImportance(); + } return false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java index 1992b6c9ccdd..0657dc1e86f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java @@ -195,7 +195,7 @@ public class NotificationSnooze extends LinearLayout } @Override - public boolean handleCloseControls() { + public boolean handleCloseControls(boolean save) { // When snooze is closed (i.e. there was interaction outside of the notification) // then we commit the snooze action. if (mSnoozeListener != null && mSelectedOption != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 365d99165121..bc43663ba261 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -5807,7 +5807,6 @@ public class StatusBar extends SystemUI implements DemoMode, private void saveAndCloseNotificationMenu(NotificationInfo info, ExpandableNotificationRow row, NotificationGuts guts, View done) { guts.resetFalsingCheck(); - info.saveImportance(); int[] rowLocation = new int[2]; int[] doneLocation = new int[2]; row.getLocationOnScreen(rowLocation); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java index 3e0d15d3cb69..0491fc40a865 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java @@ -20,6 +20,7 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; @@ -32,38 +33,42 @@ import static org.mockito.Mockito.when; import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationChannel; +import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.graphics.drawable.Drawable; import android.service.notification.StatusBarNotification; import android.support.test.InstrumentationRegistry; import android.support.test.annotation.UiThreadTest; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; -import android.widget.RadioButton; import android.widget.Switch; import android.widget.TextView; +import com.android.internal.util.CharSequences; import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.Test; import org.mockito.Mockito; +import java.util.Arrays; import java.util.Collections; import java.util.concurrent.CountDownLatch; @SmallTest @RunWith(AndroidJUnit4.class) -public class NotificationGutsTest { +public class NotificationInfoTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "test_package"; private static final String TEST_CHANNEL = "test_channel"; private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME"; - private NotificationGuts mNotificationGuts; private NotificationInfo mNotificationInfo; private final INotificationManager mMockINotificationManager = mock(INotificationManager.class); private final PackageManager mMockPackageManager = mock(PackageManager.class); @@ -76,12 +81,9 @@ public class NotificationGutsTest { public void setUp() throws Exception { // Inflate the layout final LayoutInflater layoutInflater = - LayoutInflater.from(InstrumentationRegistry.getTargetContext()); + LayoutInflater.from(mContext); mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info, null); - mNotificationGuts = (NotificationGuts) layoutInflater.inflate(R.layout.notification_guts, - null); - mNotificationInfo.setInteractionListener(mNotificationGuts); // PackageManager must return a packageInfo and applicationInfo. final PackageInfo packageInfo = new PackageInfo(); @@ -96,6 +98,20 @@ public class NotificationGutsTest { mNotificationChannel = new NotificationChannel( TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW); when(mMockStatusBarNotification.getPackageName()).thenReturn(TEST_PACKAGE_NAME); + + when(mMockINotificationManager.getNumNotificationChannelsForPackage( + eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(1); + } + + private CharSequence getStringById(int resId) { + return mContext.getString(resId); + } + + private CharSequence getNumChannelsString(int numChannels) { + return String.format( + mContext.getResources().getQuantityString( + R.plurals.notification_num_channels_desc, numChannels), + numChannels); } @Test @@ -110,6 +126,49 @@ public class NotificationGutsTest { @Test @UiThreadTest + public void testBindNotification_SetsPackageIcon() throws Exception { + final Drawable iconDrawable = mock(Drawable.class); + when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) + .thenReturn(iconDrawable); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + final ImageView iconView = (ImageView) mNotificationInfo.findViewById(R.id.pkgicon); + assertEquals(iconDrawable, iconView.getDrawable()); + } + + @Test + @UiThreadTest + public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception { + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name); + assertEquals(View.GONE, groupNameView.getVisibility()); + final TextView groupDividerView = + (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider); + assertEquals(View.GONE, groupDividerView.getVisibility()); + } + + @Test + @UiThreadTest + public void testBindNotification_SetsGroupNameIfNonNull() throws Exception { + mNotificationChannel.setGroup("test_group_id"); + final NotificationChannelGroup notificationChannelGroup = + new NotificationChannelGroup("test_group_id", "Test Group Name"); + when(mMockINotificationManager.getNotificationChannelGroupForPackage( + eq("test_group_id"), eq(TEST_PACKAGE_NAME), anyInt())) + .thenReturn(notificationChannelGroup); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name); + assertEquals(View.VISIBLE, groupNameView.getVisibility()); + assertEquals("Test Group Name", groupNameView.getText()); + final TextView groupDividerView = + (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider); + assertEquals(View.VISIBLE, groupDividerView.getVisibility()); + } + + @Test + @UiThreadTest public void testBindNotification_SetsTextChannelName() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); @@ -125,7 +184,7 @@ public class NotificationGutsTest { mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> { latch.countDown(); }, null, null); - final TextView settingsButton = + final TextView settingsButton = (TextView) mNotificationInfo.findViewById(R.id.more_settings); settingsButton.performClick(); // Verify that listener was triggered. @@ -134,6 +193,30 @@ public class NotificationGutsTest { @Test @UiThreadTest + public void testBindNotification_SettingsTextWithOneChannel() throws Exception { + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null, + null); + final TextView settingsButton = + (TextView) mNotificationInfo.findViewById(R.id.more_settings); + assertEquals(getStringById(R.string.notification_more_settings), settingsButton.getText()); + } + + @Test + @UiThreadTest + public void testBindNotification_SettingsTextWithMultipleChannels() throws Exception { + when(mMockINotificationManager.getNumNotificationChannelsForPackage( + eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null, + null); + final TextView settingsButton = + (TextView) mNotificationInfo.findViewById(R.id.more_settings); + assertEquals(getStringById(R.string.notification_all_categories), settingsButton.getText()); + } + + @Test + @UiThreadTest public void testBindNotification_SetsOnClickListenerForDone() throws Exception { final CountDownLatch latch = new CountDownLatch(1); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, @@ -149,33 +232,85 @@ public class NotificationGutsTest { @Test @UiThreadTest - public void testHasImportanceChanged_DefaultsToFalse() throws Exception { + public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception { + final NotificationChannel defaultChannel = new NotificationChannel( + NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME, + NotificationManager.IMPORTANCE_LOW); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, defaultChannel, null, null, null); + final TextView numChannelsView = + (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc); + assertTrue(numChannelsView.getVisibility() != View.VISIBLE); + } + + @Test + @UiThreadTest + public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel() + throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - assertFalse(mNotificationInfo.hasImportanceChanged()); + final TextView numChannelsView = + (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc); + assertEquals(numChannelsView.getVisibility(), View.VISIBLE); + assertEquals(getNumChannelsString(1), numChannelsView.getText()); } @Test @UiThreadTest - public void testHasImportanceChanged_ReturnsTrueAfterButtonChecked() throws Exception { - mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); + public void testBindNotification_NumChannelsTextScalesWithNumberOfChannels() + throws Exception { + when(mMockINotificationManager.getNumNotificationChannelsForPackage( + eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - // Find the high button and check it. - RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance); - highButton.setChecked(true); - assertTrue(mNotificationInfo.hasImportanceChanged()); + final TextView numChannelsView = + (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc); + assertEquals(getNumChannelsString(2), numChannelsView.getText()); } @Test @UiThreadTest - public void testImportanceButtonCheckedBasedOnInitialImportance() throws Exception { - mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH); + public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); + final TextView channelDisabledView = + (TextView) mNotificationInfo.findViewById(R.id.channel_disabled); + assertEquals(channelDisabledView.getVisibility(), View.GONE); + } - RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance); - assertTrue(highButton.isChecked()); + @Test + @UiThreadTest + public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception { + mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + final TextView channelDisabledView = + (TextView) mNotificationInfo.findViewById(R.id.channel_disabled); + assertEquals(channelDisabledView.getVisibility(), View.VISIBLE); + // Replaces the numChannelsView + final TextView numChannelsView = + (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc); + assertEquals(numChannelsView.getVisibility(), View.GONE); + } + + @Test + @UiThreadTest + public void testHasImportanceChanged_DefaultsToFalse() throws Exception { + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + assertFalse(mNotificationInfo.hasImportanceChanged()); + } + + @Test + @UiThreadTest + public void testHasImportanceChanged_ReturnsTrueAfterChannelDisabled() throws Exception { + mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); + mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, mNotificationChannel, null, null, null); + // Find the high button and check it. + Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); + enabledSwitch.setChecked(false); + assertTrue(mNotificationInfo.hasImportanceChanged()); } @Test @@ -194,60 +329,57 @@ public class NotificationGutsTest { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance); - highButton.setChecked(true); + Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); + enabledSwitch.setChecked(false); verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( anyString(), anyInt(), any()); } @Test @UiThreadTest - public void testSaveImportance_DoesNotUpdateNotificationChannelIfUnchanged() throws Exception { + public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged() + throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - mNotificationInfo.saveImportance(); + mNotificationInfo.handleCloseControls(true); verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( anyString(), anyInt(), any()); } @Test @UiThreadTest - public void testSaveImportance_DoesNotUpdateNotificationChannelIfUnspecified() + public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - mNotificationInfo.saveImportance(); + mNotificationInfo.handleCloseControls(true); verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( anyString(), anyInt(), any()); } @Test @UiThreadTest - public void testSaveImportance_CallsUpdateNotificationChannelIfChanged() throws Exception { + public void testEnabledSwitchOnByDefault() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); - RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance); - highButton.setChecked(true); - mNotificationInfo.saveImportance(); - verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( - eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel)); - assertEquals(NotificationManager.IMPORTANCE_HIGH, mNotificationChannel.getImportance()); + Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); + assertTrue(enabledSwitch.isChecked()); } @Test @UiThreadTest - public void testEnabledSwitchOnByDefault() throws Exception { - mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); + public void testEnabledButtonOffWhenAlreadyBanned() throws Exception { + mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); - assertTrue(enabledSwitch.isChecked()); + assertFalse(enabledSwitch.isChecked()); } @Test @@ -283,23 +415,23 @@ public class NotificationGutsTest { Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); enabledSwitch.setChecked(false); - mNotificationInfo.saveImportance(); + mNotificationInfo.handleCloseControls(true); verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel)); } @Test @UiThreadTest - public void testEnabledSwitchOverridesOtherButtons() throws Exception { + public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, - mMockStatusBarNotification, mNotificationChannel, null, null, null); + mMockStatusBarNotification, mNotificationChannel, null, null, + Collections.singleton(TEST_PACKAGE_NAME)); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); - RadioButton lowButton = (RadioButton) mNotificationInfo.findViewById(R.id.low_importance); - lowButton.setChecked(true); enabledSwitch.setChecked(false); - mNotificationInfo.saveImportance(); - assertEquals(NotificationManager.IMPORTANCE_NONE, mNotificationChannel.getImportance()); + mNotificationInfo.handleCloseControls(false); + verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( + eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel)); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index cc3fc003c918..19c9d9b0edb3 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1678,11 +1678,19 @@ public class NotificationManagerService extends SystemService { @Override public ParceledListSlice<NotificationChannel> getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted) { - checkCallerIsSystem(); + enforceSystemOrSystemUI("getNotificationChannelsForPackage"); return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted); } @Override + public int getNumNotificationChannelsForPackage(String pkg, int uid, + boolean includeDeleted) { + enforceSystemOrSystemUI("getNumNotificationChannelsForPackage"); + return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted) + .getList().size(); + } + + @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage( String pkg, int uid, boolean includeDeleted) { checkCallerIsSystem(); @@ -1690,13 +1698,19 @@ public class NotificationManagerService extends SystemService { } @Override + public NotificationChannelGroup getNotificationChannelGroupForPackage( + String groupId, String pkg, int uid) { + enforceSystemOrSystemUI("getNotificationChannelGroupForPackage"); + return mRankingHelper.getNotificationChannelGroup(groupId, pkg, uid); + } + + @Override public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) { checkCallerIsSystemOrSameApp(pkg); return mRankingHelper.getNotificationChannels( pkg, Binder.getCallingUid(), false /* includeDeleted */); } - @Override public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException { checkCallerIsSystem(); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 46c449bcab8e..76890b1dc79d 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -670,6 +670,13 @@ public class RankingHelper implements RankingConfig { } } + public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg, + int uid) { + Preconditions.checkNotNull(pkg); + Record r = getRecord(pkg, uid); + return r.groups.get(groupId); + } + @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted) { |