summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2015-05-08 22:28:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-08 22:28:51 +0000
commitd89a6b2abc38907a532da7dec073663da5a74e7c (patch)
treed0ba1cec4ea6f69dda965770ca744bbe3b89400c
parent5759a8a9cfef08b7f9485c67b07be9ae268dea0a (diff)
parent807749301fcbda892dfc8a5832b19acf7d1cf53b (diff)
downloadframeworks_base-d89a6b2abc38907a532da7dec073663da5a74e7c.zip
frameworks_base-d89a6b2abc38907a532da7dec073663da5a74e7c.tar.gz
frameworks_base-d89a6b2abc38907a532da7dec073663da5a74e7c.tar.bz2
Merge "Zen: Simplify notification policy api, add zenmode api." into mnc-dev
-rw-r--r--api/current.txt41
-rw-r--r--api/system-current.txt41
-rw-r--r--core/java/android/app/INotificationManager.aidl13
-rw-r--r--core/java/android/app/INotificationManagerCallback.aidl2
-rw-r--r--core/java/android/app/NotificationManager.aidl1
-rw-r--r--core/java/android/app/NotificationManager.java290
-rw-r--r--core/java/android/provider/Settings.java12
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java33
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java6
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java4
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java133
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java38
12 files changed, 361 insertions, 253 deletions
diff --git a/api/current.txt b/api/current.txt
index f1865d5..07137f1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5145,17 +5145,31 @@ package android.app {
method public void cancel(java.lang.String, int);
method public void cancelAll();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
- method public android.app.NotificationManager.Policy getNotificationPolicy(android.app.NotificationManager.Policy.Token);
- method public boolean isNotificationPolicyTokenValid(android.app.NotificationManager.Policy.Token);
+ method public final int getCurrentInterruptionFilter();
+ method public android.app.NotificationManager.Policy getNotificationPolicy();
+ method public boolean isNotificationPolicyAccessGranted();
method public void notify(int, android.app.Notification);
method public void notify(java.lang.String, int, android.app.Notification);
- method public void requestNotificationPolicyToken(android.app.NotificationManager.Policy.Token.RequestCallback, android.os.Handler);
- method public void setNotificationPolicy(android.app.NotificationManager.Policy.Token, android.app.NotificationManager.Policy);
+ method public void requestPolicyAccess(android.app.NotificationManager.NotificationPolicyAccessRequestCallback, android.os.Handler);
+ method public final void setInterruptionFilter(int);
+ method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+ field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+ field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
+ field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
+ field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
+ field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
+ field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+ }
+
+ public static abstract class NotificationManager.NotificationPolicyAccessRequestCallback {
+ ctor public NotificationManager.NotificationPolicyAccessRequestCallback();
+ method public abstract void onAccessDenied();
+ method public abstract void onAccessGranted();
}
public static class NotificationManager.Policy implements android.os.Parcelable {
- ctor public NotificationManager.Policy(int, int);
+ ctor public NotificationManager.Policy(int, int, int);
method public int describeContents();
method public static java.lang.String priorityCategoriesToString(int);
method public static java.lang.String prioritySendersToString(int);
@@ -5169,20 +5183,9 @@ package android.app {
field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
+ field public final int priorityCallSenders;
field public final int priorityCategories;
- field public final int prioritySenders;
- }
-
- public static class NotificationManager.Policy.Token implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy.Token> CREATOR;
- }
-
- public static abstract class NotificationManager.Policy.Token.RequestCallback {
- ctor public NotificationManager.Policy.Token.RequestCallback();
- method public abstract void onTokenDenied();
- method public abstract void onTokenGranted(android.app.NotificationManager.Policy.Token);
+ field public final int priorityMessageSenders;
}
public final class PendingIntent implements android.os.Parcelable {
@@ -26543,6 +26546,7 @@ package android.provider {
field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
+ field public static final java.lang.String ACTION_ZEN_ACCESS_SETTINGS = "android.settings.ZEN_ACCESS_SETTINGS";
field public static final java.lang.String AUTHORITY = "settings";
field public static final java.lang.String EXTRA_ACCOUNT_TYPES = "account_types";
field public static final java.lang.String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
@@ -28842,7 +28846,6 @@ package android.service.notification {
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
- method public final android.app.NotificationManager.Policy.Token getNotificationPolicyToken();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
diff --git a/api/system-current.txt b/api/system-current.txt
index aacb9a0..00da3d3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5237,17 +5237,31 @@ package android.app {
method public void cancel(java.lang.String, int);
method public void cancelAll();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
- method public android.app.NotificationManager.Policy getNotificationPolicy(android.app.NotificationManager.Policy.Token);
- method public boolean isNotificationPolicyTokenValid(android.app.NotificationManager.Policy.Token);
+ method public final int getCurrentInterruptionFilter();
+ method public android.app.NotificationManager.Policy getNotificationPolicy();
+ method public boolean isNotificationPolicyAccessGranted();
method public void notify(int, android.app.Notification);
method public void notify(java.lang.String, int, android.app.Notification);
- method public void requestNotificationPolicyToken(android.app.NotificationManager.Policy.Token.RequestCallback, android.os.Handler);
- method public void setNotificationPolicy(android.app.NotificationManager.Policy.Token, android.app.NotificationManager.Policy);
+ method public void requestPolicyAccess(android.app.NotificationManager.NotificationPolicyAccessRequestCallback, android.os.Handler);
+ method public final void setInterruptionFilter(int);
+ method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+ field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+ field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
+ field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
+ field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
+ field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
+ field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+ }
+
+ public static abstract class NotificationManager.NotificationPolicyAccessRequestCallback {
+ ctor public NotificationManager.NotificationPolicyAccessRequestCallback();
+ method public abstract void onAccessDenied();
+ method public abstract void onAccessGranted();
}
public static class NotificationManager.Policy implements android.os.Parcelable {
- ctor public NotificationManager.Policy(int, int);
+ ctor public NotificationManager.Policy(int, int, int);
method public int describeContents();
method public static java.lang.String priorityCategoriesToString(int);
method public static java.lang.String prioritySendersToString(int);
@@ -5261,20 +5275,9 @@ package android.app {
field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
+ field public final int priorityCallSenders;
field public final int priorityCategories;
- field public final int prioritySenders;
- }
-
- public static class NotificationManager.Policy.Token implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy.Token> CREATOR;
- }
-
- public static abstract class NotificationManager.Policy.Token.RequestCallback {
- ctor public NotificationManager.Policy.Token.RequestCallback();
- method public abstract void onTokenDenied();
- method public abstract void onTokenGranted(android.app.NotificationManager.Policy.Token);
+ field public final int priorityMessageSenders;
}
public final class PendingIntent implements android.os.Parcelable {
@@ -28556,6 +28559,7 @@ package android.provider {
field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
+ field public static final java.lang.String ACTION_ZEN_ACCESS_SETTINGS = "android.settings.ZEN_ACCESS_SETTINGS";
field public static final java.lang.String AUTHORITY = "settings";
field public static final java.lang.String EXTRA_ACCOUNT_TYPES = "account_types";
field public static final java.lang.String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
@@ -30896,7 +30900,6 @@ package android.service.notification {
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
- method public final android.app.NotificationManager.Policy.Token getNotificationPolicyToken();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index ac8d5d8..63ff005 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -75,7 +75,7 @@ interface INotificationManager
void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter);
int getInterruptionFilterFromListener(in INotificationListener token);
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
- NotificationManager.Policy.Token getPolicyTokenFromListener(in INotificationListener listener);
+ void setInterruptionFilter(String pkg, int interruptionFilter);
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
@@ -87,10 +87,13 @@ interface INotificationManager
oneway void setZenMode(int mode, in Uri conditionId, String reason);
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
oneway void requestZenModeConditions(in IConditionListener callback, int relevance);
- oneway void requestNotificationPolicyToken(String pkg, in INotificationManagerCallback callback);
- boolean isNotificationPolicyTokenValid(String pkg, in NotificationManager.Policy.Token token);
- NotificationManager.Policy getNotificationPolicy(in NotificationManager.Policy.Token token);
- void setNotificationPolicy(in NotificationManager.Policy.Token token, in NotificationManager.Policy policy);
+ oneway void requestNotificationPolicyAccess(String pkg, in INotificationManagerCallback callback);
+ boolean isNotificationPolicyAccessGranted(String pkg);
+ NotificationManager.Policy getNotificationPolicy(String pkg);
+ void setNotificationPolicy(String pkg, in NotificationManager.Policy policy);
+ String[] getPackagesRequestingNotificationPolicyAccess();
+ boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
+ void setNotificationPolicyAccessGranted(String pkg, boolean granted);
byte[] getBackupPayload(int user);
void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/INotificationManagerCallback.aidl b/core/java/android/app/INotificationManagerCallback.aidl
index b9414ca..9929745 100644
--- a/core/java/android/app/INotificationManagerCallback.aidl
+++ b/core/java/android/app/INotificationManagerCallback.aidl
@@ -20,5 +20,5 @@ import android.app.NotificationManager;
/** @hide */
oneway interface INotificationManagerCallback {
- void onPolicyToken(in NotificationManager.Policy.Token token);
+ void onPolicyRequestResult(boolean granted);
}
diff --git a/core/java/android/app/NotificationManager.aidl b/core/java/android/app/NotificationManager.aidl
index 8380b8d..a5d5671 100644
--- a/core/java/android/app/NotificationManager.aidl
+++ b/core/java/android/app/NotificationManager.aidl
@@ -17,4 +17,3 @@
package android.app;
parcelable NotificationManager.Policy;
-parcelable NotificationManager.Policy.Token; \ No newline at end of file
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0a59026..e4bbe27 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.app.Notification.Builder;
-import android.app.NotificationManager.Policy.Token;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -38,6 +37,7 @@ import android.provider.Settings.Global;
import android.service.notification.IConditionListener;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
+import android.util.ArraySet;
import android.util.Log;
import java.util.Objects;
@@ -107,6 +107,43 @@ public class NotificationManager
public static final String ACTION_NOTIFICATION_POLICY_CHANGED
= "android.app.action.NOTIFICATION_POLICY_CHANGED";
+ /**
+ * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
+ * This broadcast is only sent to registered receivers.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_INTERRUPTION_FILTER_CHANGED
+ = "android.app.action.INTERRUPTION_FILTER_CHANGED";
+
+ /**
+ * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+ * Normal interruption filter.
+ */
+ public static final int INTERRUPTION_FILTER_ALL = 1;
+
+ /**
+ * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+ * Priority interruption filter.
+ */
+ public static final int INTERRUPTION_FILTER_PRIORITY = 2;
+
+ /**
+ * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+ * No interruptions filter.
+ */
+ public static final int INTERRUPTION_FILTER_NONE = 3;
+
+ /**
+ * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+ * Alarms only interruption filter.
+ */
+ public static final int INTERRUPTION_FILTER_ALARMS = 4;
+
+ /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
+ * the value is unavailable for any reason.
+ */
+ public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
+
private static INotificationManager sService;
/** @hide */
@@ -357,29 +394,29 @@ public class NotificationManager
}
/**
- * Requests a notification policy token for the calling package.
+ * Requests the ability to read/modify notification policy for the calling package.
*
- * @param callback required, used to receive the granted token or the deny signal.
+ * @param callback required, used to receive the granted or the denied signal.
* @param handler The handler used when receiving the result.
* If null, the current thread is used.
*/
- public void requestNotificationPolicyToken(@NonNull final Policy.Token.RequestCallback callback,
+ public void requestPolicyAccess(@NonNull final NotificationPolicyAccessRequestCallback callback,
@Nullable Handler handler) {
checkRequired("callback", callback);
final Handler h = handler != null ? handler : new Handler();
INotificationManager service = getService();
try {
- service.requestNotificationPolicyToken(mContext.getOpPackageName(),
+ service.requestNotificationPolicyAccess(mContext.getOpPackageName(),
new INotificationManagerCallback.Stub() {
@Override
- public void onPolicyToken(final Token token) throws RemoteException {
+ public void onPolicyRequestResult(final boolean granted) throws RemoteException {
h.post(new Runnable() {
@Override
public void run() {
- if (token != null) {
- callback.onTokenGranted(token);
+ if (granted) {
+ callback.onAccessGranted();
} else {
- callback.onTokenDenied();
+ callback.onAccessDenied();
}
}
});
@@ -389,16 +426,38 @@ public class NotificationManager
}
}
+ /** Callback for receiving the result of a policy access request. */
+ public static abstract class NotificationPolicyAccessRequestCallback {
+ /**
+ * Received if the request was granted for this package.
+ */
+ public abstract void onAccessGranted();
+
+ /**
+ * Received if the request was denied for this package.
+ */
+ public abstract void onAccessDenied();
+ }
+
/**
- * Checks a given notification policy token.
+ * Checks the ability to read/modify notification policy for the calling package.
*
- * Returns true if the token is still valid for managing policy.
+ * Returns true if the calling package can read/modify notification policy.
*/
- public boolean isNotificationPolicyTokenValid(@NonNull Policy.Token token) {
- if (token == null) return false;
+ public boolean isNotificationPolicyAccessGranted() {
INotificationManager service = getService();
try {
- return service.isNotificationPolicyTokenValid(mContext.getOpPackageName(), token);
+ return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /** @hide */
+ public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+ INotificationManager service = getService();
+ try {
+ return service.isNotificationPolicyAccessGrantedForPackage(pkg);
} catch (RemoteException e) {
}
return false;
@@ -407,13 +466,13 @@ public class NotificationManager
/**
* Gets the current notification policy.
*
- * @param token A valid notification policy token is required to access the current policy.
+ * <p>
+ * Only available if policy access is granted.
*/
- public Policy getNotificationPolicy(@NonNull Policy.Token token) {
- checkRequired("token", token);
+ public Policy getNotificationPolicy() {
INotificationManager service = getService();
try {
- return service.getNotificationPolicy(token);
+ return service.getNotificationPolicy(mContext.getOpPackageName());
} catch (RemoteException e) {
}
return null;
@@ -422,19 +481,46 @@ public class NotificationManager
/**
* Sets the current notification policy.
*
- * @param token A valid notification policy token is required to modify the current policy.
+ * <p>
+ * Only available if policy access is granted.
+ *
* @param policy The new desired policy.
*/
- public void setNotificationPolicy(@NonNull Policy.Token token, @NonNull Policy policy) {
- checkRequired("token", token);
+ public void setNotificationPolicy(@NonNull Policy policy) {
checkRequired("policy", policy);
INotificationManager service = getService();
try {
- service.setNotificationPolicy(token, policy);
+ service.setNotificationPolicy(mContext.getOpPackageName(), policy);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /** @hide */
+ public void setNotificationPolicyAccessGranted(String pkg, boolean granted) {
+ INotificationManager service = getService();
+ try {
+ service.setNotificationPolicyAccessGranted(pkg, granted);
} catch (RemoteException e) {
}
}
+ /** @hide */
+ public ArraySet<String> getPackagesRequestingNotificationPolicyAccess() {
+ INotificationManager service = getService();
+ try {
+ final String[] pkgs = service.getPackagesRequestingNotificationPolicyAccess();
+ if (pkgs != null && pkgs.length > 0) {
+ final ArraySet<String> rt = new ArraySet<>(pkgs.length);
+ for (int i = 0; i < pkgs.length; i++) {
+ rt.add(pkgs[i]);
+ }
+ return rt;
+ }
+ } catch (RemoteException e) {
+ }
+ return new ArraySet<String>();
+ }
+
private Context mContext;
private static void checkRequired(String name, Object value) {
@@ -477,24 +563,30 @@ public class NotificationManager
/** Notification categories to prioritize. Bitmask of PRIORITY_CATEGORY_* constants. */
public final int priorityCategories;
- /** Notification senders to prioritize. One of:
+ /** Notification senders to prioritize for calls. One of:
+ * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
+ public final int priorityCallSenders;
+
+ /** Notification senders to prioritize for messages. One of:
* PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
- public final int prioritySenders;
+ public final int priorityMessageSenders;
- public Policy(int priorityCategories, int prioritySenders) {
+ public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
this.priorityCategories = priorityCategories;
- this.prioritySenders = prioritySenders;
+ this.priorityCallSenders = priorityCallSenders;
+ this.priorityMessageSenders = priorityMessageSenders;
}
/** @hide */
public Policy(Parcel source) {
- this(source.readInt(), source.readInt());
+ this(source.readInt(), source.readInt(), source.readInt());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(priorityCategories);
- dest.writeInt(prioritySenders);
+ dest.writeInt(priorityCallSenders);
+ dest.writeInt(priorityMessageSenders);
}
@Override
@@ -504,7 +596,7 @@ public class NotificationManager
@Override
public int hashCode() {
- return Objects.hash(priorityCategories, prioritySenders);
+ return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders);
}
@Override
@@ -513,14 +605,16 @@ public class NotificationManager
if (o == this) return true;
final Policy other = (Policy) o;
return other.priorityCategories == priorityCategories
- && other.prioritySenders == prioritySenders;
+ && other.priorityCallSenders == priorityCallSenders
+ && other.priorityMessageSenders == priorityMessageSenders;
}
@Override
public String toString() {
return "NotificationManager.Policy["
+ "priorityCategories=" + priorityCategoriesToString(priorityCategories)
- + ",prioritySenders=" + prioritySendersToString(prioritySenders)
+ + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders)
+ + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders)
+ "]";
}
@@ -574,75 +668,6 @@ public class NotificationManager
}
};
- /**
- * Represents a client-specific token required to manage notification policy.
- */
- public static class Token implements Parcelable {
- private final IBinder mBinder;
-
- /** @hide */
- public Token(IBinder binder) {
- if (binder == null) throw new IllegalArgumentException("Binder required for token");
- mBinder = binder;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mBinder);
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Token)) return false;
- if (o == this) return true;
- final Token other = (Token) o;
- return Objects.equals(other.mBinder, mBinder);
- }
-
- @Override
- public String toString() {
- return String.format("NotificationManager.Token[0x%08x]",
- System.identityHashCode(mBinder));
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mBinder);
- }
-
- public static final Parcelable.Creator<Token> CREATOR
- = new Parcelable.Creator<Token>() {
- @Override
- public Token createFromParcel(Parcel in) {
- return new Token(in.readStrongBinder());
- }
-
- @Override
- public Token[] newArray(int size) {
- return new Token[size];
- }
- };
-
- /** Callback for receiving the result of a token request. */
- public static abstract class RequestCallback {
- /**
- * Received if the request was granted for this package.
- *
- * @param token can be used to manage notification policy.
- */
- public abstract void onTokenGranted(Policy.Token token);
-
- /**
- * Received if the request was denied for this package.
- */
- public abstract void onTokenDenied();
- }
- }
}
/**
@@ -671,4 +696,69 @@ public class NotificationManager
}
return new StatusBarNotification[0];
}
+
+ /**
+ * Gets the current notification interruption filter.
+ *
+ * <p>
+ * The interruption filter defines which notifications are allowed to interrupt the user
+ * (e.g. via sound &amp; vibration) and is applied globally.
+ * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
+ * unavailable.
+ *
+ * <p>
+ * Only available if policy access is granted.
+ */
+ public final int getCurrentInterruptionFilter() {
+ final INotificationManager service = getService();
+ try {
+ return zenModeToInterruptionFilter(service.getZenMode());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ }
+ return INTERRUPTION_FILTER_UNKNOWN;
+ }
+
+ /**
+ * Sets the current notification interruption filter.
+ *
+ * <p>
+ * The interruption filter defines which notifications are allowed to interrupt the user
+ * (e.g. via sound &amp; vibration) and is applied globally.
+ * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
+ * unavailable.
+ *
+ * <p>
+ * Only available if policy access is granted.
+ */
+ public final void setInterruptionFilter(int interruptionFilter) {
+ final INotificationManager service = getService();
+ try {
+ service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ }
+ }
+
+ /** @hide */
+ public static int zenModeToInterruptionFilter(int zen) {
+ switch (zen) {
+ case Global.ZEN_MODE_OFF: return INTERRUPTION_FILTER_ALL;
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return INTERRUPTION_FILTER_PRIORITY;
+ case Global.ZEN_MODE_ALARMS: return INTERRUPTION_FILTER_ALARMS;
+ case Global.ZEN_MODE_NO_INTERRUPTIONS: return INTERRUPTION_FILTER_NONE;
+ default: return INTERRUPTION_FILTER_UNKNOWN;
+ }
+ }
+
+ /** @hide */
+ public static int zenModeFromInterruptionFilter(int interruptionFilter, int defValue) {
+ switch (interruptionFilter) {
+ case INTERRUPTION_FILTER_ALL: return Global.ZEN_MODE_OFF;
+ case INTERRUPTION_FILTER_PRIORITY: return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ case INTERRUPTION_FILTER_ALARMS: return Global.ZEN_MODE_ALARMS;
+ case INTERRUPTION_FILTER_NONE: return Global.ZEN_MODE_NO_INTERRUPTIONS;
+ default: return defValue;
+ }
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7c3c11b..dc70d7b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -809,6 +809,18 @@ public final class Settings {
= "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
/**
+ * Activity Action: Show Do Not Disturb access settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ZEN_ACCESS_SETTINGS = "android.settings.ZEN_ACCESS_SETTINGS";
+
+ /**
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 35b8819..7956a3f 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -21,7 +21,7 @@ import android.annotation.SdkConstant;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.Notification.Builder;
-import android.app.NotificationManager.Policy;
+import android.app.NotificationManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -64,25 +64,29 @@ public abstract class NotificationListenerService extends Service {
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Normal interruption filter.
*/
- public static final int INTERRUPTION_FILTER_ALL = 1;
+ public static final int INTERRUPTION_FILTER_ALL
+ = NotificationManager.INTERRUPTION_FILTER_ALL;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Priority interruption filter.
*/
- public static final int INTERRUPTION_FILTER_PRIORITY = 2;
+ public static final int INTERRUPTION_FILTER_PRIORITY
+ = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* No interruptions filter.
*/
- public static final int INTERRUPTION_FILTER_NONE = 3;
+ public static final int INTERRUPTION_FILTER_NONE
+ = NotificationManager.INTERRUPTION_FILTER_NONE;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Alarms only interruption filter.
*/
- public static final int INTERRUPTION_FILTER_ALARMS = 4;
+ public static final int INTERRUPTION_FILTER_ALARMS
+ = NotificationManager.INTERRUPTION_FILTER_ALARMS;
/** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
* the value is unavailable for any reason. For example, before the notification listener
@@ -90,7 +94,8 @@ public abstract class NotificationListenerService extends Service {
*
* {@see #onListenerConnected()}
*/
- public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
+ public static final int INTERRUPTION_FILTER_UNKNOWN
+ = NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
/** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
* should disable notification sound, vibrating and other visual or aural effects.
@@ -516,22 +521,6 @@ public abstract class NotificationListenerService extends Service {
}
/**
- * Gets the notification policy token associated with this listener.
- *
- * <p>
- * Returns null if this listener is not currently active.
- */
- public final Policy.Token getNotificationPolicyToken() {
- if (!isBound()) return null;
- try {
- return getNotificationInterface().getPolicyTokenFromListener(mWrapper);
- } catch (android.os.RemoteException ex) {
- Log.v(TAG, "Unable to contact notification manager", ex);
- return null;
- }
- }
-
- /**
* Sets the desired {@link #getCurrentListenerHints() listener hints}.
*
* <p>
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 26bd10f..20b8cbe 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -538,7 +538,7 @@ public class ZenModeConfig implements Parcelable {
}
priorityCallSenders = sourceToPrioritySenders(allowCallsFrom, priorityCallSenders);
priorityMessageSenders = sourceToPrioritySenders(allowMessagesFrom, priorityMessageSenders);
- return new Policy(priorityCategories, priorityCallSenders);
+ return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders);
}
private static int sourceToPrioritySenders(int source, int def) {
@@ -567,7 +567,9 @@ public class ZenModeConfig implements Parcelable {
allowReminders = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REMINDERS) != 0;
allowRepeatCallers = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)
!= 0;
- allowCallsFrom = prioritySendersToSource(policy.prioritySenders, allowCallsFrom);
+ allowCallsFrom = prioritySendersToSource(policy.priorityCallSenders, allowCallsFrom);
+ allowMessagesFrom = prioritySendersToSource(policy.priorityMessageSenders,
+ allowMessagesFrom);
}
public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index b92c734..6f8e3ca 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -189,6 +189,10 @@ abstract public class ManagedServices {
}
}
+ public boolean isComponentEnabledForPackage(String pkg) {
+ return mEnabledServicesPackageNames.contains(pkg);
+ }
+
public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+ " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 25998da..791c1de 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -37,7 +37,6 @@ import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -233,7 +232,7 @@ public class NotificationManagerService extends SystemService {
new ArrayMap<String, NotificationRecord>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
- private final ArrayMap<String, Policy.Token> mPolicyTokens = new ArrayMap<>();
+ private final ArrayMap<String, Boolean> mPolicyAccess = new ArrayMap<>();
// The last key in this list owns the hardware.
@@ -899,6 +898,7 @@ public class NotificationManagerService extends SystemService {
@Override
void onZenModeChanged() {
+ sendRegisteredOnlyBroadcast(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
synchronized(mNotificationList) {
updateInterruptionFilterLocked();
}
@@ -906,9 +906,12 @@ public class NotificationManagerService extends SystemService {
@Override
void onPolicyChanged() {
- getContext().sendBroadcast(
- new Intent(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
- .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
+ sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
+ }
+
+ private void sendRegisteredOnlyBroadcast(String action) {
+ getContext().sendBroadcast(new Intent(action)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
}
});
final File systemDir = new File(Environment.getDataDirectory(), "system");
@@ -1607,6 +1610,19 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
+ enforcePolicyAccess(pkg, "setInterruptionFilter");
+ final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
+ if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mZenModeHelper.setManualZenMode(zen, null, "setInterruptionFilter");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void notifyConditions(String pkg, IConditionProvider provider,
Condition[] conditions) {
final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider);
@@ -1641,16 +1657,19 @@ public class NotificationManagerService extends SystemService {
message);
}
- private void enforcePolicyToken(Policy.Token token, String method) {
- if (!checkPolicyToken(token)) {
- Slog.w(TAG, "Invalid notification policy token calling " + method);
- throw new SecurityException("Invalid notification policy token");
+ private void enforcePolicyAccess(String pkg, String method) {
+ if (!checkPolicyAccess(pkg)) {
+ Slog.w(TAG, "Notification policy access denied calling " + method);
+ throw new SecurityException("Notification policy access denied");
}
}
- private boolean checkPolicyToken(Policy.Token token) {
- return mPolicyTokens.containsValue(token)
- || mListeners.mPolicyTokens.containsValue(token);
+ private boolean checkPackagePolicyAccess(String pkg) {
+ return Boolean.TRUE.equals(mPolicyAccess.get(pkg));
+ }
+
+ private boolean checkPolicyAccess(String pkg) {
+ return checkPackagePolicyAccess(pkg) || mListeners.isComponentEnabledForPackage(pkg);
}
@Override
@@ -1702,52 +1721,76 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public Policy.Token getPolicyTokenFromListener(INotificationListener listener) {
+ public void requestNotificationPolicyAccess(String pkg,
+ INotificationManagerCallback callback) throws RemoteException {
+ if (callback == null) {
+ Slog.w(TAG, "requestNotificationPolicyAccess: no callback specified");
+ return;
+ }
+ if (pkg == null) {
+ Slog.w(TAG, "requestNotificationPolicyAccess denied: no package specified");
+ callback.onPolicyRequestResult(false);
+ return;
+ }
final long identity = Binder.clearCallingIdentity();
try {
- return mListeners.getPolicyToken(listener);
+ synchronized (mNotificationList) {
+ // immediately grant for now
+ mPolicyAccess.put(pkg, true);
+ if (DBG) Slog.w(TAG, "requestNotificationPolicyAccess granted for " + pkg);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
+ callback.onPolicyRequestResult(true);
}
@Override
- public void requestNotificationPolicyToken(String pkg,
- INotificationManagerCallback callback) throws RemoteException {
- if (callback == null) {
- Slog.w(TAG, "requestNotificationPolicyToken: no callback specified");
- return;
- }
- if (pkg == null) {
- Slog.w(TAG, "requestNotificationPolicyToken denied: no package specified");
- callback.onPolicyToken(null);
- return;
- }
- Policy.Token token = null;
+ public boolean isNotificationPolicyAccessGranted(String pkg) {
+ return checkPolicyAccess(pkg);
+ }
+
+ @Override
+ public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+ enforceSystemOrSystemUI("request policy access status for another package");
+ return checkPackagePolicyAccess(pkg);
+ }
+
+ @Override
+ public String[] getPackagesRequestingNotificationPolicyAccess()
+ throws RemoteException {
+ enforceSystemOrSystemUI("request policy access packages");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
- token = mPolicyTokens.get(pkg);
- if (token == null) {
- token = new Policy.Token(new Binder());
- mPolicyTokens.put(pkg, token);
+ final String[] rt = new String[mPolicyAccess.size()];
+ for (int i = 0; i < mPolicyAccess.size(); i++) {
+ rt[i] = mPolicyAccess.keyAt(i);
}
- if (DBG) Slog.w(TAG, "requestNotificationPolicyToken granted for " + pkg);
+ return rt;
}
} finally {
Binder.restoreCallingIdentity(identity);
}
- callback.onPolicyToken(token);
}
@Override
- public boolean isNotificationPolicyTokenValid(String pkg, Policy.Token token) {
- return checkPolicyToken(token);
+ public void setNotificationPolicyAccessGranted(String pkg, boolean granted)
+ throws RemoteException {
+ enforceSystemOrSystemUI("grant notification policy access");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mNotificationList) {
+ mPolicyAccess.put(pkg, granted);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
- public Policy getNotificationPolicy(Policy.Token token) {
- enforcePolicyToken(token, "getNotificationPolicy");
+ public Policy getNotificationPolicy(String pkg) {
+ enforcePolicyAccess(pkg, "getNotificationPolicy");
final long identity = Binder.clearCallingIdentity();
try {
return mZenModeHelper.getNotificationPolicy();
@@ -1757,8 +1800,8 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void setNotificationPolicy(Policy.Token token, Policy policy) {
- enforcePolicyToken(token, "setNotificationPolicy");
+ public void setNotificationPolicy(String pkg, Policy policy) {
+ enforcePolicyAccess(pkg, "setNotificationPolicy");
final long identity = Binder.clearCallingIdentity();
try {
mZenModeHelper.setNotificationPolicy(policy);
@@ -1881,11 +1924,9 @@ public class NotificationManagerService extends SystemService {
pw.print(listener.component);
}
pw.println(')');
- pw.print(" mPolicyTokens.keys: ");
- pw.println(TextUtils.join(",", mPolicyTokens.keySet()));
- pw.print(" mListeners.mPolicyTokens.keys: ");
- pw.println(TextUtils.join(",", mListeners.mPolicyTokens.keySet()));
}
+ pw.println("\n Policy access:");
+ pw.print(" mPolicyAccess: "); pw.println(mPolicyAccess);
pw.println("\n Condition providers:");
mConditionProviders.dump(pw, filter);
@@ -3138,18 +3179,12 @@ public class NotificationManagerService extends SystemService {
public class NotificationListeners extends ManagedServices {
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
- private final ArrayMap<ComponentName, Policy.Token> mPolicyTokens = new ArrayMap<>();
private boolean mNotificationGroupsDesired;
public NotificationListeners() {
super(getContext(), mHandler, mNotificationList, mUserProfiles);
}
- public Policy.Token getPolicyToken(INotificationListener listener) {
- final ManagedServiceInfo info = checkServiceTokenLocked(listener);
- return info == null ? null : mPolicyTokens.get(info.component);
- }
-
@Override
protected Config getConfig() {
Config c = new Config();
@@ -3174,7 +3209,6 @@ public class NotificationManagerService extends SystemService {
synchronized (mNotificationList) {
updateNotificationGroupsDesiredLocked();
update = makeRankingUpdateLocked(info);
- mPolicyTokens.put(info.component, new Policy.Token(new Binder()));
}
try {
listener.onListenerConnected(update);
@@ -3191,7 +3225,6 @@ public class NotificationManagerService extends SystemService {
}
mLightTrimListeners.remove(removed);
updateNotificationGroupsDesiredLocked();
- mPolicyTokens.remove(removed.component);
}
public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e97def8..ca354e0 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -22,6 +22,7 @@ import static android.media.AudioAttributes.USAGE_NOTIFICATION;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import android.app.AppOpsManager;
+import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -142,11 +143,11 @@ public class ZenModeHelper {
}
public int getZenModeListenerInterruptionFilter() {
- return getZenModeListenerInterruptionFilter(mZenMode);
+ return NotificationManager.zenModeToInterruptionFilter(mZenMode);
}
- public void requestFromListener(ComponentName name, int interruptionFilter) {
- final int newZen = zenModeFromListenerInterruptionFilter(interruptionFilter, -1);
+ public void requestFromListener(ComponentName name, int filter) {
+ final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
if (newZen != -1) {
setManualZenMode(newZen, null,
"listener:" + (name != null ? name.flattenToShortString() : null));
@@ -393,37 +394,6 @@ public class ZenModeHelper {
}
}
- private static int getZenModeListenerInterruptionFilter(int zen) {
- switch (zen) {
- case Global.ZEN_MODE_OFF:
- return NotificationListenerService.INTERRUPTION_FILTER_ALL;
- case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
- return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
- case Global.ZEN_MODE_ALARMS:
- return NotificationListenerService.INTERRUPTION_FILTER_ALARMS;
- case Global.ZEN_MODE_NO_INTERRUPTIONS:
- return NotificationListenerService.INTERRUPTION_FILTER_NONE;
- default:
- return 0;
- }
- }
-
- private static int zenModeFromListenerInterruptionFilter(int listenerInterruptionFilter,
- int defValue) {
- switch (listenerInterruptionFilter) {
- case NotificationListenerService.INTERRUPTION_FILTER_ALL:
- return Global.ZEN_MODE_OFF;
- case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY:
- return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
- case NotificationListenerService.INTERRUPTION_FILTER_ALARMS:
- return Global.ZEN_MODE_ALARMS;
- case NotificationListenerService.INTERRUPTION_FILTER_NONE:
- return Global.ZEN_MODE_NO_INTERRUPTIONS;
- default:
- return defValue;
- }
- }
-
private ZenModeConfig readDefaultConfig(Resources resources) {
XmlResourceParser parser = null;
try {