diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 8794d319e1792..e6bcea1eb4ab1 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -43,6 +43,7 @@ interface IStatusBarService void onPanelRevealed(); void onPanelHidden(); void onNotificationClick(String key); + void onNotificationActionClick(String key, int actionIndex); void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId); void onClearAllNotifications(int userId); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f5e5517b731c4..7c74246ba4d23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -69,6 +69,7 @@ import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; import android.view.ViewStub; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -266,6 +267,7 @@ public abstract class BaseStatusBar extends SystemUI implements if (DEBUG) { Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); } + logActionClick(view); // The intent we are sending is for the application, which // won't have permission to immediately start an activity after // the user switches to home. We know it is safe to do at this @@ -308,6 +310,37 @@ public abstract class BaseStatusBar extends SystemUI implements } } + private void logActionClick(View view) { + ViewParent parent = view.getParent(); + String key = getNotificationKeyForParent(parent); + if (key == null) { + Log.w(TAG, "Couldn't determine notification for click."); + return; + } + int index = -1; + // If this is a default template, determine the index of the button. + if (view.getId() == com.android.internal.R.id.action0 && + parent != null && parent instanceof ViewGroup) { + ViewGroup actionGroup = (ViewGroup) parent; + index = actionGroup.indexOfChild(view); + } + try { + mBarService.onNotificationActionClick(key, index); + } catch (RemoteException e) { + // Ignore + } + } + + private String getNotificationKeyForParent(ViewParent parent) { + while (parent != null) { + if (parent instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey(); + } + parent = parent.getParent(); + } + return null; + } + private boolean superOnClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { return super.onClickHandler(view, pendingIntent, fillInIntent); diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 64d8f6fd09f56..f7925f0b6e152 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -69,6 +69,8 @@ option java_package com.android.server 27511 notification_expansion (key|3),(user_action|1),(expanded|1) # when a notification has been clicked 27520 notification_clicked (key|3) +# when a notification action button has been clicked +27521 notification_action_clicked (key|3),(action_index|1) # --------------------------- # Watchdog.java diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java index 97f0a1ec263d4..24fc45508bc1b 100644 --- a/services/core/java/com/android/server/notification/NotificationDelegate.java +++ b/services/core/java/com/android/server/notification/NotificationDelegate.java @@ -20,6 +20,7 @@ public interface NotificationDelegate { void onSetDisabled(int status); void onClearAll(int callingUid, int callingPid, int userId); void onNotificationClick(int callingUid, int callingPid, String key); + void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex); void onNotificationClear(int callingUid, int callingPid, String pkg, String tag, int id, int userId); void onNotificationError(int callingUid, int callingPid, diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 22f060f9c8e20..e0708cbcb4171 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -540,6 +540,20 @@ public class NotificationManagerService extends SystemService { } } + @Override + public void onNotificationActionClick(int callingUid, int callingPid, String key, + int actionIndex) { + synchronized (mNotificationList) { + EventLogTags.writeNotificationActionClicked(key, actionIndex); + NotificationRecord r = mNotificationsByKey.get(key); + if (r == null) { + Log.w(TAG, "No notification with key: " + key); + return; + } + // TODO: Log action click via UsageStats. + } + } + @Override public void onNotificationClear(int callingUid, int callingPid, String pkg, String tag, int id, int userId) { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index f85e2d9a29b64..86c78dd643f1a 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -522,6 +522,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } + @Override + public void onNotificationActionClick(String key, int actionIndex) { + enforceStatusBarService(); + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + long identity = Binder.clearCallingIdentity(); + try { + mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key, + actionIndex); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId) {