Merge "Statsd UiEvent logging for notification history." into rvc-dev

This commit is contained in:
Will Brockman
2020-06-03 17:55:47 +00:00
committed by Android (Google) Code Review
4 changed files with 109 additions and 17 deletions

View File

@@ -26,7 +26,6 @@ import android.app.ActivityManager;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Outline; import android.graphics.Outline;
@@ -49,10 +48,12 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
@@ -82,6 +83,48 @@ public class NotificationHistoryActivity extends Activity {
private PackageManager mPm; private PackageManager mPm;
private CountDownLatch mCountdownLatch; private CountDownLatch mCountdownLatch;
private Future mCountdownFuture; private Future mCountdownFuture;
private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
enum NotificationHistoryEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "User turned on notification history")
NOTIFICATION_HISTORY_ON(504),
@UiEvent(doc = "User turned off notification history")
NOTIFICATION_HISTORY_OFF(505),
@UiEvent(doc = "User opened notification history page")
NOTIFICATION_HISTORY_OPEN(506),
@UiEvent(doc = "User closed notification history page")
NOTIFICATION_HISTORY_CLOSE(507),
@UiEvent(doc = "User clicked on a notification history item in recently dismissed section")
NOTIFICATION_HISTORY_RECENT_ITEM_CLICK(508),
@UiEvent(doc = "User clicked on a notification history item in snoozed section")
NOTIFICATION_HISTORY_SNOOZED_ITEM_CLICK(509),
@UiEvent(doc = "User clicked to expand the notification history of a package (app)")
NOTIFICATION_HISTORY_PACKAGE_HISTORY_OPEN(510),
@UiEvent(doc = "User clicked to close the notification history of a package (app)")
NOTIFICATION_HISTORY_PACKAGE_HISTORY_CLOSE(511),
@UiEvent(doc = "User clicked on a notification history item in an expanded by-app section")
NOTIFICATION_HISTORY_OLDER_ITEM_CLICK(512),
@UiEvent(doc = "User dismissed a notification history item in an expanded by-app section")
NOTIFICATION_HISTORY_OLDER_ITEM_DELETE(513);
private int mId;
NotificationHistoryEvent(int id) {
mId = id;
}
@Override
public int getId() {
return mId;
}
}
private HistoryLoader.OnHistoryLoaderListener mOnHistoryLoaderListener = notifications -> { private HistoryLoader.OnHistoryLoaderListener mOnHistoryLoaderListener = notifications -> {
findViewById(R.id.today_list).setVisibility( findViewById(R.id.today_list).setVisibility(
@@ -105,7 +148,8 @@ public class NotificationHistoryActivity extends Activity {
} }
}); });
// for each package, new header and recycler view // for each package, new header and recycler view
for (NotificationHistoryPackage nhp : notifications) { for (int i = 0, notificationsSize = notifications.size(); i < notificationsSize; i++) {
NotificationHistoryPackage nhp = notifications.get(i);
View viewForPackage = LayoutInflater.from(this) View viewForPackage = LayoutInflater.from(this)
.inflate(R.layout.notification_history_app_layout, null); .inflate(R.layout.notification_history_app_layout, null);
@@ -115,6 +159,7 @@ public class NotificationHistoryActivity extends Activity {
expand.setContentDescription(container.getVisibility() == View.VISIBLE expand.setContentDescription(container.getVisibility() == View.VISIBLE
? getString(R.string.condition_expand_hide) ? getString(R.string.condition_expand_hide)
: getString(R.string.condition_expand_show)); : getString(R.string.condition_expand_show));
int finalI = i;
expand.setOnClickListener(v -> { expand.setOnClickListener(v -> {
container.setVisibility(container.getVisibility() == View.VISIBLE container.setVisibility(container.getVisibility() == View.VISIBLE
? View.GONE : View.VISIBLE); ? View.GONE : View.VISIBLE);
@@ -125,6 +170,11 @@ public class NotificationHistoryActivity extends Activity {
? getString(R.string.condition_expand_hide) ? getString(R.string.condition_expand_hide)
: getString(R.string.condition_expand_show)); : getString(R.string.condition_expand_show));
expand.sendAccessibilityEvent(TYPE_VIEW_ACCESSIBILITY_FOCUSED); expand.sendAccessibilityEvent(TYPE_VIEW_ACCESSIBILITY_FOCUSED);
mUiEventLogger.logWithPosition(
(container.getVisibility() == View.VISIBLE)
? NotificationHistoryEvent.NOTIFICATION_HISTORY_PACKAGE_HISTORY_OPEN
: NotificationHistoryEvent.NOTIFICATION_HISTORY_PACKAGE_HISTORY_CLOSE,
nhp.uid, nhp.pkgName, finalI);
}); });
TextView label = viewForPackage.findViewById(R.id.label); TextView label = viewForPackage.findViewById(R.id.label);
@@ -148,7 +198,7 @@ public class NotificationHistoryActivity extends Activity {
if (newCount == 0) { if (newCount == 0) {
viewForPackage.setVisibility(View.GONE); viewForPackage.setVisibility(View.GONE);
} }
})); }, mUiEventLogger));
((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete( ((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete(
new ArrayList<>(nhp.notifications)); new ArrayList<>(nhp.notifications));
@@ -217,6 +267,8 @@ public class NotificationHistoryActivity extends Activity {
} }
}); });
}); });
mUiEventLogger.log(NotificationHistoryEvent.NOTIFICATION_HISTORY_OPEN);
} }
@Override @Override
@@ -226,6 +278,7 @@ public class NotificationHistoryActivity extends Activity {
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Cannot unregister listener", e); Log.e(TAG, "Cannot unregister listener", e);
} }
mUiEventLogger.log(NotificationHistoryEvent.NOTIFICATION_HISTORY_CLOSE);
super.onPause(); super.onPause();
} }
@@ -273,9 +326,21 @@ public class NotificationHistoryActivity extends Activity {
private final SwitchBar.OnSwitchChangeListener mOnSwitchClickListener = private final SwitchBar.OnSwitchChangeListener mOnSwitchClickListener =
(switchView, isChecked) -> { (switchView, isChecked) -> {
Settings.Secure.putInt(getContentResolver(), int oldState = 0;
NOTIFICATION_HISTORY_ENABLED, try {
isChecked ? 1 : 0); oldState = Settings.Secure.getInt(getContentResolver(),
NOTIFICATION_HISTORY_ENABLED);
} catch (Settings.SettingNotFoundException ignored) {
}
final int newState = isChecked ? 1 : 0;
if (oldState != newState) {
Settings.Secure.putInt(getContentResolver(),
NOTIFICATION_HISTORY_ENABLED, newState);
mUiEventLogger.log(isChecked ? NotificationHistoryEvent.NOTIFICATION_HISTORY_ON
: NotificationHistoryEvent.NOTIFICATION_HISTORY_OFF);
Log.d(TAG, "onSwitchChange history to " + isChecked);
}
// Reset UI visibility to ensure it matches real state.
mHistoryOn.setVisibility(View.GONE); mHistoryOn.setVisibility(View.GONE);
if (isChecked) { if (isChecked) {
mHistoryEmpty.setVisibility(View.VISIBLE); mHistoryEmpty.setVisibility(View.VISIBLE);
@@ -308,7 +373,8 @@ public class NotificationHistoryActivity extends Activity {
LinearLayoutManager lm = new LinearLayoutManager(NotificationHistoryActivity.this); LinearLayoutManager lm = new LinearLayoutManager(NotificationHistoryActivity.this);
mSnoozedRv.setLayoutManager(lm); mSnoozedRv.setLayoutManager(lm);
mSnoozedRv.setAdapter( mSnoozedRv.setAdapter(
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm)); new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm,
true, mUiEventLogger));
mSnoozedRv.setNestedScrollingEnabled(false); mSnoozedRv.setNestedScrollingEnabled(false);
if (snoozed == null || snoozed.length == 0) { if (snoozed == null || snoozed.length == 0) {
@@ -323,7 +389,8 @@ public class NotificationHistoryActivity extends Activity {
new LinearLayoutManager(NotificationHistoryActivity.this); new LinearLayoutManager(NotificationHistoryActivity.this);
mDismissedRv.setLayoutManager(dismissLm); mDismissedRv.setLayoutManager(dismissLm);
mDismissedRv.setAdapter( mDismissedRv.setAdapter(
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm)); new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm,
false , mUiEventLogger));
mDismissedRv.setNestedScrollingEnabled(false); mDismissedRv.setNestedScrollingEnabled(false);
if (dismissed == null || dismissed.length == 0) { if (dismissed == null || dismissed.length == 0) {

View File

@@ -36,6 +36,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.UiEventLogger;
import com.android.settings.R; import com.android.settings.R;
import java.util.ArrayList; import java.util.ArrayList;
@@ -50,15 +51,17 @@ public class NotificationHistoryAdapter extends
private INotificationManager mNm; private INotificationManager mNm;
private List<HistoricalNotification> mValues; private List<HistoricalNotification> mValues;
private OnItemDeletedListener mListener; private OnItemDeletedListener mListener;
private UiEventLogger mUiEventLogger;
public NotificationHistoryAdapter(INotificationManager nm, public NotificationHistoryAdapter(INotificationManager nm,
NotificationHistoryRecyclerView listView, NotificationHistoryRecyclerView listView,
OnItemDeletedListener listener) { OnItemDeletedListener listener,
UiEventLogger uiEventLogger) {
mValues = new ArrayList<>(); mValues = new ArrayList<>();
setHasStableIds(true); setHasStableIds(true);
listView.setOnItemSwipeDeleteListener(this); listView.setOnItemSwipeDeleteListener(this);
mNm = nm; mNm = nm;
mListener = listener; mListener = listener;
mUiEventLogger = uiEventLogger;
} }
@Override @Override
@@ -76,6 +79,8 @@ public class NotificationHistoryAdapter extends
holder.setSummary(hn.getText()); holder.setSummary(hn.getText());
holder.setPostedTime(hn.getPostedTimeMs()); holder.setPostedTime(hn.getPostedTimeMs());
holder.itemView.setOnClickListener(v -> { holder.itemView.setOnClickListener(v -> {
mUiEventLogger.logWithPosition(NotificationHistoryActivity.NotificationHistoryEvent
.NOTIFICATION_HISTORY_OLDER_ITEM_CLICK, hn.getUid(), hn.getPackage(), position);
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(EXTRA_APP_PACKAGE, hn.getPackage()) .putExtra(EXTRA_APP_PACKAGE, hn.getPackage())
.putExtra(EXTRA_CHANNEL_ID, hn.getChannelId()) .putExtra(EXTRA_CHANNEL_ID, hn.getChannelId())
@@ -136,6 +141,9 @@ public class NotificationHistoryAdapter extends
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Failed to delete item", e); Slog.e(TAG, "Failed to delete item", e);
} }
mUiEventLogger.logWithPosition(NotificationHistoryActivity.NotificationHistoryEvent
.NOTIFICATION_HISTORY_OLDER_ITEM_DELETE, hn.getUid(), hn.getPackage(),
position);
} }
mListener.onItemDeleted(mValues.size()); mListener.onItemDeleted(mValues.size());
notifyItemRemoved(position); notifyItemRemoved(position);

View File

@@ -49,11 +49,11 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.ContrastColorUtil; import com.android.internal.util.ContrastColorUtil;
import com.android.settings.R; import com.android.settings.R;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -70,8 +70,11 @@ public class NotificationSbnAdapter extends
private boolean mInNightMode; private boolean mInNightMode;
private @UserIdInt int mCurrentUser; private @UserIdInt int mCurrentUser;
private List<Integer> mEnabledProfiles = new ArrayList<>(); private List<Integer> mEnabledProfiles = new ArrayList<>();
private boolean mIsSnoozed;
private UiEventLogger mUiEventLogger;
public NotificationSbnAdapter(Context context, PackageManager pm, UserManager um) { public NotificationSbnAdapter(Context context, PackageManager pm, UserManager um,
boolean isSnoozed, UiEventLogger uiEventLogger) {
mContext = context; mContext = context;
mPm = pm; mPm = pm;
mUserBadgeCache = new HashMap<>(); mUserBadgeCache = new HashMap<>();
@@ -89,6 +92,9 @@ public class NotificationSbnAdapter extends
} }
} }
setHasStableIds(true); setHasStableIds(true);
// If true, this is the panel for snoozed notifs, otherwise the one for dismissed notifs.
mIsSnoozed = isSnoozed;
mUiEventLogger = uiEventLogger;
} }
@Override @Override
@@ -116,8 +122,9 @@ public class NotificationSbnAdapter extends
mUserBadgeCache.put(userId, profile); mUserBadgeCache.put(userId, profile);
} }
holder.setProfileBadge(mUserBadgeCache.get(userId)); holder.setProfileBadge(mUserBadgeCache.get(userId));
holder.addOnClick(sbn.getPackageName(), sbn.getUserId(), holder.addOnClick(position, sbn.getPackageName(), sbn.getUid(), sbn.getUserId(),
sbn.getNotification().contentIntent); sbn.getNotification().contentIntent, sbn.getInstanceId(), mIsSnoozed,
mUiEventLogger);
holder.itemView.setOnLongClickListener(v -> { holder.itemView.setOnLongClickListener(v -> {
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(EXTRA_APP_PACKAGE, sbn.getPackageName()) .putExtra(EXTRA_APP_PACKAGE, sbn.getPackageName())

View File

@@ -20,7 +20,6 @@ import android.app.PendingIntent;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Slog; import android.util.Slog;
@@ -34,6 +33,8 @@ import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.settings.R; import com.android.settings.R;
public class NotificationSbnViewHolder extends RecyclerView.ViewHolder { public class NotificationSbnViewHolder extends RecyclerView.ViewHolder {
@@ -91,13 +92,22 @@ public class NotificationSbnViewHolder extends RecyclerView.ViewHolder {
mDivider.setVisibility(visible ? View.VISIBLE : View.GONE); mDivider.setVisibility(visible ? View.VISIBLE : View.GONE);
} }
void addOnClick(String pkg, int userId, PendingIntent pi) { void addOnClick(int position, String pkg, int uid, int userId, PendingIntent pi,
InstanceId instanceId,
boolean isSnoozed, UiEventLogger uiEventLogger) {
Intent appIntent = itemView.getContext().getPackageManager() Intent appIntent = itemView.getContext().getPackageManager()
.getLaunchIntentForPackage(pkg); .getLaunchIntentForPackage(pkg);
boolean isPendingIntentValid = pi != null && PendingIntent.getActivity( boolean isPendingIntentValid = pi != null && PendingIntent.getActivity(
itemView.getContext(), 0, pi.getIntent(), PendingIntent.FLAG_NO_CREATE) != null; itemView.getContext(), 0, pi.getIntent(), PendingIntent.FLAG_NO_CREATE) != null;
if (isPendingIntentValid || appIntent != null) { if (isPendingIntentValid || appIntent != null) {
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
uiEventLogger.logWithInstanceIdAndPosition(
isSnoozed
? NotificationHistoryActivity.NotificationHistoryEvent
.NOTIFICATION_HISTORY_SNOOZED_ITEM_CLICK
: NotificationHistoryActivity.NotificationHistoryEvent
.NOTIFICATION_HISTORY_RECENT_ITEM_CLICK,
uid, pkg, instanceId, position);
if (pi != null) { if (pi != null) {
try { try {
pi.send(); pi.send();