Merge "Write eventlog entries for notification visibility"

This commit is contained in:
Christoph Studer
2014-04-16 15:49:54 +00:00
committed by Android (Google) Code Review
6 changed files with 148 additions and 0 deletions

View File

@@ -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();

View File

@@ -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
//

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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();