am d89a6b2a: Merge "Zen: Simplify notification policy api, add zenmode api." into mnc-dev

* commit 'd89a6b2abc38907a532da7dec073663da5a74e7c':
  Zen: Simplify notification policy api, add zenmode api.
This commit is contained in:
John Spurlock
2015-05-08 22:39:39 +00:00
committed by Android Git Automerger
12 changed files with 363 additions and 255 deletions

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);

View File

@@ -20,5 +20,5 @@ import android.app.NotificationManager;
/** @hide */
oneway interface INotificationManagerCallback {
void onPolicyToken(in NotificationManager.Policy.Token token);
void onPolicyRequestResult(boolean granted);
}

View File

@@ -17,4 +17,3 @@
package android.app;
parcelable NotificationManager.Policy;
parcelable NotificationManager.Policy.Token;

View File

@@ -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 prioritySenders;
public final int priorityCallSenders;
public Policy(int priorityCategories, int prioritySenders) {
/** Notification senders to prioritize for messages. One of:
* PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
public final int priorityMessageSenders;
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;
}
}
}

View File

@@ -808,6 +808,18 @@ public final class Settings {
public static final String ACTION_NOTIFICATION_LISTENER_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
*/

View File

@@ -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.
@@ -515,22 +520,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}.
*

View File

@@ -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) {

View File

@@ -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))

View File

@@ -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");
@@ -1606,6 +1609,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) {
@@ -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) {
final long identity = Binder.clearCallingIdentity();
try {
return mListeners.getPolicyToken(listener);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void requestNotificationPolicyToken(String pkg,
public void requestNotificationPolicyAccess(String pkg,
INotificationManagerCallback callback) throws RemoteException {
if (callback == null) {
Slog.w(TAG, "requestNotificationPolicyToken: no callback specified");
Slog.w(TAG, "requestNotificationPolicyAccess: no callback specified");
return;
}
if (pkg == null) {
Slog.w(TAG, "requestNotificationPolicyToken denied: no package specified");
callback.onPolicyToken(null);
Slog.w(TAG, "requestNotificationPolicyAccess denied: no package specified");
callback.onPolicyRequestResult(false);
return;
}
Policy.Token token = null;
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);
}
if (DBG) Slog.w(TAG, "requestNotificationPolicyToken granted for " + pkg);
// immediately grant for now
mPolicyAccess.put(pkg, true);
if (DBG) Slog.w(TAG, "requestNotificationPolicyAccess granted for " + pkg);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
callback.onPolicyToken(token);
callback.onPolicyRequestResult(true);
}
@Override
public boolean isNotificationPolicyTokenValid(String pkg, Policy.Token token) {
return checkPolicyToken(token);
public boolean isNotificationPolicyAccessGranted(String pkg) {
return checkPolicyAccess(pkg);
}
@Override
public Policy getNotificationPolicy(Policy.Token token) {
enforcePolicyToken(token, "getNotificationPolicy");
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) {
final String[] rt = new String[mPolicyAccess.size()];
for (int i = 0; i < mPolicyAccess.size(); i++) {
rt[i] = mPolicyAccess.keyAt(i);
}
return rt;
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
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(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) {

View File

@@ -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 {