Allow users to set app-wide Importance default
And the associated ui changes to the notification guts. Bug: 22451710 Change-Id: I4e0b11e7b24d70b039a432c5e6cd76c9c7cc547c
This commit is contained in:
@@ -54,6 +54,7 @@ interface INotificationManager
|
||||
int getTopicPriority(String pkg, int uid, in Notification.Topic topic);
|
||||
void setTopicImportance(String pkg, int uid, in Notification.Topic topic, int importance);
|
||||
int getTopicImportance(String pkg, int uid, in Notification.Topic topic);
|
||||
void setAppImportance(String pkg, int uid, int importance);
|
||||
|
||||
// TODO: Remove this when callers have been migrated to the equivalent
|
||||
// INotificationListener method.
|
||||
|
||||
@@ -24,35 +24,23 @@
|
||||
android:clickable="true"
|
||||
android:gravity="top|start"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingStart="@*android:dimen/notification_content_margin_start"
|
||||
android:paddingEnd="@*android:dimen/notification_content_margin_end"
|
||||
android:background="@color/notification_guts_text_color" >
|
||||
|
||||
<!-- header -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@*android:dimen/notification_content_margin_start"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp" >
|
||||
android:paddingBottom="8dp" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/notification_guts_header"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginEnd="52dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/notification_guts_app_details"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:layout_gravity="start|top"
|
||||
android:gravity="center_vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="18dp"
|
||||
@@ -76,22 +64,12 @@
|
||||
android:layout_gravity="bottom|start"
|
||||
android:visibility="gone"
|
||||
android:textColor="#ffffff" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/topic_details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
|
||||
android:textColor="@color/notification_guts_text_color"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
|
||||
android:id="@+id/notification_inspect_item"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
@@ -103,7 +81,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="@*android:dimen/notification_content_margin_start"
|
||||
android:orientation="vertical"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
@@ -116,8 +93,7 @@
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||
android:textColor="@color/notification_guts_text_color"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:text="@*android:string/notification_importance_title"/>
|
||||
android:fadingEdge="horizontal"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/summary"
|
||||
@@ -133,7 +109,7 @@
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="6dp" >
|
||||
android:paddingTop="8dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/low_importance"
|
||||
@@ -162,5 +138,21 @@
|
||||
android:layout_height="24dp"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<RadioGroup android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="8dp">
|
||||
<RadioButton android:id="@+id/apply_to_topic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/notification_guts_text_color"
|
||||
android:visibility="gone"/>
|
||||
<RadioButton android:id="@+id/apply_to_app"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/apply_to_app"
|
||||
android:textColor="@color/notification_guts_text_color"
|
||||
android:visibility="gone"/>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
</com.android.systemui.statusbar.NotificationGuts>
|
||||
|
||||
@@ -1201,4 +1201,34 @@
|
||||
<!-- Bluetooth enablement ok text [CHAR LIMIT=40] -->
|
||||
<string name="enable_bluetooth_confirmation_ok">Turn on</string>
|
||||
|
||||
<!-- Apply notification importance setting to a topic [CHAR LIMIT=NONE] -->
|
||||
<string name="apply_to_topic">Apply to <xliff:g id="topic_name" example="Friend Request">%1$s</xliff:g> notifications</string>
|
||||
<!-- Apply notification importance setting to an app [CHAR LIMIT=NONE] -->
|
||||
<string name="apply_to_app">Apply to all notifications from this app</string>
|
||||
<!-- Notification importance title, blocked status-->
|
||||
<string name="blocked_importance">Blocked</string>
|
||||
<!-- Notification importance title, low status-->
|
||||
<string name="low_importance">Low importance</string>
|
||||
<!-- Notification importance title, normal status-->
|
||||
<string name="default_importance">Normal importance</string>
|
||||
<!-- Notification importance title, high status-->
|
||||
<string name="high_importance">High importance</string>
|
||||
<!-- Notification importance title, max status-->
|
||||
<string name="max_importance">Urgent importance</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
|
||||
<string name="notification_importance_blocked">Never show these notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
|
||||
<string name="notification_importance_low">Silently show at the bottom of the notification list</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
|
||||
<string name="notification_importance_default">Silently show these notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
|
||||
<string name="notification_importance_high">Show at the top of the notifications list and make sound</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
|
||||
<string name="notification_importance_max">Peek onto the screen and make sound</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -947,7 +947,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
final StatusBarNotification sbn = row.getStatusBarNotification();
|
||||
PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
|
||||
row.setTag(sbn.getPackageName());
|
||||
final View guts = row.getGuts();
|
||||
final NotificationGuts guts = row.getGuts();
|
||||
final String pkg = sbn.getPackageName();
|
||||
String appname = pkg;
|
||||
Drawable pkgicon = null;
|
||||
@@ -969,8 +969,6 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
|
||||
((TextView) row.findViewById(R.id.pkgname)).setText(appname);
|
||||
|
||||
bindTopicImportance(sbn, row);
|
||||
|
||||
final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
|
||||
if (appUid >= 0) {
|
||||
final int appUidF = appUid;
|
||||
@@ -983,69 +981,8 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
} else {
|
||||
settingsButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindTopicImportance(final StatusBarNotification sbn,
|
||||
ExpandableNotificationRow row) {
|
||||
final INotificationManager sINM = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
final Notification.Topic topic = sbn.getNotification().getTopic() == null
|
||||
? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString(
|
||||
com.android.internal.R.string.default_notification_topic_label))
|
||||
: sbn.getNotification().getTopic();
|
||||
|
||||
((TextView) row.findViewById(R.id.topic_details)).setText(topic.getLabel());
|
||||
final TextView topicSummary = ((TextView) row.findViewById(R.id.summary));
|
||||
int importance = mNotificationData.getImportance(sbn.getKey());
|
||||
SeekBar seekBar = (SeekBar) row.findViewById(R.id.seekbar);
|
||||
seekBar.setMax(4);
|
||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
topicSummary.setText(getProgressSummary(progress));
|
||||
if (fromUser) {
|
||||
try {
|
||||
sINM.setTopicImportance(sbn.getPackageName(), sbn.getUid(), topic,
|
||||
progress);
|
||||
} catch (RemoteException e) {
|
||||
// :(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
private String getProgressSummary(int progress) {
|
||||
switch (progress) {
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_NONE:
|
||||
return mContext.getString(
|
||||
com.android.internal.R.string.notification_importance_blocked);
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_LOW:
|
||||
return mContext.getString(
|
||||
com.android.internal.R.string.notification_importance_low);
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
|
||||
return mContext.getString(
|
||||
com.android.internal.R.string.notification_importance_default);
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
|
||||
return mContext.getString(
|
||||
com.android.internal.R.string.notification_importance_high);
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_MAX:
|
||||
return mContext.getString(
|
||||
com.android.internal.R.string.notification_importance_max);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
});
|
||||
seekBar.setProgress(importance);
|
||||
guts.bindImportance(sbn, row, mNotificationData.getImportance(sbn.getKey()));
|
||||
}
|
||||
|
||||
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
|
||||
|
||||
@@ -16,12 +16,22 @@
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
@@ -83,6 +93,88 @@ public class NotificationGuts extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
void bindImportance(final StatusBarNotification sbn, final ExpandableNotificationRow row,
|
||||
final int importance) {
|
||||
final INotificationManager sINM = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
final Notification.Topic topic = sbn.getNotification().getTopic() == null
|
||||
? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString(
|
||||
com.android.internal.R.string.default_notification_topic_label))
|
||||
: sbn.getNotification().getTopic();
|
||||
|
||||
final RadioButton applyToTopic = (RadioButton) row.findViewById(R.id.apply_to_topic);
|
||||
if (sbn.getNotification().getTopic() != null) {
|
||||
applyToTopic.setVisibility(View.VISIBLE);
|
||||
applyToTopic.setChecked(true);
|
||||
applyToTopic.setText(mContext.getString(R.string.apply_to_topic, topic.getLabel()));
|
||||
row.findViewById(R.id.apply_to_app).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final TextView topicSummary = ((TextView) row.findViewById(R.id.summary));
|
||||
final TextView topicTitle = ((TextView) row.findViewById(R.id.title));
|
||||
SeekBar seekBar = (SeekBar) row.findViewById(R.id.seekbar);
|
||||
seekBar.setMax(4);
|
||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
updateTitleAndSummary(progress);
|
||||
if (fromUser) {
|
||||
try {
|
||||
if (applyToTopic.isChecked()) {
|
||||
sINM.setTopicImportance(sbn.getPackageName(), sbn.getUid(), topic,
|
||||
progress);
|
||||
} else {
|
||||
sINM.setAppImportance(sbn.getPackageName(), sbn.getUid(), progress);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// :(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
private void updateTitleAndSummary(int progress) {
|
||||
switch (progress) {
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_NONE:
|
||||
topicSummary.setText(mContext.getString(
|
||||
R.string.notification_importance_blocked));
|
||||
topicTitle.setText(mContext.getString(R.string.blocked_importance));
|
||||
break;
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_LOW:
|
||||
topicSummary.setText(mContext.getString(
|
||||
R.string.notification_importance_low));
|
||||
topicTitle.setText(mContext.getString(R.string.low_importance));
|
||||
break;
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
|
||||
topicSummary.setText(mContext.getString(
|
||||
R.string.notification_importance_default));
|
||||
topicTitle.setText(mContext.getString(R.string.default_importance));
|
||||
break;
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
|
||||
topicSummary.setText(mContext.getString(
|
||||
R.string.notification_importance_high));
|
||||
topicTitle.setText(mContext.getString(R.string.high_importance));
|
||||
break;
|
||||
case NotificationListenerService.Ranking.IMPORTANCE_MAX:
|
||||
topicSummary.setText(mContext.getString(
|
||||
R.string.notification_importance_max));
|
||||
topicTitle.setText(mContext.getString(R.string.max_importance));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
seekBar.setProgress(importance);
|
||||
}
|
||||
|
||||
public void setActualHeight(int actualHeight) {
|
||||
mActualHeight = actualHeight;
|
||||
invalidate();
|
||||
|
||||
@@ -1248,6 +1248,13 @@ public class NotificationManagerService extends SystemService {
|
||||
return mRankingHelper.getTopicImportance(pkg, uid, topic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAppImportance(String pkg, int uid, int importance) {
|
||||
enforceSystemOrSystemUI("Caller not system or systemui");
|
||||
mRankingHelper.setAppImportance(pkg, uid, importance);
|
||||
savePolicyFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* System-only API for getting a list of current (i.e. not cleared) notifications.
|
||||
*
|
||||
|
||||
@@ -35,4 +35,6 @@ public interface RankingConfig {
|
||||
void setTopicImportance(String packageName, int uid, Notification.Topic topic, int importance);
|
||||
|
||||
int getTopicImportance(String packageName, int uid, Notification.Topic topic);
|
||||
|
||||
void setAppImportance(String packageName, int uid, int importance);
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ public class RankingHelper implements RankingConfig {
|
||||
}
|
||||
out.startTag(null, TAG_PACKAGE);
|
||||
out.attribute(null, ATT_NAME, r.pkg);
|
||||
out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
|
||||
|
||||
if (!forBackup) {
|
||||
out.attribute(null, ATT_UID, Integer.toString(r.uid));
|
||||
@@ -426,6 +427,20 @@ public class RankingHelper implements RankingConfig {
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default importance for all new topics that appear in the future, and resets
|
||||
* the importance of all current topics.
|
||||
*/
|
||||
@Override
|
||||
public void setAppImportance(String pkgName, int uid, int importance) {
|
||||
final Record r = getOrCreateRecord(pkgName, uid);
|
||||
r.importance = importance;
|
||||
for (Topic t : r.topics.values()) {
|
||||
t.importance = importance;
|
||||
}
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
private Topic getOrCreateTopic(Record r, Notification.Topic topic) {
|
||||
if (topic == null) {
|
||||
topic = createDefaultTopic();
|
||||
@@ -435,6 +450,7 @@ public class RankingHelper implements RankingConfig {
|
||||
return t;
|
||||
} else {
|
||||
t = new Topic(topic);
|
||||
t.importance = r.importance;
|
||||
r.topics.put(topic.getId(), t);
|
||||
return t;
|
||||
}
|
||||
@@ -477,6 +493,8 @@ public class RankingHelper implements RankingConfig {
|
||||
pw.print(" (");
|
||||
pw.print(r.uid == Record.UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
|
||||
pw.print(')');
|
||||
pw.print(" importance=");
|
||||
pw.print(Ranking.importanceToString(r.importance));
|
||||
pw.println();
|
||||
for (Topic t : r.topics.values()) {
|
||||
pw.print(prefix);
|
||||
@@ -532,6 +550,7 @@ public class RankingHelper implements RankingConfig {
|
||||
|
||||
String pkg;
|
||||
int uid = UNKNOWN_UID;
|
||||
int importance = DEFAULT_IMPORTANCE;
|
||||
Map<String, Topic> topics = new ArrayMap<>();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
@@ -180,6 +181,9 @@ public class NotificationTestList extends TestActivity
|
||||
|
||||
new Test("with topic GoodBye") {
|
||||
public void run() {
|
||||
Notification.BigPictureStyle picture = new Notification.BigPictureStyle();
|
||||
picture.bigPicture(BitmapFactory.decodeResource(getResources(),
|
||||
R.id.large_icon_pineapple2));
|
||||
Notification n = new Notification.Builder(NotificationTestList.this)
|
||||
.setSmallIcon(R.drawable.icon1)
|
||||
.setWhen(mActivityCreateTime)
|
||||
@@ -187,11 +191,29 @@ public class NotificationTestList extends TestActivity
|
||||
.setContentText("This is a notification!!!")
|
||||
.setContentIntent(makeIntent2())
|
||||
.setTopic(new Notification.Topic("bye", "Goodbye"))
|
||||
.setStyle(picture)
|
||||
.build();
|
||||
|
||||
mNM.notify(9999, n);
|
||||
}
|
||||
},
|
||||
new Test("with topic Bananas") {
|
||||
public void run() {
|
||||
Notification.BigTextStyle bigText = new Notification.BigTextStyle();
|
||||
bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n");
|
||||
Notification n = new Notification.Builder(NotificationTestList.this)
|
||||
.setSmallIcon(R.drawable.icon1)
|
||||
.setStyle(bigText)
|
||||
.setWhen(mActivityCreateTime)
|
||||
.setContentTitle("bananananana")
|
||||
.setContentText("This is a banana!!!")
|
||||
.setContentIntent(makeIntent2())
|
||||
.setTopic(new Notification.Topic("bananas", "Bananas"))
|
||||
.build();
|
||||
|
||||
mNM.notify(999, n);
|
||||
}
|
||||
},
|
||||
|
||||
new Test("Whens") {
|
||||
public void run()
|
||||
|
||||
Reference in New Issue
Block a user