Loading core/java/com/android/internal/statusbar/IStatusBarService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ interface IStatusBarService int uid, int initialPid, String message, int userId); void onClearAllNotifications(int userId); void onNotificationClear(String pkg, String tag, int id, int userId); void onNotificationVisibilityChanged( in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys); void setSystemUiVisibility(int vis, int mask); void setHardKeyboardEnabled(boolean enabled); void toggleRecentApps(); Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +119 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; Loading Loading @@ -111,10 +112,14 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; import com.android.systemui.statusbar.stack.StackScrollState.ViewState; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; public class PhoneStatusBar extends BaseStatusBar implements DemoMode { static final String TAG = "PhoneStatusBar"; Loading Loading @@ -147,6 +152,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; private static final long AUTOHIDE_TIMEOUT_MS = 3000; /** The minimum delay in ms between reports of notification visibility. */ private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500; // fling gesture tuning parameters, scaled to display density private float mSelfExpandVelocityPx; // classic value: 2000px/s private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up") Loading Loading @@ -376,6 +384,82 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mOnFlipRunnable = onFlipRunnable; } /** Keys of notifications currently visible to the user. */ private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>(); private long mLastVisibilityReportUptimeMs; private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD | ViewState.LOCATION_TOP_STACK_PEEKING | ViewState.LOCATION_MAIN_AREA | ViewState.LOCATION_BOTTOM_STACK_PEEKING; private final OnChildLocationsChangedListener mNotificationLocationsChangedListener = new OnChildLocationsChangedListener() { @Override public void onChildLocationsChanged( NotificationStackScrollLayout stackScrollLayout) { if (mHandler.hasCallbacks(mVisibilityReporter)) { // Visibilities will be reported when the existing // callback is executed. return; } // Calculate when we're allowed to run the visibility // reporter. Note that this timestamp might already have // passed. That's OK, the callback will just be executed // ASAP. long nextReportUptimeMs = mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS; mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs); } }; // Tracks notifications currently visible in mNotificationStackScroller and // emits visibility events via NoMan on changes. private final Runnable mVisibilityReporter = new Runnable() { private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>(); private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>(); @Override public void run() { mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis(); // 1. Loop over mNotificationData entries: // A. Keep list of visible notifications. // B. Keep list of previously hidden, now visible notifications. // 2. Compute no-longer visible notifications by removing currently // visible notifications from the set of previously visible // notifications. // 3. Report newly visible and no-longer visible notifications. // 4. Keep currently visible notifications for next report. int N = mNotificationData.size(); for (int i = 0; i < N; i++) { Entry entry = mNotificationData.get(i); String key = entry.notification.getKey(); boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key); boolean currentlyVisible = (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0; if (currentlyVisible) { // Build new set of visible notifications. mTmpCurrentlyVisibleNotifications.add(key); } if (!previouslyVisible && currentlyVisible) { mTmpNewlyVisibleNotifications.add(key); } } ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications; noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications); logNotificationVisibilityChanges( mTmpNewlyVisibleNotifications, noLongerVisibleNotifications); mCurrentlyVisibleNotifications.clear(); mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications); mTmpNewlyVisibleNotifications.clear(); mTmpCurrentlyVisibleNotifications.clear(); } }; @Override public void setZenMode(int mode) { super.setZenMode(mode); Loading Loading @@ -2647,6 +2731,41 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (false) Log.v(TAG, "updateResources"); } // Visibility reporting @Override protected void visibilityChanged(boolean visible) { if (visible) { mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener); } else { // Report all notifications as invisible and turn down the // reporter. if (!mCurrentlyVisibleNotifications.isEmpty()) { logNotificationVisibilityChanges( Collections.<String>emptyList(), mCurrentlyVisibleNotifications); mCurrentlyVisibleNotifications.clear(); } mHandler.removeCallbacks(mVisibilityReporter); mStackScroller.setChildLocationsChangedListener(null); } super.visibilityChanged(visible); } private void logNotificationVisibilityChanges( Collection<String> newlyVisible, Collection<String> noLongerVisible) { if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) { return; } String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]); String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]); try { mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr); } catch (RemoteException e) { // Ignore. } } // // tracing // Loading services/core/java/com/android/server/EventLogTags.logtags +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ option java_package com.android.server 27500 notification_panel_revealed # when the notification panel is hidden 27501 notification_panel_hidden # when notifications are newly displayed on screen, or disappear from screen 27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3) # --------------------------- # Watchdog.java Loading services/core/java/com/android/server/notification/NotificationDelegate.java +2 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,6 @@ public interface NotificationDelegate { void onPanelRevealed(); void onPanelHidden(); boolean allowDisable(int what, IBinder token, String pkg); void onNotificationVisibilityChanged( String[] newlyVisibleKeys, String[] noLongerVisibleKeys); } services/core/java/com/android/server/notification/NotificationManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -1071,6 +1071,16 @@ public class NotificationManagerService extends SystemService { } return true; } @Override public void onNotificationVisibilityChanged( String[] newlyVisibleKeys, String[] noLongerVisibleKeys) { // Using ';' as separator since eventlogs uses ',' to separate // args. EventLogTags.writeNotificationVisibilityChanged( TextUtils.join(";", newlyVisibleKeys), TextUtils.join(";", noLongerVisibleKeys)); } }; private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { Loading Loading
core/java/com/android/internal/statusbar/IStatusBarService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ interface IStatusBarService int uid, int initialPid, String message, int userId); void onClearAllNotifications(int userId); void onNotificationClear(String pkg, String tag, int id, int userId); void onNotificationVisibilityChanged( in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys); void setSystemUiVisibility(int vis, int mask); void setHardKeyboardEnabled(boolean enabled); void toggleRecentApps(); Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +119 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; Loading Loading @@ -111,10 +112,14 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; import com.android.systemui.statusbar.stack.StackScrollState.ViewState; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; public class PhoneStatusBar extends BaseStatusBar implements DemoMode { static final String TAG = "PhoneStatusBar"; Loading Loading @@ -147,6 +152,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; private static final long AUTOHIDE_TIMEOUT_MS = 3000; /** The minimum delay in ms between reports of notification visibility. */ private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500; // fling gesture tuning parameters, scaled to display density private float mSelfExpandVelocityPx; // classic value: 2000px/s private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up") Loading Loading @@ -376,6 +384,82 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mOnFlipRunnable = onFlipRunnable; } /** Keys of notifications currently visible to the user. */ private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>(); private long mLastVisibilityReportUptimeMs; private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD | ViewState.LOCATION_TOP_STACK_PEEKING | ViewState.LOCATION_MAIN_AREA | ViewState.LOCATION_BOTTOM_STACK_PEEKING; private final OnChildLocationsChangedListener mNotificationLocationsChangedListener = new OnChildLocationsChangedListener() { @Override public void onChildLocationsChanged( NotificationStackScrollLayout stackScrollLayout) { if (mHandler.hasCallbacks(mVisibilityReporter)) { // Visibilities will be reported when the existing // callback is executed. return; } // Calculate when we're allowed to run the visibility // reporter. Note that this timestamp might already have // passed. That's OK, the callback will just be executed // ASAP. long nextReportUptimeMs = mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS; mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs); } }; // Tracks notifications currently visible in mNotificationStackScroller and // emits visibility events via NoMan on changes. private final Runnable mVisibilityReporter = new Runnable() { private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>(); private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>(); @Override public void run() { mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis(); // 1. Loop over mNotificationData entries: // A. Keep list of visible notifications. // B. Keep list of previously hidden, now visible notifications. // 2. Compute no-longer visible notifications by removing currently // visible notifications from the set of previously visible // notifications. // 3. Report newly visible and no-longer visible notifications. // 4. Keep currently visible notifications for next report. int N = mNotificationData.size(); for (int i = 0; i < N; i++) { Entry entry = mNotificationData.get(i); String key = entry.notification.getKey(); boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key); boolean currentlyVisible = (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0; if (currentlyVisible) { // Build new set of visible notifications. mTmpCurrentlyVisibleNotifications.add(key); } if (!previouslyVisible && currentlyVisible) { mTmpNewlyVisibleNotifications.add(key); } } ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications; noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications); logNotificationVisibilityChanges( mTmpNewlyVisibleNotifications, noLongerVisibleNotifications); mCurrentlyVisibleNotifications.clear(); mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications); mTmpNewlyVisibleNotifications.clear(); mTmpCurrentlyVisibleNotifications.clear(); } }; @Override public void setZenMode(int mode) { super.setZenMode(mode); Loading Loading @@ -2647,6 +2731,41 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (false) Log.v(TAG, "updateResources"); } // Visibility reporting @Override protected void visibilityChanged(boolean visible) { if (visible) { mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener); } else { // Report all notifications as invisible and turn down the // reporter. if (!mCurrentlyVisibleNotifications.isEmpty()) { logNotificationVisibilityChanges( Collections.<String>emptyList(), mCurrentlyVisibleNotifications); mCurrentlyVisibleNotifications.clear(); } mHandler.removeCallbacks(mVisibilityReporter); mStackScroller.setChildLocationsChangedListener(null); } super.visibilityChanged(visible); } private void logNotificationVisibilityChanges( Collection<String> newlyVisible, Collection<String> noLongerVisible) { if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) { return; } String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]); String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]); try { mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr); } catch (RemoteException e) { // Ignore. } } // // tracing // Loading
services/core/java/com/android/server/EventLogTags.logtags +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ option java_package com.android.server 27500 notification_panel_revealed # when the notification panel is hidden 27501 notification_panel_hidden # when notifications are newly displayed on screen, or disappear from screen 27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3) # --------------------------- # Watchdog.java Loading
services/core/java/com/android/server/notification/NotificationDelegate.java +2 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,6 @@ public interface NotificationDelegate { void onPanelRevealed(); void onPanelHidden(); boolean allowDisable(int what, IBinder token, String pkg); void onNotificationVisibilityChanged( String[] newlyVisibleKeys, String[] noLongerVisibleKeys); }
services/core/java/com/android/server/notification/NotificationManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -1071,6 +1071,16 @@ public class NotificationManagerService extends SystemService { } return true; } @Override public void onNotificationVisibilityChanged( String[] newlyVisibleKeys, String[] noLongerVisibleKeys) { // Using ';' as separator since eventlogs uses ',' to separate // args. EventLogTags.writeNotificationVisibilityChanged( TextUtils.join(";", newlyVisibleKeys), TextUtils.join(";", noLongerVisibleKeys)); } }; private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { Loading