am 5feceebb
: New NotificationListenerService.
* commit '5feceebb892d4cb5777cea3c6174b206705d456b': New NotificationListenerService.
This commit is contained in:
@ -69,7 +69,6 @@ LOCAL_SRC_FILES += \
|
|||||||
core/java/android/app/IAlarmManager.aidl \
|
core/java/android/app/IAlarmManager.aidl \
|
||||||
core/java/android/app/IBackupAgent.aidl \
|
core/java/android/app/IBackupAgent.aidl \
|
||||||
core/java/android/app/IInstrumentationWatcher.aidl \
|
core/java/android/app/IInstrumentationWatcher.aidl \
|
||||||
core/java/android/app/INotificationListener.aidl \
|
|
||||||
core/java/android/app/INotificationManager.aidl \
|
core/java/android/app/INotificationManager.aidl \
|
||||||
core/java/android/app/IProcessObserver.aidl \
|
core/java/android/app/IProcessObserver.aidl \
|
||||||
core/java/android/app/ISearchManager.aidl \
|
core/java/android/app/ISearchManager.aidl \
|
||||||
@ -148,6 +147,7 @@ LOCAL_SRC_FILES += \
|
|||||||
core/java/android/os/IUpdateLock.aidl \
|
core/java/android/os/IUpdateLock.aidl \
|
||||||
core/java/android/os/IUserManager.aidl \
|
core/java/android/os/IUserManager.aidl \
|
||||||
core/java/android/os/IVibratorService.aidl \
|
core/java/android/os/IVibratorService.aidl \
|
||||||
|
core/java/android/service/notification/INotificationListener.aidl \
|
||||||
core/java/android/service/dreams/IDreamManager.aidl \
|
core/java/android/service/dreams/IDreamManager.aidl \
|
||||||
core/java/android/service/dreams/IDreamService.aidl \
|
core/java/android/service/dreams/IDreamService.aidl \
|
||||||
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
|
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
|
||||||
|
@ -159,6 +159,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
|
|||||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
|
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
|
||||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodSession.*)
|
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodSession.*)
|
||||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
|
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
|
||||||
|
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
|
||||||
# ************************************************
|
# ************************************************
|
||||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||||
# ************************************************
|
# ************************************************
|
||||||
|
@ -22,6 +22,7 @@ package android {
|
|||||||
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
|
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
|
||||||
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
|
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
|
||||||
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
|
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
|
||||||
|
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
|
||||||
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
|
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
|
||||||
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
|
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
|
||||||
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
|
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
|
||||||
@ -20839,6 +20840,38 @@ package android.service.dreams {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package android.service.notification {
|
||||||
|
|
||||||
|
public abstract class NotificationListenerService extends android.app.Service {
|
||||||
|
ctor public NotificationListenerService();
|
||||||
|
method public final void clearAllNotifications();
|
||||||
|
method public final void clearNotification(java.lang.String, java.lang.String, int);
|
||||||
|
method public android.os.IBinder onBind(android.content.Intent);
|
||||||
|
method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
|
||||||
|
method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
|
||||||
|
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatusBarNotification implements android.os.Parcelable {
|
||||||
|
ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
|
||||||
|
ctor public StatusBarNotification(android.os.Parcel);
|
||||||
|
method public android.service.notification.StatusBarNotification clone();
|
||||||
|
method public int describeContents();
|
||||||
|
method public int getUserId();
|
||||||
|
method public boolean isClearable();
|
||||||
|
method public boolean isOngoing();
|
||||||
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final android.os.Parcelable.Creator CREATOR;
|
||||||
|
field public final int id;
|
||||||
|
field public final android.app.Notification notification;
|
||||||
|
field public final java.lang.String pkg;
|
||||||
|
field public final long postTime;
|
||||||
|
field public final java.lang.String tag;
|
||||||
|
field public final android.os.UserHandle user;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
package android.service.textservice {
|
package android.service.textservice {
|
||||||
|
|
||||||
public abstract class SpellCheckerService extends android.app.Service {
|
public abstract class SpellCheckerService extends android.app.Service {
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
import android.app.INotificationListener;
|
|
||||||
import android.app.ITransientNotification;
|
import android.app.ITransientNotification;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.service.notification.INotificationListener;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
/** {@hide} */
|
/** {@hide} */
|
||||||
interface INotificationManager
|
interface INotificationManager
|
||||||
@ -41,7 +41,9 @@ interface INotificationManager
|
|||||||
StatusBarNotification[] getActiveNotifications(String callingPkg);
|
StatusBarNotification[] getActiveNotifications(String callingPkg);
|
||||||
StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
|
StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
|
||||||
|
|
||||||
void registerListener(in INotificationListener listener, String pkg, int userid);
|
void registerListener(in INotificationListener listener, in ComponentName component, int userid);
|
||||||
void unregisterListener(in INotificationListener listener, int userid);
|
void unregisterListener(in INotificationListener listener, int userid);
|
||||||
}
|
|
||||||
|
|
||||||
|
void clearNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
|
||||||
|
void clearAllNotificationsFromListener(in INotificationListener token);
|
||||||
|
}
|
@ -655,6 +655,22 @@ public final class Settings {
|
|||||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||||
public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
|
public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity Action: Show Notification listener settings.
|
||||||
|
* <p>
|
||||||
|
* In some cases, a matching Activity may not exist, so ensure you
|
||||||
|
* safeguard against this.
|
||||||
|
* <p>
|
||||||
|
* Input: Nothing.
|
||||||
|
* <p>
|
||||||
|
* Output: Nothing.
|
||||||
|
* @see android.service.notification.NotificationListenerService
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||||
|
public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS
|
||||||
|
= "android.settings.NOTIFICATION_LISTENER_SETTINGS";
|
||||||
|
|
||||||
// End of Intent actions for Settings
|
// End of Intent actions for Settings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package android.app;
|
package android.service.notification;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
oneway interface INotificationListener
|
oneway interface INotificationListener
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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.service.notification;
|
||||||
|
|
||||||
|
import android.annotation.SdkConstant;
|
||||||
|
import android.app.INotificationManager;
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public abstract class NotificationListenerService extends Service {
|
||||||
|
// TAG = "NotificationListenerService[MySubclass]"
|
||||||
|
private final String TAG = NotificationListenerService.class.getSimpleName()
|
||||||
|
+ "[" + getClass().getSimpleName() + "]";
|
||||||
|
|
||||||
|
private INotificationListenerWrapper mWrapper = null;
|
||||||
|
|
||||||
|
private INotificationManager mNoMan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Intent} that must be declared as handled by the service.
|
||||||
|
*/
|
||||||
|
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||||||
|
public static final String SERVICE_INTERFACE
|
||||||
|
= "android.service.notification.NotificationListenerService";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this method to learn about new notifications as they are posted by apps.
|
||||||
|
*
|
||||||
|
* @param sbn A data structure encapsulating the original {@link android.app.Notification}
|
||||||
|
* object as well as its identifying information (tag and id) and source
|
||||||
|
* (package name).
|
||||||
|
*/
|
||||||
|
public abstract void onNotificationPosted(StatusBarNotification sbn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this method to learn when notifications are removed.
|
||||||
|
* <P>
|
||||||
|
* This might occur because the user has dismissed the notification using system UI (or another
|
||||||
|
* notification listener) or because the app has withdrawn the notification.
|
||||||
|
*
|
||||||
|
* @param sbn A data structure encapsulating the original {@link android.app.Notification}
|
||||||
|
* object as well as its identifying information (tag and id) and source
|
||||||
|
* (package name).
|
||||||
|
*/
|
||||||
|
public abstract void onNotificationRemoved(StatusBarNotification sbn);
|
||||||
|
|
||||||
|
private final INotificationManager getNotificationInterface() {
|
||||||
|
if (mNoMan == null) {
|
||||||
|
mNoMan = INotificationManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||||
|
}
|
||||||
|
return mNoMan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inform the notification manager about dismissal of a single notification.
|
||||||
|
* <p>
|
||||||
|
* Use this if your listener has a user interface that allows the user to dismiss individual
|
||||||
|
* notifications, similar to the behavior of Android's status bar and notification panel.
|
||||||
|
* It should be called after the user dismisses a single notification using your UI;
|
||||||
|
* upon being informed, the notification manager will actually remove the notification
|
||||||
|
* and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
|
||||||
|
* <P>
|
||||||
|
* <b>Note:</b> If your listener allows the user to fire a notification's
|
||||||
|
* {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
|
||||||
|
* this method at that time <i>if</i> the Notification in question has the
|
||||||
|
* {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
|
||||||
|
*
|
||||||
|
* @param pkg Package of the notifying app.
|
||||||
|
* @param tag Tag of the notification as specified by the notifying app in
|
||||||
|
* {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
|
||||||
|
* @param id ID of the notification as specified by the notifying app in
|
||||||
|
* {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
|
||||||
|
*/
|
||||||
|
public final void clearNotification(String pkg, String tag, int id) {
|
||||||
|
try {
|
||||||
|
getNotificationInterface().clearNotificationFromListener(mWrapper, pkg, tag, id);
|
||||||
|
} catch (android.os.RemoteException ex) {
|
||||||
|
Log.v(TAG, "Unable to contact notification manager", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inform the notification manager about dismissal of all notifications.
|
||||||
|
* <p>
|
||||||
|
* Use this if your listener has a user interface that allows the user to dismiss all
|
||||||
|
* notifications, similar to the behavior of Android's status bar and notification panel.
|
||||||
|
* It should be called after the user invokes the "dismiss all" function of your UI;
|
||||||
|
* upon being informed, the notification manager will actually remove all active notifications
|
||||||
|
* and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks.
|
||||||
|
*
|
||||||
|
* {@see #clearNotification(String, String, int)}
|
||||||
|
*/
|
||||||
|
public final void clearAllNotifications() {
|
||||||
|
try {
|
||||||
|
getNotificationInterface().clearAllNotificationsFromListener(mWrapper);
|
||||||
|
} catch (android.os.RemoteException ex) {
|
||||||
|
Log.v(TAG, "Unable to contact notification manager", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
if (mWrapper == null) {
|
||||||
|
mWrapper = new INotificationListenerWrapper();
|
||||||
|
}
|
||||||
|
return mWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class INotificationListenerWrapper extends INotificationListener.Stub {
|
||||||
|
@Override
|
||||||
|
public void onNotificationPosted(StatusBarNotification sbn) {
|
||||||
|
NotificationListenerService.this.onNotificationPosted(sbn);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onNotificationRemoved(StatusBarNotification sbn) {
|
||||||
|
NotificationListenerService.this.onNotificationRemoved(sbn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.internal.statusbar;
|
package android.service.notification;
|
||||||
|
|
||||||
parcelable StatusBarNotification;
|
parcelable StatusBarNotification;
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.internal.statusbar;
|
package android.service.notification;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@ -23,34 +23,54 @@ import android.os.UserHandle;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class encapsulating a Notification. Sent by the NotificationManagerService to clients including
|
* Class encapsulating a Notification. Sent by the NotificationManagerService to clients including
|
||||||
* the IStatusBar (in System UI).
|
* the status bar and any {@link android.service.notification.NotificationListenerService}s.
|
||||||
*/
|
*/
|
||||||
public class StatusBarNotification implements Parcelable {
|
public class StatusBarNotification implements Parcelable {
|
||||||
|
/** The package of the app that posted the notification. */
|
||||||
public final String pkg;
|
public final String pkg;
|
||||||
public final String basePkg;
|
/** The id supplied to {@link android.app.NotificationManager#notify}. */
|
||||||
public final int id;
|
public final int id;
|
||||||
|
/** The tag supplied to {@link android.app.NotificationManager#notify}, or null if no tag
|
||||||
|
* was specified. */
|
||||||
public final String tag;
|
public final String tag;
|
||||||
|
|
||||||
|
/** The notifying app's calling uid. @hide */
|
||||||
public final int uid;
|
public final int uid;
|
||||||
|
/** The notifying app's base package. @hide */
|
||||||
|
public final String basePkg;
|
||||||
|
/** @hide */
|
||||||
public final int initialPid;
|
public final int initialPid;
|
||||||
// TODO: make this field private and move callers to an accessor that
|
// TODO: make this field private and move callers to an accessor that
|
||||||
// ensures sourceUser is applied.
|
// ensures sourceUser is applied.
|
||||||
|
|
||||||
|
/** The {@link android.app.Notification} supplied to
|
||||||
|
* {@link android.app.NotificationManager#notify}. */
|
||||||
public final Notification notification;
|
public final Notification notification;
|
||||||
public final int score;
|
/** The {@link android.os.UserHandle} for whom this notification is intended. */
|
||||||
public final UserHandle user;
|
public final UserHandle user;
|
||||||
|
/** The time (in {@link System#currentTimeMillis} time) the notification was posted,
|
||||||
|
* which may be different than {@link android.app.Notification#when}.
|
||||||
|
*/
|
||||||
public final long postTime;
|
public final long postTime;
|
||||||
|
|
||||||
/** This is temporarily needed for the JB MR1 PDK. */
|
/** @hide */
|
||||||
|
public final int score;
|
||||||
|
|
||||||
|
/** This is temporarily needed for the JB MR1 PDK.
|
||||||
|
* @hide */
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
|
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
|
||||||
Notification notification) {
|
Notification notification) {
|
||||||
this(pkg, id, tag, uid, initialPid, score, notification, UserHandle.OWNER);
|
this(pkg, id, tag, uid, initialPid, score, notification, UserHandle.OWNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
|
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
|
||||||
Notification notification, UserHandle user) {
|
Notification notification, UserHandle user) {
|
||||||
this(pkg, null, id, tag, uid, initialPid, score, notification, user);
|
this(pkg, null, id, tag, uid, initialPid, score, notification, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
|
public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
|
||||||
int initialPid, int score, Notification notification, UserHandle user) {
|
int initialPid, int score, Notification notification, UserHandle user) {
|
||||||
this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
|
this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
|
||||||
@ -147,10 +167,17 @@ public class StatusBarNotification implements Parcelable {
|
|||||||
this.score, this.notification);
|
this.score, this.notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Convenience method to check the notification's flags for
|
||||||
|
* {@link Notification#FLAG_ONGOING_EVENT}.
|
||||||
|
*/
|
||||||
public boolean isOngoing() {
|
public boolean isOngoing() {
|
||||||
return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
|
return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Convenience method to check the notification's flags for
|
||||||
|
* either {@link Notification#FLAG_ONGOING_EVENT} or
|
||||||
|
* {@link Notification#FLAG_NO_CLEAR}.
|
||||||
|
*/
|
||||||
public boolean isClearable() {
|
public boolean isClearable() {
|
||||||
return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0)
|
return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0)
|
||||||
&& ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
|
&& ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
|
@ -17,7 +17,7 @@
|
|||||||
package com.android.internal.statusbar;
|
package com.android.internal.statusbar;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
oneway interface IStatusBar
|
oneway interface IStatusBar
|
||||||
|
@ -19,7 +19,7 @@ package com.android.internal.statusbar;
|
|||||||
import com.android.internal.statusbar.IStatusBar;
|
import com.android.internal.statusbar.IStatusBar;
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarIconList;
|
import com.android.internal.statusbar.StatusBarIconList;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
interface IStatusBarService
|
interface IStatusBarService
|
||||||
|
@ -2193,6 +2193,14 @@
|
|||||||
android:description="@string/permdesc_accessNotifications"
|
android:description="@string/permdesc_accessNotifications"
|
||||||
android:protectionLevel="signature|system" />
|
android:protectionLevel="signature|system" />
|
||||||
|
|
||||||
|
<!-- Must be required by an {@link
|
||||||
|
android.service.notification.NotificationListenerService},
|
||||||
|
to ensure that only the system can bind to it. -->
|
||||||
|
<permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
|
||||||
|
android:label="@string/permlab_bindNotificationListenerService"
|
||||||
|
android:description="@string/permdesc_bindNotificationListenerService"
|
||||||
|
android:protectionLevel="signature" />
|
||||||
|
|
||||||
<!-- The system process is explicitly the only one allowed to launch the
|
<!-- The system process is explicitly the only one allowed to launch the
|
||||||
confirmation UI for full backup/restore -->
|
confirmation UI for full backup/restore -->
|
||||||
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
|
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
|
||||||
|
@ -1816,6 +1816,11 @@
|
|||||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||||
<string name="permdesc_accessNotifications">Allows the app to retrieve, examine, and clear notifications, including those posted by other apps.</string>
|
<string name="permdesc_accessNotifications">Allows the app to retrieve, examine, and clear notifications, including those posted by other apps.</string>
|
||||||
|
|
||||||
|
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||||
|
<string name="permlab_bindNotificationListenerService">bind to a notification listener service</string>
|
||||||
|
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||||
|
<string name="permdesc_bindNotificationListenerService">Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps.</string>
|
||||||
|
|
||||||
<!-- Policy administration -->
|
<!-- Policy administration -->
|
||||||
|
|
||||||
<!-- Title of policy access to limiting the user's password choices -->
|
<!-- Title of policy access to limiting the user's password choices -->
|
||||||
@ -3508,6 +3513,9 @@
|
|||||||
<string name="wallpaper_binding_label">Wallpaper</string>
|
<string name="wallpaper_binding_label">Wallpaper</string>
|
||||||
<!-- Dialog title for user to select a different wallpaper from service list -->
|
<!-- Dialog title for user to select a different wallpaper from service list -->
|
||||||
<string name="chooser_wallpaper">Change wallpaper</string>
|
<string name="chooser_wallpaper">Change wallpaper</string>
|
||||||
|
<!-- Label to show for a service that is running because it is observing
|
||||||
|
the user's notifications. -->
|
||||||
|
<string name="notification_listener_binding_label">Notification listener</string>
|
||||||
|
|
||||||
<!-- Do Not Translate: Alternate eri.xml -->
|
<!-- Do Not Translate: Alternate eri.xml -->
|
||||||
<string name="alternate_eri_file">/data/eri.xml</string>
|
<string name="alternate_eri_file">/data/eri.xml</string>
|
||||||
|
@ -1638,6 +1638,7 @@
|
|||||||
<java-symbol type="string" name="launch_warning_title" />
|
<java-symbol type="string" name="launch_warning_title" />
|
||||||
<java-symbol type="string" name="low_internal_storage_view_text" />
|
<java-symbol type="string" name="low_internal_storage_view_text" />
|
||||||
<java-symbol type="string" name="low_internal_storage_view_title" />
|
<java-symbol type="string" name="low_internal_storage_view_title" />
|
||||||
|
<java-symbol type="string" name="notification_listener_binding_label" />
|
||||||
<java-symbol type="string" name="report" />
|
<java-symbol type="string" name="report" />
|
||||||
<java-symbol type="string" name="select_input_method" />
|
<java-symbol type="string" name="select_input_method" />
|
||||||
<java-symbol type="string" name="select_keyboard_layout_notification_title" />
|
<java-symbol type="string" name="select_keyboard_layout_notification_title" />
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar;
|
package com.android.systemui.statusbar;
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import com.android.internal.statusbar.IStatusBarService;
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarIconList;
|
import com.android.internal.statusbar.StatusBarIconList;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.internal.widget.SizeAdaptiveLayout;
|
import com.android.internal.widget.SizeAdaptiveLayout;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SearchPanelView;
|
import com.android.systemui.SearchPanelView;
|
||||||
|
@ -20,10 +20,10 @@ import android.os.Handler;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import com.android.internal.statusbar.IStatusBar;
|
import com.android.internal.statusbar.IStatusBar;
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarIconList;
|
import com.android.internal.statusbar.StatusBarIconList;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class takes the functions from IStatusBar that come in on
|
* This class takes the functions from IStatusBar that come in on
|
||||||
|
@ -16,12 +16,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar;
|
package com.android.systemui.statusbar;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -26,6 +26,7 @@ import android.app.ActivityManagerNative;
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -76,7 +77,6 @@ import android.widget.ScrollView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.systemui.EventLogTags;
|
import com.android.systemui.EventLogTags;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.BaseStatusBar;
|
import com.android.systemui.statusbar.BaseStatusBar;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@ -23,10 +24,7 @@ import android.os.Handler;
|
|||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Slog;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.TextSwitcher;
|
import android.widget.TextSwitcher;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -35,7 +33,6 @@ import android.widget.ImageSwitcher;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.internal.util.CharSequences;
|
import com.android.internal.util.CharSequences;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
@ -28,16 +28,11 @@ import android.content.IntentFilter;
|
|||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Slog;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
// private NM API
|
// private NM API
|
||||||
import android.app.INotificationManager;
|
import android.app.INotificationManager;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
|
|
||||||
|
|
||||||
public class LocationController extends BroadcastReceiver {
|
public class LocationController extends BroadcastReceiver {
|
||||||
private static final String TAG = "StatusBar.LocationController";
|
private static final String TAG = "StatusBar.LocationController";
|
||||||
|
@ -23,6 +23,7 @@ import android.app.ActivityManagerNative;
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -58,7 +59,6 @@ import android.widget.ScrollView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.BaseStatusBar;
|
import com.android.systemui.statusbar.BaseStatusBar;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
|
@ -21,9 +21,9 @@ import java.util.Arrays;
|
|||||||
import android.animation.LayoutTransition;
|
import android.animation.LayoutTransition;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -37,11 +37,9 @@ import android.view.ViewGroup;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.StatusBarIconView;
|
import com.android.systemui.statusbar.StatusBarIconView;
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.tv;
|
package com.android.systemui.statusbar.tv;
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.systemui.statusbar.BaseStatusBar;
|
import com.android.systemui.statusbar.BaseStatusBar;
|
||||||
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
@ -26,16 +26,17 @@ import android.app.AppGlobals;
|
|||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.IActivityManager;
|
import android.app.IActivityManager;
|
||||||
import android.app.INotificationManager;
|
import android.app.INotificationManager;
|
||||||
import android.app.INotificationListener;
|
|
||||||
import android.app.ITransientNotification;
|
import android.app.ITransientNotification;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@ -57,6 +58,9 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.service.notification.INotificationListener;
|
||||||
|
import android.service.notification.NotificationListenerService;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
@ -68,8 +72,6 @@ import android.view.accessibility.AccessibilityEvent;
|
|||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
@ -121,6 +123,8 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
|
private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
|
||||||
private static final boolean ENABLE_BLOCKED_TOASTS = true;
|
private static final boolean ENABLE_BLOCKED_TOASTS = true;
|
||||||
|
|
||||||
|
private static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":";
|
||||||
|
|
||||||
final Context mContext;
|
final Context mContext;
|
||||||
final IActivityManager mAm;
|
final IActivityManager mAm;
|
||||||
final UserManager mUserManager;
|
final UserManager mUserManager;
|
||||||
@ -163,8 +167,18 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
|
|
||||||
private final AppOpsManager mAppOps;
|
private final AppOpsManager mAppOps;
|
||||||
|
|
||||||
private ArrayList<NotificationListenerInfo> mListeners = new ArrayList<NotificationListenerInfo>();
|
// contains connections to all connected listeners, including app services
|
||||||
private ArrayList<String> mEnabledListenersForCurrentUser = new ArrayList<String>();
|
// and system listeners
|
||||||
|
private ArrayList<NotificationListenerInfo> mListeners
|
||||||
|
= new ArrayList<NotificationListenerInfo>();
|
||||||
|
// things that will be put into mListeners as soon as they're ready
|
||||||
|
private ArrayList<String> mServicesBinding = new ArrayList<String>();
|
||||||
|
// lists the component names of all enabled (and therefore connected) listener
|
||||||
|
// app services for the current user only
|
||||||
|
private HashSet<ComponentName> mEnabledListenersForCurrentUser
|
||||||
|
= new HashSet<ComponentName>();
|
||||||
|
// Just the packages from mEnabledListenersForCurrentUser
|
||||||
|
private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();
|
||||||
|
|
||||||
// Notification control database. For now just contains disabled packages.
|
// Notification control database. For now just contains disabled packages.
|
||||||
private AtomicFile mPolicyFile;
|
private AtomicFile mPolicyFile;
|
||||||
@ -181,27 +195,42 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
|
|
||||||
private class NotificationListenerInfo implements DeathRecipient {
|
private class NotificationListenerInfo implements DeathRecipient {
|
||||||
INotificationListener listener;
|
INotificationListener listener;
|
||||||
String pkg;
|
ComponentName component;
|
||||||
int userid;
|
int userid;
|
||||||
boolean isSystem;
|
boolean isSystem;
|
||||||
|
ServiceConnection connection;
|
||||||
|
|
||||||
public NotificationListenerInfo(INotificationListener listener, String pkg, int userid,
|
public NotificationListenerInfo(INotificationListener listener, ComponentName component,
|
||||||
boolean isSystem) {
|
int userid, boolean isSystem) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.pkg = pkg;
|
this.component = component;
|
||||||
this.userid = userid;
|
this.userid = userid;
|
||||||
this.isSystem = isSystem;
|
this.isSystem = isSystem;
|
||||||
|
this.connection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationListenerInfo(INotificationListener listener, ComponentName component,
|
||||||
|
int userid, ServiceConnection connection) {
|
||||||
|
this.listener = listener;
|
||||||
|
this.component = component;
|
||||||
|
this.userid = userid;
|
||||||
|
this.isSystem = false;
|
||||||
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean enabledAndUserMatches(StatusBarNotification sbn) {
|
boolean enabledAndUserMatches(StatusBarNotification sbn) {
|
||||||
final int nid = sbn.getUserId();
|
final int nid = sbn.getUserId();
|
||||||
if (!(isSystem || isEnabledForUser(nid))) return false;
|
if (!isEnabledForCurrentUser()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (this.userid == UserHandle.USER_ALL) return true;
|
if (this.userid == UserHandle.USER_ALL) return true;
|
||||||
return (nid == UserHandle.USER_ALL || nid == this.userid);
|
return (nid == UserHandle.USER_ALL || nid == this.userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
|
public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
|
||||||
if (!enabledAndUserMatches(sbn)) return;
|
if (!enabledAndUserMatches(sbn)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
listener.onNotificationPosted(sbn);
|
listener.onNotificationPosted(sbn);
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
@ -220,15 +249,17 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
unregisterListener(this.listener, this.userid);
|
if (connection == null) {
|
||||||
|
// This is not a service; it won't be recreated. We can give up this connection.
|
||||||
|
unregisterListener(this.listener, this.userid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** convenience method for looking in mEnabledListenersForCurrentUser */
|
/** convenience method for looking in mEnabledListenersForCurrentUser */
|
||||||
public boolean isEnabledForUser(int userid) {
|
public boolean isEnabledForCurrentUser() {
|
||||||
for (int i=0; i<mEnabledListenersForCurrentUser.size(); i++) {
|
if (this.isSystem) return true;
|
||||||
if (this.pkg.equals(mEnabledListenersForCurrentUser.get(i))) return true;
|
if (this.connection == null) return false;
|
||||||
}
|
return mEnabledListenersForCurrentUser.contains(this.component);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,6 +465,12 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System-only API for getting a list of current (i.e. not cleared) notifications.
|
||||||
|
*
|
||||||
|
* Requires ACCESS_NOTIFICATIONS which is signature|system.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public StatusBarNotification[] getActiveNotifications(String callingPkg) {
|
public StatusBarNotification[] getActiveNotifications(String callingPkg) {
|
||||||
// enforce() will ensure the calling uid has the correct permission
|
// enforce() will ensure the calling uid has the correct permission
|
||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
|
||||||
@ -456,6 +493,12 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System-only API for getting a list of recent (cleared, no longer shown) notifications.
|
||||||
|
*
|
||||||
|
* Requires ACCESS_NOTIFICATIONS which is signature|system.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
|
public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
|
||||||
// enforce() will ensure the calling uid has the correct permission
|
// enforce() will ensure the calling uid has the correct permission
|
||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
|
||||||
@ -474,27 +517,76 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean packageCanTapNotificationsForUser(final int uid, final String pkg) {
|
/**
|
||||||
// Make sure the package and uid match, and that the package is allowed access
|
* Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS
|
||||||
return (AppOpsManager.MODE_ALLOWED
|
* is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
|
||||||
== mAppOps.checkOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, pkg));
|
*/
|
||||||
|
void rebindListenerServices() {
|
||||||
|
String flat = Settings.Secure.getString(
|
||||||
|
mContext.getContentResolver(),
|
||||||
|
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
|
||||||
|
|
||||||
|
NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
|
||||||
|
final ArrayList<ComponentName> toAdd;
|
||||||
|
final int currentUser = ActivityManager.getCurrentUser();
|
||||||
|
|
||||||
|
synchronized (mNotificationList) {
|
||||||
|
// unbind and remove all existing listeners
|
||||||
|
toRemove = mListeners.toArray(toRemove);
|
||||||
|
|
||||||
|
toAdd = new ArrayList<ComponentName>();
|
||||||
|
final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
|
||||||
|
final HashSet<String> newPackages = new HashSet<String>();
|
||||||
|
|
||||||
|
// decode the list of components
|
||||||
|
if (flat != null) {
|
||||||
|
String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
|
||||||
|
for (int i=0; i<components.length; i++) {
|
||||||
|
final ComponentName component
|
||||||
|
= ComponentName.unflattenFromString(components[i]);
|
||||||
|
if (component != null) {
|
||||||
|
newEnabled.add(component);
|
||||||
|
toAdd.add(component);
|
||||||
|
newPackages.add(component.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mEnabledListenersForCurrentUser = newEnabled;
|
||||||
|
mEnabledListenerPackageNames = newPackages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NotificationListenerInfo info : toRemove) {
|
||||||
|
final ComponentName component = info.component;
|
||||||
|
final int oldUser = info.userid;
|
||||||
|
Slog.v(TAG, "disabling notification listener for user " + oldUser + ": " + component);
|
||||||
|
unregisterListenerService(component, info.userid);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int N = toAdd.size();
|
||||||
|
for (int i=0; i<N; i++) {
|
||||||
|
final ComponentName component = toAdd.get(i);
|
||||||
|
Slog.v(TAG, "enabling notification listener for user " + currentUser + ": "
|
||||||
|
+ component);
|
||||||
|
registerListenerService(component, currentUser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener binder directly with the notification manager.
|
||||||
|
*
|
||||||
|
* Only works with system callers. Apps should extend
|
||||||
|
* {@link android.service.notification.NotificationListenerService}.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void registerListener(final INotificationListener listener,
|
public void registerListener(final INotificationListener listener,
|
||||||
final String pkg, final int userid) {
|
final ComponentName component, final int userid) {
|
||||||
// ensure system or allowed pkg
|
checkCallerIsSystem();
|
||||||
int uid = Binder.getCallingUid();
|
|
||||||
boolean isSystem = (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0);
|
|
||||||
if (!(isSystem || packageCanTapNotificationsForUser(uid, pkg))) {
|
|
||||||
throw new SecurityException("Package " + pkg
|
|
||||||
+ " may not listen for notifications");
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mNotificationList) {
|
synchronized (mNotificationList) {
|
||||||
try {
|
try {
|
||||||
NotificationListenerInfo info
|
NotificationListenerInfo info
|
||||||
= new NotificationListenerInfo(listener, pkg, userid, isSystem);
|
= new NotificationListenerInfo(listener, component, userid, true);
|
||||||
listener.asBinder().linkToDeath(info, 0);
|
listener.asBinder().linkToDeath(info, 0);
|
||||||
mListeners.add(info);
|
mListeners.add(info);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@ -503,6 +595,90 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of registerListener that takes the name of a
|
||||||
|
* {@link android.service.notification.NotificationListenerService} to bind to.
|
||||||
|
*
|
||||||
|
* This is the mechanism by which third parties may subscribe to notifications.
|
||||||
|
*/
|
||||||
|
private void registerListenerService(final ComponentName name, final int userid) {
|
||||||
|
checkCallerIsSystem();
|
||||||
|
|
||||||
|
if (DBG) Slog.v(TAG, "registerListenerService: " + name + " u=" + userid);
|
||||||
|
|
||||||
|
synchronized (mNotificationList) {
|
||||||
|
final String servicesBindingTag = name.toString() + "/" + userid;
|
||||||
|
if (mServicesBinding.contains(servicesBindingTag)) {
|
||||||
|
// stop registering this thing already! we're working on it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mServicesBinding.add(servicesBindingTag);
|
||||||
|
|
||||||
|
final int N = mListeners.size();
|
||||||
|
for (int i=N-1; i>=0; i--) {
|
||||||
|
final NotificationListenerInfo info = mListeners.get(i);
|
||||||
|
if (name.equals(info.component)
|
||||||
|
&& info.userid == userid) {
|
||||||
|
// cut old connections
|
||||||
|
if (DBG) Slog.v(TAG, " disconnecting old listener: " + info.listener);
|
||||||
|
mListeners.remove(i);
|
||||||
|
if (info.connection != null) {
|
||||||
|
mContext.unbindService(info.connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent intent = new Intent(NotificationListenerService.SERVICE_INTERFACE);
|
||||||
|
intent.setComponent(name);
|
||||||
|
|
||||||
|
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
|
||||||
|
com.android.internal.R.string.notification_listener_binding_label);
|
||||||
|
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
|
||||||
|
mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0));
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (DBG) Slog.v(TAG, "binding: " + intent);
|
||||||
|
if (!mContext.bindServiceAsUser(intent,
|
||||||
|
new ServiceConnection() {
|
||||||
|
INotificationListener mListener;
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
synchronized (mNotificationList) {
|
||||||
|
mServicesBinding.remove(servicesBindingTag);
|
||||||
|
try {
|
||||||
|
mListener = INotificationListener.Stub.asInterface(service);
|
||||||
|
NotificationListenerInfo info = new NotificationListenerInfo(
|
||||||
|
mListener, name, userid, this);
|
||||||
|
service.linkToDeath(info, 0);
|
||||||
|
mListeners.add(info);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// already dead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
Slog.v(TAG, "notification listener connection lost: " + name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Context.BIND_AUTO_CREATE,
|
||||||
|
new UserHandle(userid)))
|
||||||
|
{
|
||||||
|
mServicesBinding.remove(servicesBindingTag);
|
||||||
|
Slog.w(TAG, "Unable to bind listener service: " + intent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (SecurityException ex) {
|
||||||
|
Slog.e(TAG, "Unable to bind listener service: " + intent, ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a listener binder directly
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void unregisterListener(INotificationListener listener, int userid) {
|
public void unregisterListener(INotificationListener listener, int userid) {
|
||||||
// no need to check permissions; if your listener binder is in the list,
|
// no need to check permissions; if your listener binder is in the list,
|
||||||
@ -513,12 +689,39 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
for (int i=N-1; i>=0; i--) {
|
for (int i=N-1; i>=0; i--) {
|
||||||
final NotificationListenerInfo info = mListeners.get(i);
|
final NotificationListenerInfo info = mListeners.get(i);
|
||||||
if (info.listener == listener && info.userid == userid) {
|
if (info.listener == listener && info.userid == userid) {
|
||||||
mListeners.remove(listener);
|
mListeners.remove(i);
|
||||||
|
if (info.connection != null) {
|
||||||
|
mContext.unbindService(info.connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a listener service for the given user by ComponentName
|
||||||
|
*/
|
||||||
|
private void unregisterListenerService(ComponentName name, int userid) {
|
||||||
|
checkCallerIsSystem();
|
||||||
|
|
||||||
|
synchronized (mNotificationList) {
|
||||||
|
final int N = mListeners.size();
|
||||||
|
for (int i=N-1; i>=0; i--) {
|
||||||
|
final NotificationListenerInfo info = mListeners.get(i);
|
||||||
|
if (name.equals(info.component)
|
||||||
|
&& info.userid == userid) {
|
||||||
|
mListeners.remove(i);
|
||||||
|
if (info.connection != null) {
|
||||||
|
mContext.unbindService(info.connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* asynchronously notify all listeners about a new notification
|
||||||
|
*/
|
||||||
private void notifyPostedLocked(NotificationRecord n) {
|
private void notifyPostedLocked(NotificationRecord n) {
|
||||||
final StatusBarNotification sbn = n.sbn;
|
final StatusBarNotification sbn = n.sbn;
|
||||||
for (final NotificationListenerInfo info : mListeners) {
|
for (final NotificationListenerInfo info : mListeners) {
|
||||||
@ -530,6 +733,9 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* asynchronously notify all listeners about a removed notification
|
||||||
|
*/
|
||||||
private void notifyRemovedLocked(NotificationRecord n) {
|
private void notifyRemovedLocked(NotificationRecord n) {
|
||||||
final StatusBarNotification sbn = n.sbn;
|
final StatusBarNotification sbn = n.sbn;
|
||||||
for (final NotificationListenerInfo info : mListeners) {
|
for (final NotificationListenerInfo info : mListeners) {
|
||||||
@ -541,6 +747,57 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- APIs to support listeners clicking/clearing notifications --
|
||||||
|
|
||||||
|
private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
|
||||||
|
final IBinder token = listener.asBinder();
|
||||||
|
final int N = mListeners.size();
|
||||||
|
for (int i=0; i<N; i++) {
|
||||||
|
final NotificationListenerInfo info = mListeners.get(i);
|
||||||
|
if (info.listener.asBinder() == token) return info;
|
||||||
|
}
|
||||||
|
throw new SecurityException("Disallowed call from unknown listener: " + listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow an INotificationListener to simulate a "clear all" operation.
|
||||||
|
*
|
||||||
|
* {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications}
|
||||||
|
*
|
||||||
|
* @param token The binder for the listener, to check that the caller is allowed
|
||||||
|
*/
|
||||||
|
public void clearAllNotificationsFromListener(INotificationListener token) {
|
||||||
|
NotificationListenerInfo info = checkListenerToken(token);
|
||||||
|
long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
cancelAll(info.userid);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow an INotificationListener to simulate clearing (dismissing) a single notification.
|
||||||
|
*
|
||||||
|
* {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
|
||||||
|
*
|
||||||
|
* @param token The binder for the listener, to check that the caller is allowed
|
||||||
|
*/
|
||||||
|
public void clearNotificationFromListener(INotificationListener token, String pkg, String tag, int id) {
|
||||||
|
NotificationListenerInfo info = checkListenerToken(token);
|
||||||
|
long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
cancelNotification(pkg, tag, id, 0,
|
||||||
|
Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
|
||||||
|
true,
|
||||||
|
info.userid);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- end of listener APIs --
|
||||||
|
|
||||||
public static final class NotificationRecord
|
public static final class NotificationRecord
|
||||||
{
|
{
|
||||||
final StatusBarNotification sbn;
|
final StatusBarNotification sbn;
|
||||||
@ -759,12 +1016,23 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
pkgList = new String[]{pkgName};
|
pkgList = new String[]{pkgName};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean anyListenersInvolved = false;
|
||||||
if (pkgList != null && (pkgList.length > 0)) {
|
if (pkgList != null && (pkgList.length > 0)) {
|
||||||
for (String pkgName : pkgList) {
|
for (String pkgName : pkgList) {
|
||||||
cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
|
cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
|
||||||
UserHandle.USER_ALL);
|
UserHandle.USER_ALL);
|
||||||
|
if (mEnabledListenerPackageNames.contains(pkgName)) {
|
||||||
|
anyListenersInvolved = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anyListenersInvolved) {
|
||||||
|
// make sure we're still bound to any of our
|
||||||
|
// listeners who may have just upgraded
|
||||||
|
rebindListenerServices();
|
||||||
|
}
|
||||||
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
|
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
|
||||||
// Keep track of screen on/off state, but do not turn off the notification light
|
// Keep track of screen on/off state, but do not turn off the notification light
|
||||||
// until user passes through the lock screen or views the notification.
|
// until user passes through the lock screen or views the notification.
|
||||||
@ -795,7 +1063,7 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
= Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
|
= Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
|
||||||
|
|
||||||
private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
|
private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
|
||||||
= Settings.System.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
|
= Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
|
||||||
|
|
||||||
SettingsObserver(Handler handler) {
|
SettingsObserver(Handler handler) {
|
||||||
super(handler);
|
super(handler);
|
||||||
@ -804,9 +1072,9 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
void observe() {
|
void observe() {
|
||||||
ContentResolver resolver = mContext.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
|
resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
|
||||||
false, this);
|
false, this, UserHandle.USER_ALL);
|
||||||
resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
|
resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
|
||||||
false, this);
|
false, this, UserHandle.USER_ALL);
|
||||||
update(null);
|
update(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,19 +1093,7 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
|
if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
|
||||||
String pkglist = Settings.Secure.getString(
|
rebindListenerServices();
|
||||||
mContext.getContentResolver(),
|
|
||||||
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
|
|
||||||
mEnabledListenersForCurrentUser.clear();
|
|
||||||
if (pkglist != null) {
|
|
||||||
String[] pkgs = pkglist.split(";");
|
|
||||||
for (int i=0; i<pkgs.length; i++) {
|
|
||||||
final String pkg = pkgs[i];
|
|
||||||
if (pkg != null && ! "".equals(pkg)) {
|
|
||||||
mEnabledListenersForCurrentUser.add(pkgs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -956,6 +1212,9 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
|
|
||||||
// no beeping until we're basically done booting
|
// no beeping until we're basically done booting
|
||||||
mSystemReady = true;
|
mSystemReady = true;
|
||||||
|
|
||||||
|
// make sure our listener services are properly bound
|
||||||
|
rebindListenerServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toasts
|
// Toasts
|
||||||
@ -1781,16 +2040,17 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
|
|
||||||
pw.println("Current Notification Manager state:");
|
pw.println("Current Notification Manager state:");
|
||||||
|
|
||||||
pw.print(" Enabled listeners: [");
|
pw.println(" Listeners (" + mEnabledListenersForCurrentUser.size()
|
||||||
for (String pkg : mEnabledListenersForCurrentUser) {
|
+ ") enabled for current user:");
|
||||||
pw.print(" " + pkg);
|
for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
|
||||||
|
pw.println(" " + cmpt);
|
||||||
}
|
}
|
||||||
pw.println(" ]");
|
|
||||||
|
|
||||||
pw.println(" Live listeners:");
|
pw.println(" Live listeners (" + mListeners.size() + "):");
|
||||||
for (NotificationListenerInfo info : mListeners) {
|
for (NotificationListenerInfo info : mListeners) {
|
||||||
pw.println(" " + info.pkg + " (user " + info.userid + "): " + info.listener
|
pw.println(" " + info.component
|
||||||
+ (info.isSystem?" SYSTEM":""));
|
+ " (user " + info.userid + "): " + info.listener
|
||||||
|
+ (info.isSystem?" SYSTEM":""));
|
||||||
}
|
}
|
||||||
|
|
||||||
int N;
|
int N;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -33,7 +34,6 @@ import com.android.internal.statusbar.IStatusBar;
|
|||||||
import com.android.internal.statusbar.IStatusBarService;
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.internal.statusbar.StatusBarIconList;
|
import com.android.internal.statusbar.StatusBarIconList;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
import com.android.server.wm.WindowManagerService;
|
import com.android.server.wm.WindowManagerService;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
|
@ -33,13 +33,10 @@ import android.util.Log;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
|
||||||
// private NM API
|
// private NM API
|
||||||
import android.app.INotificationManager;
|
import android.app.INotificationManager;
|
||||||
import com.android.internal.statusbar.StatusBarNotification;
|
|
||||||
|
|
||||||
public class NotificationTestList extends TestActivity
|
public class NotificationTestList extends TestActivity
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user