core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
core/java/android/app/INotificationManager.aidl \
+ core/java/android/app/INotificationManagerCallback.aidl \
core/java/android/app/IProcessObserver.aidl \
core/java/android/app/ISearchManager.aidl \
core/java/android/app/ISearchManagerCallback.aidl \
frameworks/base/core/java/android/app/AssistStructure.aidl \
frameworks/base/core/java/android/app/AssistContent.aidl \
frameworks/base/core/java/android/app/Notification.aidl \
+ frameworks/base/core/java/android/app/NotificationManager.aidl \
frameworks/base/core/java/android/app/WallpaperInfo.aidl \
frameworks/base/core/java/android/app/AppOpsManager.aidl \
frameworks/base/core/java/android/app/ActivityManager.aidl \
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
+ method public android.app.NotificationManager.Policy getNotificationPolicy(android.app.NotificationManager.Policy.Token);
+ method public boolean isNotificationPolicyTokenValid(android.app.NotificationManager.Policy.Token);
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);
+ field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+ }
+
+ public static class NotificationManager.Policy implements android.os.Parcelable {
+ ctor public NotificationManager.Policy(int, int);
+ method public int describeContents();
+ method public static java.lang.String priorityCategoriesToString(int);
+ method public static java.lang.String prioritySendersToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
+ field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
+ field public static final int PRIORITY_CATEGORY_EVENTS = 2; // 0x2
+ field public static final int PRIORITY_CATEGORY_MESSAGES = 4; // 0x4
+ field public static final int PRIORITY_CATEGORY_REMINDERS = 1; // 0x1
+ field public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 16; // 0x10
+ 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 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);
}
public final class PendingIntent implements android.os.Parcelable {
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();
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
+ method public android.app.NotificationManager.Policy getNotificationPolicy(android.app.NotificationManager.Policy.Token);
+ method public boolean isNotificationPolicyTokenValid(android.app.NotificationManager.Policy.Token);
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);
+ field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+ }
+
+ public static class NotificationManager.Policy implements android.os.Parcelable {
+ ctor public NotificationManager.Policy(int, int);
+ method public int describeContents();
+ method public static java.lang.String priorityCategoriesToString(int);
+ method public static java.lang.String prioritySendersToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
+ field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
+ field public static final int PRIORITY_CATEGORY_EVENTS = 2; // 0x2
+ field public static final int PRIORITY_CATEGORY_MESSAGES = 4; // 0x4
+ field public static final int PRIORITY_CATEGORY_REMINDERS = 1; // 0x1
+ field public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 16; // 0x10
+ 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 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);
}
public final class PendingIntent implements android.os.Parcelable {
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();
package android.app;
+import android.app.INotificationManagerCallback;
import android.app.ITransientNotification;
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
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);
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
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);
}
--- /dev/null
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.app.NotificationManager;
+
+/** @hide */
+oneway interface INotificationManagerCallback {
+ void onPolicyToken(in NotificationManager.Policy.Token token);
+}
--- /dev/null
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+parcelable NotificationManager.Policy;
+parcelable NotificationManager.Policy.Token;
\ No newline at end of file
package android.app;
+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.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.service.notification.ZenModeConfig;
import android.util.Log;
+import java.util.Objects;
+
/**
* Class to notify the user of events that happen. This is how you tell
* the user that something has happened in the background. {@more}
public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED
= "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
+ /**
+ * Intent that is broadcast when the state of getNotificationPolicy() changes.
+ * This broadcast is only sent to registered receivers.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_POLICY_CHANGED
+ = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+
private static INotificationManager sService;
/** @hide */
return null;
}
+ /**
+ * Requests a notification policy token for the calling package.
+ *
+ * @param callback required, used to receive the granted token or the deny 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,
+ @Nullable Handler handler) {
+ checkRequired("callback", callback);
+ final Handler h = handler != null ? handler : new Handler();
+ INotificationManager service = getService();
+ try {
+ service.requestNotificationPolicyToken(mContext.getOpPackageName(),
+ new INotificationManagerCallback.Stub() {
+ @Override
+ public void onPolicyToken(final Token token) throws RemoteException {
+ h.post(new Runnable() {
+ @Override
+ public void run() {
+ if (token != null) {
+ callback.onTokenGranted(token);
+ } else {
+ callback.onTokenDenied();
+ }
+ }
+ });
+ }
+ });
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Checks a given notification policy token.
+ *
+ * Returns true if the token is still valid for managing policy.
+ */
+ public boolean isNotificationPolicyTokenValid(@NonNull Policy.Token token) {
+ if (token == null) return false;
+ INotificationManager service = getService();
+ try {
+ return service.isNotificationPolicyTokenValid(mContext.getOpPackageName(), token);
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current notification policy.
+ *
+ * @param token A valid notification policy token is required to access the current policy.
+ */
+ public Policy getNotificationPolicy(@NonNull Policy.Token token) {
+ checkRequired("token", token);
+ INotificationManager service = getService();
+ try {
+ return service.getNotificationPolicy(token);
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Sets the current notification policy.
+ *
+ * @param token A valid notification policy token is required to modify the current policy.
+ * @param policy The new desired policy.
+ */
+ public void setNotificationPolicy(@NonNull Policy.Token token, @NonNull Policy policy) {
+ checkRequired("token", token);
+ checkRequired("policy", policy);
+ INotificationManager service = getService();
+ try {
+ service.setNotificationPolicy(token, policy);
+ } catch (RemoteException e) {
+ }
+ }
+
private Context mContext;
+
+ private static void checkRequired(String name, Object value) {
+ if (value == null) {
+ throw new IllegalArgumentException(name + " is required");
+ }
+ }
+
+ /**
+ * Notification policy configuration. Represents user-preferences for notification
+ * filtering and prioritization.
+ */
+ public static class Policy implements android.os.Parcelable {
+ /** Reminder notifications are prioritized. */
+ public static final int PRIORITY_CATEGORY_REMINDERS = 1 << 0;
+ /** Event notifications are prioritized. */
+ public static final int PRIORITY_CATEGORY_EVENTS = 1 << 1;
+ /** Message notifications are prioritized. */
+ public static final int PRIORITY_CATEGORY_MESSAGES = 1 << 2;
+ /** Calls are prioritized. */
+ public static final int PRIORITY_CATEGORY_CALLS = 1 << 3;
+ /** Calls from repeat callers are prioritized. */
+ public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4;
+
+ private static final int[] ALL_PRIORITY_CATEGORIES = {
+ PRIORITY_CATEGORY_REMINDERS,
+ PRIORITY_CATEGORY_EVENTS,
+ PRIORITY_CATEGORY_MESSAGES,
+ PRIORITY_CATEGORY_CALLS,
+ PRIORITY_CATEGORY_REPEAT_CALLERS,
+ };
+
+ /** Any sender is prioritized. */
+ public static final int PRIORITY_SENDERS_ANY = 0;
+ /** Saved contacts are prioritized. */
+ public static final int PRIORITY_SENDERS_CONTACTS = 1;
+ /** Only starred contacts are prioritized. */
+ public static final int PRIORITY_SENDERS_STARRED = 2;
+
+ /** Notification categories to prioritize. Bitmask of PRIORITY_CATEGORY_* constants. */
+ public final int priorityCategories;
+
+ /** Notification senders to prioritize. One of:
+ * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
+ public final int prioritySenders;
+
+ public Policy(int priorityCategories, int prioritySenders) {
+ this.priorityCategories = priorityCategories;
+ this.prioritySenders = prioritySenders;
+ }
+
+ /** @hide */
+ public Policy(Parcel source) {
+ this(source.readInt(), source.readInt());
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(priorityCategories);
+ dest.writeInt(prioritySenders);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(priorityCategories, prioritySenders);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Policy)) return false;
+ if (o == this) return true;
+ final Policy other = (Policy) o;
+ return other.priorityCategories == priorityCategories
+ && other.prioritySenders == prioritySenders;
+ }
+
+ @Override
+ public String toString() {
+ return "NotificationManager.Policy["
+ + "priorityCategories=" + priorityCategoriesToString(priorityCategories)
+ + ",prioritySenders=" + prioritySendersToString(prioritySenders)
+ + "]";
+ }
+
+ public static String priorityCategoriesToString(int priorityCategories) {
+ if (priorityCategories == 0) return "";
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < ALL_PRIORITY_CATEGORIES.length; i++) {
+ final int priorityCategory = ALL_PRIORITY_CATEGORIES[i];
+ if ((priorityCategories & priorityCategory) != 0) {
+ if (sb.length() > 0) sb.append(',');
+ sb.append(priorityCategoryToString(priorityCategory));
+ }
+ priorityCategories &= ~priorityCategory;
+ }
+ if (priorityCategories != 0) {
+ if (sb.length() > 0) sb.append(',');
+ sb.append("PRIORITY_CATEGORY_UNKNOWN_").append(priorityCategories);
+ }
+ return sb.toString();
+ }
+
+ private static String priorityCategoryToString(int priorityCategory) {
+ switch (priorityCategory) {
+ case PRIORITY_CATEGORY_REMINDERS: return "PRIORITY_CATEGORY_REMINDERS";
+ case PRIORITY_CATEGORY_EVENTS: return "PRIORITY_CATEGORY_EVENTS";
+ case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES";
+ case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS";
+ case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS";
+ default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory;
+ }
+ }
+
+ public static String prioritySendersToString(int prioritySenders) {
+ switch (prioritySenders) {
+ case PRIORITY_SENDERS_ANY: return "PRIORITY_SENDERS_ANY";
+ case PRIORITY_SENDERS_CONTACTS: return "PRIORITY_SENDERS_CONTACTS";
+ case PRIORITY_SENDERS_STARRED: return "PRIORITY_SENDERS_STARRED";
+ default: return "PRIORITY_SENDERS_UNKNOWN_" + prioritySenders;
+ }
+ }
+
+ public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
+ @Override
+ public Policy createFromParcel(Parcel in) {
+ return new Policy(in);
+ }
+
+ @Override
+ public Policy[] newArray(int size) {
+ return new Policy[size];
+ }
+ };
+
+ /**
+ * 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();
+ }
+ }
+ }
+
}
import android.app.INotificationManager;
import android.app.Notification;
import android.app.Notification.Builder;
+import android.app.NotificationManager.Policy;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
}
/**
+ * 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>
package android.service.notification;
+import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
}
};
+ public Policy toNotificationPolicy() {
+ int priorityCategories = 0;
+ int prioritySenders = Policy.PRIORITY_SENDERS_ANY;
+ if (allowCalls) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_CALLS;
+ }
+ if (allowMessages) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_MESSAGES;
+ }
+ if (allowEvents) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_EVENTS;
+ }
+ if (allowReminders) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_REMINDERS;
+ }
+ if (allowRepeatCallers) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+ }
+ switch (allowFrom) {
+ case SOURCE_ANYONE:
+ prioritySenders = Policy.PRIORITY_SENDERS_ANY;
+ break;
+ case SOURCE_CONTACT:
+ prioritySenders = Policy.PRIORITY_SENDERS_CONTACTS;
+ break;
+ case SOURCE_STAR:
+ prioritySenders = Policy.PRIORITY_SENDERS_STARRED;
+ break;
+ }
+ return new Policy(priorityCategories, prioritySenders);
+ }
+
+ public void applyNotificationPolicy(Policy policy) {
+ if (policy == null) return;
+ allowCalls = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_CALLS) != 0;
+ allowMessages = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_MESSAGES) != 0;
+ allowEvents = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_EVENTS) != 0;
+ allowReminders = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REMINDERS) != 0;
+ allowRepeatCallers = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)
+ != 0;
+ switch (policy.prioritySenders) {
+ case Policy.PRIORITY_SENDERS_CONTACTS:
+ allowFrom = SOURCE_CONTACT;
+ break;
+ case Policy.PRIORITY_SENDERS_STARRED:
+ allowFrom = SOURCE_STAR;
+ break;
+ default:
+ allowFrom = SOURCE_ANYONE;
+ break;
+ }
+ }
+
public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) {
final long now = System.currentTimeMillis();
final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
public interface Migration {
ZenModeConfig migrate(XmlV1 v1);
}
+
}
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
+import android.app.INotificationManagerCallback;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
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<>();
+
// The last key in this list owns the hardware.
ArrayList<String> mLights = new ArrayList<>();
updateInterruptionFilterLocked();
}
}
+
+ @Override
+ void onPolicyChanged() {
+ getContext().sendBroadcast(
+ new Intent(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
+ }
});
final File systemDir = new File(Environment.getDataDirectory(), "system");
mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
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 boolean checkPolicyToken(Policy.Token token) {
+ return mPolicyTokens.containsValue(token)
+ || mListeners.mPolicyTokens.containsValue(token);
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
enforceSystemOrSystemUIOrVolume("INotificationManager.isSystemConditionProviderEnabled");
return mConditionProviders.isSystemProviderEnabled(path);
}
- };
- private String[] getActiveNotificationKeys(INotificationListener token) {
- final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- final ArrayList<String> keys = new ArrayList<String>();
- if (info.isEnabledForCurrentProfiles()) {
- synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i = 0; i < N; i++) {
- final StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (info.enabledAndUserMatches(sbn.getUserId())) {
- keys.add(sbn.getKey());
+ @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,
+ 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;
+ 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);
}
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
+ callback.onPolicyToken(token);
+ }
+
+ @Override
+ public boolean isNotificationPolicyTokenValid(String pkg, Policy.Token token) {
+ return checkPolicyToken(token);
}
- return keys.toArray(new String[keys.size()]);
- }
+
+ @Override
+ public Policy getNotificationPolicy(Policy.Token token) {
+ enforcePolicyToken(token, "getNotificationPolicy");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mZenModeHelper.getNotificationPolicy();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void setNotificationPolicy(Policy.Token token, Policy policy) {
+ enforcePolicyToken(token, "setNotificationPolicy");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mZenModeHelper.setNotificationPolicy(policy);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ };
private String disableNotificationEffects(NotificationRecord record) {
if (mDisableNotificationEffects) {
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 Condition providers:");
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();
synchronized (mNotificationList) {
updateNotificationGroupsDesiredLocked();
update = makeRankingUpdateLocked(info);
+ mPolicyTokens.put(info.component, new Policy.Token(new Binder()));
}
try {
listener.onListenerConnected(update);
}
mLightTrimListeners.remove(removed);
updateNotificationGroupsDesiredLocked();
+ mPolicyTokens.remove(removed.component);
}
public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import android.app.AppOpsManager;
+import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Objects;
/**
* NotificationManagerService helper for functionality related to zen mode.
mConfig.writeXml(out);
}
+ public Policy getNotificationPolicy() {
+ return getNotificationPolicy(mConfig);
+ }
+
+ private static Policy getNotificationPolicy(ZenModeConfig config) {
+ return config == null ? null : config.toNotificationPolicy();
+ }
+
+ public void setNotificationPolicy(Policy policy) {
+ if (policy == null || mConfig == null) return;
+ final ZenModeConfig newConfig = mConfig.copy();
+ newConfig.applyNotificationPolicy(policy);
+ setConfig(newConfig, "setNotificationPolicy");
+ }
+
public ZenModeConfig getConfig() {
return mConfig;
}
if (config.equals(mConfig)) return true;
if (DEBUG) Log.d(TAG, "setConfig reason=" + reason);
ZenLog.traceConfig(mConfig, config);
+ final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
+ getNotificationPolicy(config));
mConfig = config;
dispatchOnConfigChanged();
+ if (policyChanged){
+ dispatchOnPolicyChanged();
+ }
final String val = Integer.toString(mConfig.hashCode());
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
if (!evaluateZenMode(reason, setRingerMode)) {
}
}
+ private void dispatchOnPolicyChanged() {
+ for (Callback callback : mCallbacks) {
+ callback.onPolicyChanged();
+ }
+ }
+
private void dispatchOnZenModeChanged() {
for (Callback callback : mCallbacks) {
callback.onZenModeChanged();
public static class Callback {
void onConfigChanged() {}
void onZenModeChanged() {}
+ void onPolicyChanged() {}
}
}