Merge "add rank to notification visibility log" into mnc-dev
This commit is contained in:
@@ -19,6 +19,7 @@ package com.android.internal.statusbar;
|
||||
import com.android.internal.statusbar.IStatusBar;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.internal.statusbar.StatusBarIconList;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
/** @hide */
|
||||
@@ -53,8 +54,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 onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
|
||||
in NotificationVisibility[] noLongerVisibleKeys);
|
||||
void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
|
||||
void setSystemUiVisibility(int vis, int mask, String cause);
|
||||
void setWindowState(int window, int state);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 com.android.internal.statusbar;
|
||||
|
||||
parcelable NotificationVisibility;
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 com.android.internal.statusbar;
|
||||
|
||||
import android.os.Message;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
|
||||
public class NotificationVisibility implements Parcelable {
|
||||
private static final String TAG = "NoViz";
|
||||
private static final int MAX_POOL_SIZE = 25;
|
||||
private static ArrayDeque<NotificationVisibility> sPool = new ArrayDeque<>(MAX_POOL_SIZE);
|
||||
private static int sNexrId = 0;
|
||||
|
||||
public String key;
|
||||
public int rank;
|
||||
public boolean visible = true;
|
||||
/*package*/ int id;
|
||||
|
||||
private NotificationVisibility() {
|
||||
id = sNexrId++;
|
||||
}
|
||||
|
||||
private NotificationVisibility(String key, int rank, boolean visibile) {
|
||||
this();
|
||||
this.key = key;
|
||||
this.rank = rank;
|
||||
this.visible = visibile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NotificationVisibility(id=" + id
|
||||
+ "key=" + key
|
||||
+ " rank=" + rank
|
||||
+ (visible?" visible":"")
|
||||
+ " )";
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotificationVisibility clone() {
|
||||
return obtain(this.key, this.rank, this.visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// allow lookups by key, which _should_ never be null.
|
||||
return key == null ? 0 : key.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
// allow lookups by key, which _should_ never be null.
|
||||
if (that instanceof NotificationVisibility) {
|
||||
NotificationVisibility thatViz = (NotificationVisibility) that;
|
||||
return (key == null && thatViz.key == null) || key.equals(thatViz.key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(this.key);
|
||||
out.writeInt(this.rank);
|
||||
out.writeInt(this.visible ? 1 : 0);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
this.key = in.readString();
|
||||
this.rank = in.readInt();
|
||||
this.visible = in.readInt() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new NotificationVisibility instance from the global pool. Allows us to
|
||||
* avoid allocating new objects in many cases.
|
||||
*/
|
||||
public static NotificationVisibility obtain(String key, int rank, boolean visible) {
|
||||
NotificationVisibility vo = obtain();
|
||||
vo.key = key;
|
||||
vo.rank = rank;
|
||||
vo.visible = visible;
|
||||
return vo;
|
||||
}
|
||||
|
||||
private static NotificationVisibility obtain(Parcel in) {
|
||||
NotificationVisibility vo = obtain();
|
||||
vo.readFromParcel(in);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private static NotificationVisibility obtain() {
|
||||
synchronized (sPool) {
|
||||
if (!sPool.isEmpty()) {
|
||||
return sPool.poll();
|
||||
}
|
||||
}
|
||||
return new NotificationVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a NotificationVisibility instance to the global pool.
|
||||
* <p>
|
||||
* You MUST NOT touch the NotificationVisibility after calling this function because it has
|
||||
* effectively been freed.
|
||||
* </p>
|
||||
*/
|
||||
public void recycle() {
|
||||
if (key == null) {
|
||||
// do nothing on multiple recycles
|
||||
return;
|
||||
}
|
||||
key = null;
|
||||
if (sPool.size() < MAX_POOL_SIZE) {
|
||||
synchronized (sPool) {
|
||||
sPool.offer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable.Creator that instantiates NotificationVisibility objects
|
||||
*/
|
||||
public static final Parcelable.Creator<NotificationVisibility> CREATOR
|
||||
= new Parcelable.Creator<NotificationVisibility>()
|
||||
{
|
||||
public NotificationVisibility createFromParcel(Parcel parcel)
|
||||
{
|
||||
return obtain(parcel);
|
||||
}
|
||||
|
||||
public NotificationVisibility[] newArray(int size)
|
||||
{
|
||||
return new NotificationVisibility[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.keyguard.KeyguardHostView.OnDismissAction;
|
||||
import com.android.keyguard.ViewMediatorCallback;
|
||||
@@ -457,7 +458,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
private int mDisabledUnmodified2;
|
||||
|
||||
/** Keys of notifications currently visible to the user. */
|
||||
private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
|
||||
private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications =
|
||||
new ArraySet<>();
|
||||
private long mLastVisibilityReportUptimeMs;
|
||||
|
||||
private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
|
||||
@@ -498,12 +500,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
// 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>();
|
||||
private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications =
|
||||
new ArraySet<>();
|
||||
private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications =
|
||||
new ArraySet<>();
|
||||
private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications =
|
||||
new ArraySet<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
|
||||
final String mediaKey = getCurrentMediaNotificationKey();
|
||||
|
||||
// 1. Loop over mNotificationData entries:
|
||||
// A. Keep list of visible notifications.
|
||||
@@ -518,31 +525,45 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
for (int i = 0; i < N; i++) {
|
||||
Entry entry = activeNotifications.get(i);
|
||||
String key = entry.notification.getKey();
|
||||
boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key);
|
||||
boolean currentlyVisible =
|
||||
boolean isVisible =
|
||||
(mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
|
||||
if (currentlyVisible) {
|
||||
NotificationVisibility visObj = NotificationVisibility.obtain(key, i, isVisible);
|
||||
boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj);
|
||||
if (isVisible) {
|
||||
// Build new set of visible notifications.
|
||||
mTmpCurrentlyVisibleNotifications.add(key);
|
||||
}
|
||||
if (!previouslyVisible && currentlyVisible) {
|
||||
mTmpNewlyVisibleNotifications.add(key);
|
||||
mTmpCurrentlyVisibleNotifications.add(visObj);
|
||||
if (!previouslyVisible) {
|
||||
mTmpNewlyVisibleNotifications.add(visObj);
|
||||
}
|
||||
} else {
|
||||
// release object
|
||||
visObj.recycle();
|
||||
}
|
||||
}
|
||||
ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications;
|
||||
noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
|
||||
mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications);
|
||||
mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
|
||||
|
||||
logNotificationVisibilityChanges(
|
||||
mTmpNewlyVisibleNotifications, noLongerVisibleNotifications);
|
||||
mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications);
|
||||
|
||||
mCurrentlyVisibleNotifications.clear();
|
||||
recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
|
||||
mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
|
||||
|
||||
mTmpNewlyVisibleNotifications.clear();
|
||||
recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications);
|
||||
mTmpCurrentlyVisibleNotifications.clear();
|
||||
mTmpNewlyVisibleNotifications.clear();
|
||||
mTmpNoLongerVisibleNotifications.clear();
|
||||
}
|
||||
};
|
||||
|
||||
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
|
||||
final int N = array.size();
|
||||
for (int i = 0 ; i < N; i++) {
|
||||
array.valueAt(i).recycle();
|
||||
}
|
||||
array.clear();
|
||||
}
|
||||
|
||||
private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -2987,9 +3008,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
// Report all notifications as invisible and turn down the
|
||||
// reporter.
|
||||
if (!mCurrentlyVisibleNotifications.isEmpty()) {
|
||||
logNotificationVisibilityChanges(
|
||||
Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
|
||||
mCurrentlyVisibleNotifications.clear();
|
||||
logNotificationVisibilityChanges(Collections.<NotificationVisibility>emptyList(),
|
||||
mCurrentlyVisibleNotifications);
|
||||
recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
|
||||
}
|
||||
mHandler.removeCallbacks(mVisibilityReporter);
|
||||
mStackScroller.setChildLocationsChangedListener(null);
|
||||
@@ -3007,18 +3028,27 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
|
||||
private void logNotificationVisibilityChanges(
|
||||
Collection<String> newlyVisible, Collection<String> noLongerVisible) {
|
||||
Collection<NotificationVisibility> newlyVisible,
|
||||
Collection<NotificationVisibility> noLongerVisible) {
|
||||
if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
|
||||
String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
|
||||
NotificationVisibility[] newlyVisibleAr =
|
||||
newlyVisible.toArray(new NotificationVisibility[newlyVisible.size()]);
|
||||
NotificationVisibility[] noLongerVisibleAr =
|
||||
noLongerVisible.toArray(new NotificationVisibility[noLongerVisible.size()]);
|
||||
try {
|
||||
mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore.
|
||||
}
|
||||
setNotificationsShown(newlyVisibleAr);
|
||||
|
||||
final int N = newlyVisible.size();
|
||||
String[] newlyVisibleKeyAr = new String[N];
|
||||
for (int i = 0; i < N; i++) {
|
||||
newlyVisibleKeyAr[i] = newlyVisibleAr[i].key;
|
||||
}
|
||||
setNotificationsShown(newlyVisibleKeyAr);
|
||||
}
|
||||
|
||||
// State logging
|
||||
|
||||
@@ -74,7 +74,7 @@ option java_package com.android.server
|
||||
# when a notification has been canceled
|
||||
27530 notification_canceled (key|3),(reason|1),(lifespan|1),(freshness|1),(exposure|1)
|
||||
# replaces 27510 with a row per notification
|
||||
27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1)
|
||||
27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1),(exposure|1),(rank|1)
|
||||
# a notification emited noise, vibration, or light
|
||||
27532 notification_alert (key|3),(buzz|1),(beep|1),(blink|1)
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.notification;
|
||||
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
|
||||
public interface NotificationDelegate {
|
||||
void onSetDisabled(int status);
|
||||
void onClearAll(int callingUid, int callingPid, int userId);
|
||||
@@ -30,6 +32,7 @@ public interface NotificationDelegate {
|
||||
void onPanelHidden();
|
||||
void clearEffects();
|
||||
void onNotificationVisibilityChanged(
|
||||
String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
|
||||
NotificationVisibility[] newlyVisibleKeys,
|
||||
NotificationVisibility[] noLongerVisibleKeys);
|
||||
void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -622,22 +623,24 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationVisibilityChanged(
|
||||
String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
|
||||
public void onNotificationVisibilityChanged(NotificationVisibility[] newlyVisibleKeys,
|
||||
NotificationVisibility[] noLongerVisibleKeys) {
|
||||
synchronized (mNotificationList) {
|
||||
for (String key : newlyVisibleKeys) {
|
||||
NotificationRecord r = mNotificationsByKey.get(key);
|
||||
for (NotificationVisibility nv : newlyVisibleKeys) {
|
||||
NotificationRecord r = mNotificationsByKey.get(nv.key);
|
||||
if (r == null) continue;
|
||||
r.setVisibility(true);
|
||||
r.setVisibility(true, nv.rank);
|
||||
nv.recycle();
|
||||
}
|
||||
// Note that we might receive this event after notifications
|
||||
// have already left the system, e.g. after dismissing from the
|
||||
// shade. Hence not finding notifications in
|
||||
// mNotificationsByKey is not an exceptional condition.
|
||||
for (String key : noLongerVisibleKeys) {
|
||||
NotificationRecord r = mNotificationsByKey.get(key);
|
||||
for (NotificationVisibility nv : noLongerVisibleKeys) {
|
||||
NotificationRecord r = mNotificationsByKey.get(nv.key);
|
||||
if (r == null) continue;
|
||||
r.setVisibility(false);
|
||||
r.setVisibility(false, nv.rank);
|
||||
nv.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,13 +314,15 @@ public final class NotificationRecord {
|
||||
/**
|
||||
* Set the visibility of the notification.
|
||||
*/
|
||||
public void setVisibility(boolean visible) {
|
||||
public void setVisibility(boolean visible, int rank) {
|
||||
final long now = System.currentTimeMillis();
|
||||
mVisibleSinceMs = visible ? now : mVisibleSinceMs;
|
||||
stats.onVisibilityChanged(visible);
|
||||
EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
|
||||
(int) (now - mCreationTimeMs),
|
||||
(int) (now - mUpdateTimeMs));
|
||||
(int) (now - mUpdateTimeMs),
|
||||
0, // exposure time
|
||||
rank);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBar;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.internal.statusbar.StatusBarIconList;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -660,7 +661,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
|
||||
|
||||
@Override
|
||||
public void onNotificationVisibilityChanged(
|
||||
String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
|
||||
NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys)
|
||||
throws RemoteException {
|
||||
enforceStatusBarService();
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user