Merge "Write eventlog entries for notification visibility"
This commit is contained in:
committed by
Android (Google) Code Review
commit
97096fd0e6
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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";
|
||||
@@ -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")
|
||||
@@ -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);
|
||||
@@ -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
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -587,6 +587,19 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationVisibilityChanged(
|
||||
String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
|
||||
enforceStatusBarService();
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mNotificationDelegate.onNotificationVisibilityChanged(
|
||||
newlyVisibleKeys, noLongerVisibleKeys);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClearAllNotifications(int userId) {
|
||||
enforceStatusBarService();
|
||||
|
||||
Reference in New Issue
Block a user