Merge "Wait 100 ms for assistant response before posting."

This commit is contained in:
Julia Reynolds
2017-01-06 01:30:44 +00:00
committed by Android (Google) Code Review
4 changed files with 178 additions and 81 deletions

View File

@@ -92,6 +92,7 @@ interface INotificationManager
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
void applyEnqueuedAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentsFromAssistant(in INotificationListener token, in List<Adjustment> adjustments);
void createNotificationChannelFromAssistant(in INotificationListener token, String pkg, in NotificationChannel channel);

View File

@@ -210,7 +210,14 @@ public abstract class NotificationAssistantService extends NotificationListenerS
args.recycle();
Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
if (adjustment != null) {
adjustNotification(adjustment);
if (!isBound()) return;
try {
getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(
mWrapper, adjustment);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
throw ex.rethrowFromSystemServer();
}
}
} break;
}

View File

@@ -170,6 +170,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** {@hide} */
@@ -225,6 +226,8 @@ public class NotificationManagerService extends SystemService {
private static final int EVENTLOG_ENQUEUE_STATUS_IGNORED = 2;
private static final long MIN_PACKAGE_OVERRATE_LOG_INTERVAL = 5000; // milliseconds
private static final long DELAY_FOR_ASSISTANT_TIME = 100;
private IActivityManager mAm;
private IPackageManager mPackageManager;
AudioManager mAudioManager;
@@ -2363,6 +2366,28 @@ public class NotificationManagerService extends SystemService {
}
}
@Override
public void applyEnqueuedAdjustmentFromAssistant(INotificationListener token,
Adjustment adjustment) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mEnqueuedNotifications) {
mNotificationAssistants.checkServiceTokenLocked(token);
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
final NotificationRecord n = mEnqueuedNotifications.get(i);
if (Objects.equals(adjustment.getKey(), n.getKey())
&& Objects.equals(adjustment.getUser(), n.getUserId())) {
applyAdjustment(n, adjustment);
break;
}
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void applyAdjustmentFromAssistant(INotificationListener token,
Adjustment adjustment) throws RemoteException {
@@ -2370,7 +2395,8 @@ public class NotificationManagerService extends SystemService {
try {
synchronized (mNotificationList) {
mNotificationAssistants.checkServiceTokenLocked(token);
applyAdjustmentLocked(adjustment);
NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
applyAdjustment(n, adjustment);
}
mRankingHandler.requestSort(true);
} finally {
@@ -2387,7 +2413,8 @@ public class NotificationManagerService extends SystemService {
synchronized (mNotificationList) {
mNotificationAssistants.checkServiceTokenLocked(token);
for (Adjustment adjustment : adjustments) {
applyAdjustmentLocked(adjustment);
NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
applyAdjustment(n, adjustment);
}
}
mRankingHandler.requestSort(true);
@@ -2444,8 +2471,7 @@ public class NotificationManagerService extends SystemService {
}
};
private void applyAdjustmentLocked(Adjustment adjustment) {
NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
private void applyAdjustment(NotificationRecord n, Adjustment adjustment) {
if (n == null) {
return;
}
@@ -2653,6 +2679,21 @@ public class NotificationManagerService extends SystemService {
}
}
synchronized (mEnqueuedNotifications) {
if (!zenOnly) {
N = mEnqueuedNotifications.size();
if (N > 0) {
pw.println(" Enqueued Notification List:");
for (int i = 0; i < N; i++) {
final NotificationRecord nr = mEnqueuedNotifications.get(i);
if (filter.filtered && !filter.matches(nr.sbn)) continue;
nr.dump(pw, " ", getContext(), filter.redact);
}
pw.println(" ");
}
}
}
if (!zenOnly) {
pw.println("\n Usage Stats:");
mUsageStats.dump(pw, " ", filter);
@@ -2880,66 +2921,121 @@ public class NotificationManagerService extends SystemService {
@Override
public void run() {
try {
synchronized (mNotificationList) {
if (mSnoozeHelper.isSnoozed(userId, r.sbn.getPackageName(), r.getKey())) {
// TODO: log to event log
if (DBG) {
Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
}
mSnoozeHelper.update(userId, r);
savePolicyFile();
return;
synchronized (mNotificationList) {
if (mSnoozeHelper.isSnoozed(userId, r.sbn.getPackageName(), r.getKey())) {
// TODO: log to event log
if (DBG) {
Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
}
mSnoozeHelper.update(userId, r);
savePolicyFile();
return;
}
final StatusBarNotification n = r.sbn;
if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
NotificationRecord old = mNotificationsByKey.get(n.getKey());
final StatusBarNotification n = r.sbn;
if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
NotificationRecord old = mNotificationsByKey.get(n.getKey());
if (old != null) {
// Retain ranking information from previous record
r.copyRankingInformation(old);
}
final int callingUid = n.getUid();
final int callingPid = n.getInitialPid();
final Notification notification = n.getNotification();
final String pkg = n.getPackageName();
final int id = n.getId();
final String tag = n.getTag();
// Handle grouped notifications and bail out early if we
// can to avoid extracting signals.
handleGroupedNotificationLocked(r, old, callingUid, callingPid);
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {
int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
if (old != null) {
// Retain ranking information from previous record
r.copyRankingInformation(old);
enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
}
EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
pkg, id, tag, userId, notification.toString(),
enqueueStatus);
}
final int callingUid = n.getUid();
final int callingPid = n.getInitialPid();
final Notification notification = n.getNotification();
final String pkg = n.getPackageName();
final int id = n.getId();
final String tag = n.getTag();
final boolean isSystemNotification = isUidSystem(callingUid) ||
("android".equals(pkg));
mRankingHelper.extractSignals(r);
// Handle grouped notifications and bail out early if we
// can to avoid extracting signals.
handleGroupedNotificationLocked(r, old, callingUid, callingPid);
// blocked apps
if (isBlocked(r, mUsageStats)) {
return;
}
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {
int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
if (old != null) {
enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
// tell the assistant service about the notification
if (mNotificationAssistants.isEnabled()) {
mNotificationAssistants.onNotificationEnqueued(r);
mHandler.postDelayed(new PostNotificationRunnable(userId, r.getKey()),
DELAY_FOR_ASSISTANT_TIME);
} else {
mHandler.post(new PostNotificationRunnable(userId, r.getKey()));
}
}
}
protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) {
final String pkg = r.sbn.getPackageName();
final int callingUid = r.sbn.getUid();
final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
if (isPackageSuspended) {
Slog.e(TAG, "Suppressing notification from package due to package "
+ "suspended by administrator.");
usageStats.registerSuspendedByAdmin(r);
return isPackageSuspended;
}
final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
|| !r.getChannel().isAllowed()
|| !noteNotificationOp(pkg, callingUid);
if (isBlocked) {
Slog.e(TAG, "Suppressing notification from package by user request.");
usageStats.registerBlocked(r);
}
return isBlocked;
}
}
protected class PostNotificationRunnable implements Runnable {
private final String key;
private final int userId;
PostNotificationRunnable(int userId, String key) {
this.userId = userId;
this.key = key;
}
@Override
public void run() {
try {
NotificationRecord r = null;
synchronized (mEnqueuedNotifications) {
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
if (Objects.equals(key, enqueued.getKey())) {
r = enqueued;
break;
}
EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
pkg, id, tag, userId, notification.toString(),
enqueueStatus);
}
mRankingHelper.extractSignals(r);
// blocked apps
if (isBlocked(r, mUsageStats)) {
return;
}
// tell the assistant service about the notification
if (mNotificationAssistants.isEnabled()) {
mNotificationAssistants.onNotificationEnqueued(r);
// TODO delay the code below here for 100ms or until there is an answer
}
}
if (r == null) {
Slog.e(TAG, "Cannot find enqueued record for key: " + key);
return;
}
synchronized (mNotificationList) {
NotificationRecord old = mNotificationsByKey.get(key);
final StatusBarNotification n = r.sbn;
final Notification notification = n.getNotification();
int index = indexOfNotificationLocked(n.getKey());
if (index < 0) {
mNotificationList.add(r);
@@ -2998,32 +3094,17 @@ public class NotificationManagerService extends SystemService {
}
} finally {
synchronized (mEnqueuedNotifications) {
mEnqueuedNotifications.remove(r);
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
if (Objects.equals(key, enqueued.getKey())) {
mEnqueuedNotifications.remove(i);
break;
}
}
}
}
}
protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) {
final String pkg = r.sbn.getPackageName();
final int callingUid = r.sbn.getUid();
final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
if (isPackageSuspended) {
Slog.e(TAG, "Suppressing notification from package due to package "
+ "suspended by administrator.");
usageStats.registerSuspendedByAdmin(r);
return isPackageSuspended;
}
final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
|| !r.getChannel().isAllowed()
|| !noteNotificationOp(pkg, callingUid);
if (isBlocked) {
Slog.e(TAG, "Suppressing notification from package by user request.");
usageStats.registerBlocked(r);
}
return isBlocked;
}
}
/**

View File

@@ -39,6 +39,7 @@ import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
@@ -318,7 +319,7 @@ public final class NotificationRecord {
if (notification.actions != null && notification.actions.length > 0) {
pw.println(prefix + " actions={");
final int N = notification.actions.length;
for (int i=0; i<N; i++) {
for (int i = 0; i < N; i++) {
final Notification.Action action = notification.actions[i];
if (action != null) {
pw.println(String.format("%s [%d] \"%s\" -> %s",
@@ -350,7 +351,7 @@ public final class NotificationRecord {
final int N = Array.getLength(val);
pw.print(" (" + N + ")");
if (!redact) {
for (int j=0; j<N; j++) {
for (int j = 0; j < N; j++) {
pw.println();
pw.print(String.format("%s [%d] %s",
prefix, j, String.valueOf(Array.get(val, j))));
@@ -385,6 +386,13 @@ public final class NotificationRecord {
pw.println(prefix + " mSound= " + mSound);
pw.println(prefix + " mVibration= " + mVibration);
pw.println(prefix + " mAttributes= " + mAttributes);
pw.println(prefix + " overrideChannel=" + getChannel());
if (getPeopleOverride() != null) {
pw.println(prefix + " overridePeople= " + TextUtils.join(",", getPeopleOverride()));
}
if (getSnoozeCriteria() != null) {
pw.println(prefix + " snoozeCriteria=" + TextUtils.join(",", getSnoozeCriteria()));
}
}