Merge "create a metrics log reader for tests"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e6010d2b2a
@@ -1,6 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging;
|
||||
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
|
||||
@@ -14,16 +30,16 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
*/
|
||||
|
||||
public class LogBuilder {
|
||||
|
||||
private static final String TAG = "LogBuilder";
|
||||
private SparseArray<Object> entries = new SparseArray();
|
||||
|
||||
public LogBuilder(int mainCategory) {
|
||||
setCategory(mainCategory);
|
||||
}
|
||||
|
||||
public LogBuilder setView(View view) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VIEW, view.getId());
|
||||
return this;
|
||||
/* Deserialize from the eventlog */
|
||||
public LogBuilder(Object[] items) {
|
||||
deserialize(items);
|
||||
}
|
||||
|
||||
public LogBuilder setCategory(int category) {
|
||||
@@ -36,16 +52,48 @@ public class LogBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setSubtype(int subtype) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE, subtype);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setTimestamp(long timestamp) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP, timestamp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setPackageName(String packageName) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME, packageName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setCounterName(String name) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setCounterBucket(int bucket) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET, bucket);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setCounterBucket(long bucket) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET, bucket);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder setCounterValue(int value) {
|
||||
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VALUE, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tag From your MetricsEvent enum.
|
||||
* @param value One of Integer, Long, Float, String
|
||||
* @return
|
||||
*/
|
||||
public LogBuilder addTaggedData(int tag, Object value) {
|
||||
if (!(value instanceof Integer ||
|
||||
value instanceof String ||
|
||||
value instanceof Long ||
|
||||
value instanceof Float)) {
|
||||
if (isValidValue(value)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Value must be loggable type - int, long, float, String");
|
||||
}
|
||||
@@ -53,6 +101,94 @@ public class LogBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isValidValue(Object value) {
|
||||
return !(value instanceof Integer ||
|
||||
value instanceof String ||
|
||||
value instanceof Long ||
|
||||
value instanceof Float);
|
||||
}
|
||||
|
||||
public Object getTaggedData(int tag) {
|
||||
return entries.get(tag);
|
||||
}
|
||||
|
||||
public int getCategory() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY);
|
||||
if (obj instanceof Integer) {
|
||||
return (Integer) obj;
|
||||
} else {
|
||||
return MetricsEvent.VIEW_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE);
|
||||
if (obj instanceof Integer) {
|
||||
return (Integer) obj;
|
||||
} else {
|
||||
return MetricsEvent.TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public int getSubtype() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE);
|
||||
if (obj instanceof Integer) {
|
||||
return (Integer) obj;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP);
|
||||
if (obj instanceof Long) {
|
||||
return (Long) obj;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME);
|
||||
if (obj instanceof String) {
|
||||
return (String) obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getCounterName() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME);
|
||||
if (obj instanceof String) {
|
||||
return (String) obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public long getCounterBucket() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET);
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).longValue();
|
||||
} else {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLongCounterBucket() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET);
|
||||
return obj instanceof Long;
|
||||
}
|
||||
|
||||
public int getCounterValue() {
|
||||
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_VALUE);
|
||||
if (obj instanceof Integer) {
|
||||
return (Integer) obj;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble logs into structure suitable for EventLog.
|
||||
*/
|
||||
@@ -64,5 +200,17 @@ public class LogBuilder {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
public void deserialize(Object[] items) {
|
||||
int i = 0;
|
||||
while(i < items.length) {
|
||||
Object key = items[i++];
|
||||
Object value = i < items.length ? items[i++] : null;
|
||||
if (key instanceof Integer) {
|
||||
entries.put((Integer) key, value);
|
||||
} else {
|
||||
Log.i(TAG, "Invalid key " + key.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,10 @@ package com.android.internal.logging;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.EventLog;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Log all the things.
|
||||
*
|
||||
@@ -38,6 +36,10 @@ public class MetricsLogger {
|
||||
throw new IllegalArgumentException("Must define metric category");
|
||||
}
|
||||
EventLogTags.writeSysuiViewVisibility(category, 100);
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_OPEN)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
public static void hidden(Context context, int category) throws IllegalArgumentException {
|
||||
@@ -45,6 +47,10 @@ public class MetricsLogger {
|
||||
throw new IllegalArgumentException("Must define metric category");
|
||||
}
|
||||
EventLogTags.writeSysuiViewVisibility(category, 0);
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_CLOSE)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
public static void visibility(Context context, int category, boolean visibile)
|
||||
@@ -62,21 +68,38 @@ public class MetricsLogger {
|
||||
}
|
||||
|
||||
public static void action(Context context, int category) {
|
||||
action(context, category, "");
|
||||
EventLogTags.writeSysuiAction(category, "");
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
public static void action(Context context, int category, int value) {
|
||||
action(context, category, Integer.toString(value));
|
||||
EventLogTags.writeSysuiAction(category, Integer.toString(value));
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(value)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
public static void action(Context context, int category, boolean value) {
|
||||
action(context, category, Boolean.toString(value));
|
||||
EventLogTags.writeSysuiAction(category, Boolean.toString(value));
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(value ? 1 : 0)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
public static void action(LogBuilder content) {
|
||||
//EventLog.writeEvent(524292, content.serialize());
|
||||
// Below would be the *right* way to do this, using the generated
|
||||
// EventLogTags method, but that doesn't work.
|
||||
if (content.getType() == MetricsEvent.TYPE_UNKNOWN) {
|
||||
content.setType(MetricsEvent.TYPE_ACTION);
|
||||
}
|
||||
EventLogTags.writeSysuiMultiAction(content.serialize());
|
||||
}
|
||||
|
||||
@@ -86,15 +109,30 @@ public class MetricsLogger {
|
||||
throw new IllegalArgumentException("Must define metric category");
|
||||
}
|
||||
EventLogTags.writeSysuiAction(category, pkg);
|
||||
EventLogTags.writeSysuiMultiAction(new LogBuilder(category)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.setPackageName(pkg)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
/** Add an integer value to the monotonically increasing counter with the given name. */
|
||||
public static void count(Context context, String name, int value) {
|
||||
EventLogTags.writeSysuiCount(name, value);
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
|
||||
.setCounterName(name)
|
||||
.setCounterValue(value)
|
||||
.serialize());
|
||||
}
|
||||
|
||||
/** Increment the bucket with the integer label on the histogram with the given name. */
|
||||
public static void histogram(Context context, String name, int bucket) {
|
||||
EventLogTags.writeSysuiHistogram(name, bucket);
|
||||
EventLogTags.writeSysuiMultiAction(
|
||||
new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
|
||||
.setCounterName(name)
|
||||
.setCounterBucket(bucket)
|
||||
.setCounterValue(1)
|
||||
.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
64
core/java/com/android/internal/logging/MetricsReader.java
Normal file
64
core/java/com/android/internal/logging/MetricsReader.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging;
|
||||
|
||||
import com.android.internal.logging.legacy.LegacyConversionLogger;
|
||||
import com.android.internal.logging.legacy.EventLogCollector;
|
||||
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* Read platform logs.
|
||||
*/
|
||||
public class MetricsReader {
|
||||
private EventLogCollector mReader;
|
||||
private Queue<LogBuilder> mEventQueue;
|
||||
private long mLastEventMs;
|
||||
private long mCheckpointMs;
|
||||
|
||||
/** Open a new session and start reading logs.
|
||||
*
|
||||
* Starts reading from the oldest log not already read by this reader object.
|
||||
* On first invocation starts from the oldest available log ion the system.
|
||||
*/
|
||||
public void read(long startMs) {
|
||||
EventLogCollector reader = EventLogCollector.getInstance();
|
||||
LegacyConversionLogger logger = new LegacyConversionLogger();
|
||||
mLastEventMs = reader.collect(logger, startMs);
|
||||
mEventQueue = logger.getEvents();
|
||||
}
|
||||
|
||||
public void checkpoint() {
|
||||
read(0L);
|
||||
mCheckpointMs = mLastEventMs;
|
||||
mEventQueue = null;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
read(mCheckpointMs);
|
||||
}
|
||||
|
||||
/* Does the current log session have another entry? */
|
||||
public boolean hasNext() {
|
||||
return mEventQueue == null ? false : !mEventQueue.isEmpty();
|
||||
}
|
||||
|
||||
/* Next entry in the current log session. */
|
||||
public LogBuilder next() {
|
||||
return mEventQueue == null ? null : mEventQueue.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Parse the Android counter event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class CounterParser extends TagParser {
|
||||
private static final String TAG = "CounterParser";
|
||||
private static final int EVENTLOG_TAG = 524290;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 2) {
|
||||
try {
|
||||
String name = ((String) operands[0]);
|
||||
int value = (Integer) operands[1];
|
||||
logCount(logger, name, value);
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.d(TAG, "unexpected operand type", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.d(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
|
||||
protected void logCount(TronLogger logger, String name, int value) {
|
||||
logger.incrementBy(TronCounters.TRON_AOSP_PREFIX + name, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Scan the event log for interaction metrics events.
|
||||
* @hide
|
||||
*/
|
||||
public class EventLogCollector {
|
||||
private static final String TAG = "EventLogCollector";
|
||||
|
||||
// TODO replace this with GoogleLogTags.TRON_HEARTBEAT
|
||||
@VisibleForTesting
|
||||
static final int TRON_HEARTBEAT = 208000;
|
||||
|
||||
private static EventLogCollector sInstance;
|
||||
|
||||
private final ArrayMap<Integer, TagParser> mTagParsers;
|
||||
private int[] mInterestingTags;
|
||||
|
||||
private LogReader mLogReader;
|
||||
|
||||
private EventLogCollector() {
|
||||
mTagParsers = new ArrayMap<>();
|
||||
addParser(new SysuiViewVisibilityParser());
|
||||
addParser(new SysuiActionParser());
|
||||
addParser(new SysuiQueryParser());
|
||||
addParser(new NotificationPanelRevealedParser());
|
||||
addParser(new NotificationPanelHiddenParser());
|
||||
addParser(new NotificationClickedParser());
|
||||
addParser(new NotificationActionClickedParser());
|
||||
addParser(new NotificationCanceledParser());
|
||||
addParser(new NotificationVisibilityParser());
|
||||
addParser(new NotificationAlertParser());
|
||||
addParser(new NotificationExpansionParser());
|
||||
addParser(new CounterParser());
|
||||
addParser(new HistogramParser());
|
||||
addParser(new LockscreenGestureParser());
|
||||
addParser(new StatusBarStateParser());
|
||||
addParser(new PowerScreenStateParser());
|
||||
addParser(new SysuiMultiActionParser());
|
||||
|
||||
mLogReader = new LogReader();
|
||||
}
|
||||
|
||||
public static EventLogCollector getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new EventLogCollector();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setLogReader(LogReader logReader) {
|
||||
mLogReader = logReader;
|
||||
}
|
||||
|
||||
private int[] getInterestingTags() {
|
||||
if (mInterestingTags == null) {
|
||||
mInterestingTags = new int[mTagParsers.size()];
|
||||
for (int i = 0; i < mTagParsers.size(); i++) {
|
||||
mInterestingTags[i] = mTagParsers.valueAt(i).getTag();
|
||||
}
|
||||
}
|
||||
return mInterestingTags;
|
||||
}
|
||||
|
||||
// I would customize ArrayMap to add put(TagParser), but ArrayMap is final.
|
||||
@VisibleForTesting
|
||||
void addParser(TagParser parser) {
|
||||
mTagParsers.put(parser.getTag(), parser);
|
||||
mInterestingTags = null;
|
||||
}
|
||||
|
||||
public void collect(LegacyConversionLogger logger) {
|
||||
collect(logger, 0L);
|
||||
}
|
||||
|
||||
public long collect(TronLogger logger, long lastSeenEventMs) {
|
||||
long lastEventMs = 0L;
|
||||
final boolean debug = Util.debug();
|
||||
|
||||
if (debug) {
|
||||
Log.d(TAG, "Eventlog Collection");
|
||||
}
|
||||
ArrayList<Event> events = new ArrayList<>();
|
||||
try {
|
||||
mLogReader.readEvents(getInterestingTags(), events);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (debug) {
|
||||
Log.d(TAG, "read this many events: " + events.size());
|
||||
}
|
||||
|
||||
for (Event event : events) {
|
||||
final long millis = event.getTimeNanos() / 1000000;
|
||||
if (millis > lastSeenEventMs) {
|
||||
final int tag = event.getTag();
|
||||
TagParser parser = mTagParsers.get(tag);
|
||||
if (parser == null) {
|
||||
if (debug) {
|
||||
Log.d(TAG, "unknown tag: " + tag);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (debug) {
|
||||
Log.d(TAG, "parsing tag: " + tag);
|
||||
}
|
||||
parser.parseEvent(logger, event);
|
||||
lastEventMs = Math.max(lastEventMs, millis);
|
||||
} else {
|
||||
if (debug) {
|
||||
Log.d(TAG, "old event: " + millis + " < " + lastSeenEventMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return lastEventMs;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class Event {
|
||||
long mTimeNanos;
|
||||
int mTag;
|
||||
Object mData;
|
||||
|
||||
Event(long timeNanos, int tag, Object data) {
|
||||
super();
|
||||
mTimeNanos = timeNanos;
|
||||
mTag = tag;
|
||||
mData = data;
|
||||
}
|
||||
|
||||
Event(EventLog.Event event) {
|
||||
mTimeNanos = event.getTimeNanos();
|
||||
mTag = event.getTag();
|
||||
mData = event.getData();
|
||||
}
|
||||
|
||||
public long getTimeNanos() {
|
||||
return mTimeNanos;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return mData;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class LogReader {
|
||||
public void readEvents(int[] tags, Collection<Event> events) throws IOException {
|
||||
// Testing in Android: the Static Final Class Strikes Back!
|
||||
ArrayList<EventLog.Event> nativeEvents = new ArrayList<>();
|
||||
EventLog.readEvents(tags, nativeEvents);
|
||||
for (EventLog.Event nativeEvent : nativeEvents) {
|
||||
Event event = new Event(nativeEvent);
|
||||
events.add(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
/**
|
||||
* Parse the Android histogram event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class HistogramParser extends CounterParser {
|
||||
private static final String TAG = "HistogramParser";
|
||||
private static final int EVENTLOG_TAG = 524291;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logCount(TronLogger logger, String name, int value) {
|
||||
logger.incrementIntHistogram("tron_varz_" + name, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/** @hide */
|
||||
public class LegacyConversionLogger implements TronLogger {
|
||||
public static final String VIEW_KEY = "view";
|
||||
public static final String TYPE_KEY = "type";
|
||||
public static final String EVENT_KEY = "data";
|
||||
|
||||
public static final int TYPE_COUNTER = 1;
|
||||
public static final int TYPE_HISTOGRAM = 2;
|
||||
public static final int TYPE_EVENT = 3;
|
||||
|
||||
private final Queue<LogBuilder> mQueue;
|
||||
private HashMap<String, Boolean> mConfig;
|
||||
|
||||
public LegacyConversionLogger() {
|
||||
mQueue = new LinkedList<>();
|
||||
}
|
||||
|
||||
public Queue<LogBuilder> getEvents() {
|
||||
return mQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(String counterName) {
|
||||
LogBuilder b = new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
|
||||
.setCounterName(counterName)
|
||||
.setCounterValue(1);
|
||||
mQueue.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementBy(String counterName, int value) {
|
||||
LogBuilder b = new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
|
||||
.setCounterName(counterName)
|
||||
.setCounterValue(value);
|
||||
mQueue.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementIntHistogram(String counterName, int bucket) {
|
||||
LogBuilder b = new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
|
||||
.setCounterName(counterName)
|
||||
.setCounterBucket(bucket)
|
||||
.setCounterValue(1);
|
||||
mQueue.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementLongHistogram(String counterName, long bucket) {
|
||||
LogBuilder b = new LogBuilder(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
|
||||
.setCounterName(counterName)
|
||||
.setCounterBucket(bucket)
|
||||
.setCounterValue(1);
|
||||
mQueue.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogBuilder obtain() {
|
||||
return new LogBuilder(MetricsEvent.VIEW_UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose(LogBuilder proto) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEvent(LogBuilder proto) {
|
||||
mQueue.add(proto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getConfig(String configName) {
|
||||
if (mConfig != null && mConfig.containsKey(configName)) {
|
||||
return mConfig.get(configName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(String configName, boolean newValue) {
|
||||
if (mConfig == null) {
|
||||
mConfig = new HashMap<>();
|
||||
}
|
||||
mConfig.put(configName, newValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android lockscreen gesture logs.
|
||||
* @hide
|
||||
*/
|
||||
public class LockscreenGestureParser extends TagParser {
|
||||
private static final String TAG = "LockscreenGestureParser";
|
||||
private static final int EVENTLOG_TAG = 36021;
|
||||
|
||||
// source of truth is com.android.systemui.EventLogConstants
|
||||
public static final int[] GESTURE_TYPE_MAP = {
|
||||
MetricsEvent.VIEW_UNKNOWN, // there is no type 0
|
||||
MetricsEvent.ACTION_LS_UNLOCK, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK = 1
|
||||
MetricsEvent.ACTION_LS_SHADE, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE = 2
|
||||
MetricsEvent.ACTION_LS_HINT, // SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT = 3
|
||||
MetricsEvent.ACTION_LS_CAMERA, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA = 4
|
||||
MetricsEvent.ACTION_LS_DIALER, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER = 5
|
||||
MetricsEvent.ACTION_LS_LOCK, // SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6
|
||||
MetricsEvent.ACTION_LS_NOTE, // SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7
|
||||
MetricsEvent.ACTION_LS_QS, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS = 8
|
||||
MetricsEvent.ACTION_SHADE_QS_PULL, // SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS = 9
|
||||
MetricsEvent.ACTION_SHADE_QS_TAP // SYSUI_TAP_TO_OPEN_QS = 10
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 1) {
|
||||
try {
|
||||
int type = ((Integer) operands[0]).intValue();
|
||||
// ignore gesture length in operands[1]
|
||||
// ignore gesture velocity in operands[2]
|
||||
|
||||
int category = MetricsEvent.VIEW_UNKNOWN;
|
||||
if (type < GESTURE_TYPE_MAP.length) {
|
||||
category = GESTURE_TYPE_MAP[type];
|
||||
}
|
||||
if (category != MetricsEvent.VIEW_UNKNOWN) {
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(category);
|
||||
proto.setType(MetricsEvent.TYPE_ACTION);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
logger.addEvent(proto);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification action button interaction event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationActionClickedParser extends TagParser {
|
||||
private static final String TAG = "NotificationAction";
|
||||
private static final int EVENTLOG_TAG = 27521;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationActionClickedParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 1) {
|
||||
try {
|
||||
if (mKey.parse((String) operands[0])) {
|
||||
int index = (Integer) operands[1];
|
||||
parseTimes(operands, 2);
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION);
|
||||
proto.setType(MetricsEvent.TYPE_ACTION);
|
||||
proto.setSubtype(index);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
} else if (debug) {
|
||||
Log.e(TAG, "unable to parse key.");
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the new Android notification alert event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationAlertParser extends TagParser {
|
||||
private static final String TAG = "NotificationAlertParser";
|
||||
private static final int EVENTLOG_TAG = 27532;
|
||||
|
||||
@VisibleForTesting
|
||||
static final int BUZZ = 0x00000001;
|
||||
@VisibleForTesting
|
||||
static final int BEEP = 0x00000002;
|
||||
@VisibleForTesting
|
||||
static final int BLINK = 0x00000004;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationAlertParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 3) {
|
||||
try {
|
||||
final String keyString = (String) operands[0];
|
||||
final boolean buzz = ((Integer) operands[1]) == 1;
|
||||
final boolean beep = ((Integer) operands[2]) == 1;
|
||||
final boolean blink = ((Integer) operands[3]) == 1;
|
||||
|
||||
if (mKey.parse(keyString)) {
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ALERT);
|
||||
proto.setType(MetricsEvent.TYPE_OPEN);
|
||||
proto.setSubtype((buzz ? BUZZ : 0) | (beep ? BEEP : 0) | (blink ? BLINK : 0));
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
} else {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unable to parse key: " + keyString);
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification cancellation event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationCanceledParser extends TagParser {
|
||||
private static final String TAG = "NotificationCanceled";
|
||||
private static final int EVENTLOG_TAG = 27530;
|
||||
|
||||
// from com.android.server.notification.NotificationManagerService
|
||||
static final int REASON_DELEGATE_CLICK = 1;
|
||||
static final int REASON_DELEGATE_CANCEL = 2;
|
||||
static final int REASON_DELEGATE_CANCEL_ALL = 3;
|
||||
static final int REASON_PACKAGE_BANNED = 7;
|
||||
static final int REASON_LISTENER_CANCEL = 10;
|
||||
static final int REASON_LISTENER_CANCEL_ALL = 11;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationCanceledParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 1) {
|
||||
try {
|
||||
final String keyString = (String) operands[0];
|
||||
final int reason = (Integer) operands[1];
|
||||
parseTimes(operands, 2);
|
||||
|
||||
// handle old style log
|
||||
// TODO: delete once M is launched
|
||||
if (operands.length < 5) {
|
||||
mSinceVisibleMillis = mSinceUpdateMillis;
|
||||
mSinceUpdateMillis = 0;
|
||||
}
|
||||
|
||||
boolean intentional = true;
|
||||
switch (reason) {
|
||||
case REASON_DELEGATE_CANCEL:
|
||||
case REASON_DELEGATE_CANCEL_ALL:
|
||||
case REASON_LISTENER_CANCEL:
|
||||
case REASON_LISTENER_CANCEL_ALL:
|
||||
case REASON_DELEGATE_CLICK:
|
||||
case REASON_PACKAGE_BANNED:
|
||||
break;
|
||||
default:
|
||||
intentional = false;
|
||||
}
|
||||
|
||||
if (mKey.parse(keyString)) {
|
||||
if (intentional) {
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
|
||||
proto.setType(MetricsEvent.TYPE_DISMISS);
|
||||
proto.setSubtype(reason);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.e(TAG, "unable to parse key: " + keyString);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification interaction event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationClickedParser extends TagParser {
|
||||
private static final String TAG = "NotificationClicked";
|
||||
private static final int EVENTLOG_TAG = 27520;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationClickedParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 0) {
|
||||
try {
|
||||
if (mKey.parse((String) operands[0])) {
|
||||
parseTimes(operands, 1);
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
|
||||
proto.setType(MetricsEvent.TYPE_ACTION);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
} else if (debug) {
|
||||
Log.e(TAG, "unable to parse key.");
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification expansion event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationExpansionParser extends TagParser {
|
||||
private static final String TAG = "NotificationExpansion";
|
||||
private static final int EVENTLOG_TAG = 27511;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationExpansionParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 2) {
|
||||
try {
|
||||
if (mKey.parse((String) operands[0])) {
|
||||
boolean byUser = ((Integer) operands[1]) == 1;
|
||||
boolean expanded = ((Integer) operands[2]) == 1;
|
||||
parseTimes(operands, 3);
|
||||
|
||||
if (!byUser || !expanded) {
|
||||
return;
|
||||
}
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
|
||||
proto.setType(MetricsEvent.TYPE_DETAIL);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
} else if (debug) {
|
||||
Log.e(TAG, "unable to parse key.");
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Parse Android notification keys
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationKey {
|
||||
|
||||
private static final String TAG = "NotificationKey";
|
||||
|
||||
public int mUser;
|
||||
public String mPackageName;
|
||||
public int mId;
|
||||
public String mTag;
|
||||
public int mUid;
|
||||
|
||||
public boolean parse(String key) {
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
boolean debug = Util.debug();
|
||||
String[] parts = key.split("\\|");
|
||||
if (parts.length == 5) {
|
||||
try {
|
||||
mUser = Integer.valueOf(parts[0]);
|
||||
mPackageName = parts[1];
|
||||
mId = Integer.valueOf(parts[2]);
|
||||
mTag = parts[3].equals("null") ? "" : parts[3];
|
||||
mUid = Integer.valueOf(parts[4]);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
if (debug) {
|
||||
Log.w(TAG, "could not parse notification key.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
Log.w(TAG, "wrong number of parts in notification key: " + key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification panel visibility event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationPanelHiddenParser extends TagParser {
|
||||
private static final String TAG = "NotificationPanelHidden";
|
||||
private static final int EVENTLOG_TAG = 27501;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_PANEL);
|
||||
proto.setType(MetricsEvent.TYPE_CLOSE);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
logger.addEvent(proto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android notification panel visibility event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationPanelRevealedParser extends TagParser {
|
||||
private static final String TAG = "NotificationPanelRevea";
|
||||
private static final int EVENTLOG_TAG = 27500;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 1) {
|
||||
try {
|
||||
int load = ((Integer) operands[0]).intValue();
|
||||
//logger.incrementBy(TronCounters.TRON_NOTIFICATION_LOAD, load);
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_PANEL);
|
||||
proto.setType(MetricsEvent.TYPE_OPEN);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
logger.addEvent(proto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the new Android notification visibility event logs.
|
||||
* @hide
|
||||
*/
|
||||
public class NotificationVisibilityParser extends TagParser {
|
||||
private static final String TAG = "NotificationVisibility";
|
||||
private static final int EVENTLOG_TAG = 27531;
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationVisibilityParser() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length > 1) {
|
||||
try {
|
||||
final String keyString = (String) operands[0];
|
||||
final boolean visible = ((Integer) operands[1]) == 1;
|
||||
parseTimes(operands, 2);
|
||||
int index = 0;
|
||||
if (operands.length > 5 && operands[5] instanceof Integer) {
|
||||
index = (Integer) operands[5];
|
||||
}
|
||||
|
||||
if (mKey.parse(keyString)) {
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
|
||||
proto.setType(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setPackageName(mKey.mPackageName);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, index);
|
||||
filltimes(proto);
|
||||
logger.addEvent(proto);
|
||||
} else {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unable to parse key: " + keyString);
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android lockscreen gesture logs.
|
||||
* @hide
|
||||
*/
|
||||
public class PowerScreenStateParser extends TagParser {
|
||||
private static final String TAG = "PowerScreenStateParser";
|
||||
private static final int EVENTLOG_TAG = 2728;
|
||||
|
||||
// source of truth is android.view.WindowManagerPolicy, why:
|
||||
// 0: on
|
||||
// 1: OFF_BECAUSE_OF_ADMIN
|
||||
// 2: OFF_BECAUSE_OF_USER
|
||||
// 3: OFF_BECAUSE_OF_TIMEOUT
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 2) {
|
||||
try {
|
||||
// (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
|
||||
boolean state = (((Integer) operands[0]).intValue()) == 1;
|
||||
int why = ((Integer) operands[1]).intValue();
|
||||
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(MetricsEvent.SCREEN);
|
||||
proto.setType(state ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setSubtype(why);
|
||||
logger.addEvent(proto);
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android lockscreen gesture logs.
|
||||
* @hide
|
||||
*/
|
||||
public class StatusBarStateParser extends TagParser {
|
||||
private static final String TAG = "StatusBarStateParser";
|
||||
private static final int EVENTLOG_TAG = 36004;
|
||||
|
||||
// source of truth is com.android.systemui.statusbar.StatusBarState
|
||||
public static final int SHADE = 0;
|
||||
public static final int KEYGUARD = 1;
|
||||
public static final int SHADE_LOCKED = 2;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 6) {
|
||||
try {
|
||||
// [state, isShowing, isOccluded, isBouncerShowing, isSecure, isCurrentlyInsecure]
|
||||
int state = ((Integer) operands[0]).intValue();
|
||||
boolean isBouncerShowing = (((Integer) operands[3]).intValue()) == 1;
|
||||
int isSecure = ((Integer) operands[4]).intValue();
|
||||
|
||||
int view = MetricsEvent.LOCKSCREEN;
|
||||
int type = MetricsEvent.TYPE_OPEN;
|
||||
if (state == SHADE) {
|
||||
type = MetricsEvent.TYPE_CLOSE;
|
||||
} else if (isBouncerShowing) {
|
||||
view = MetricsEvent.BOUNCER;
|
||||
}
|
||||
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(view);
|
||||
proto.setType(type);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
proto.setSubtype(isSecure);
|
||||
logger.addEvent(proto);
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android framework sysui action logs.
|
||||
* @hide
|
||||
*/
|
||||
public class SysuiActionParser extends TagParser {
|
||||
private static final String TAG = "SysuiActionParser";
|
||||
private static final int EVENTLOG_TAG = 524288;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
try {
|
||||
String packageName = null;
|
||||
int subType = -1;
|
||||
boolean hasSubType = false;
|
||||
if (operands.length > 1) {
|
||||
String arg = (String) operands[1];
|
||||
if (arg.equals("true")) {
|
||||
hasSubType = true;
|
||||
subType = 1;
|
||||
} else if (arg.equals("false")) {
|
||||
hasSubType = true;
|
||||
subType = 0;
|
||||
} else if (arg.matches("^-?\\d+$")) {
|
||||
try {
|
||||
subType = Integer.valueOf(arg);
|
||||
hasSubType = true;
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
} else {
|
||||
packageName = arg;
|
||||
}
|
||||
}
|
||||
if (operands.length > 0) {
|
||||
int category = ((Integer) operands[0]).intValue();
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(category);
|
||||
proto.setType(MetricsEvent.TYPE_ACTION);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
if (packageName != null) {
|
||||
proto.setPackageName(packageName);
|
||||
}
|
||||
if (hasSubType) {
|
||||
proto.setSubtype(subType);
|
||||
}
|
||||
logger.addEvent(proto);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* ...and one parser to rule them all.
|
||||
*
|
||||
* This should, at some point in the future, be the only parser.
|
||||
* @hide
|
||||
*/
|
||||
public class SysuiMultiActionParser extends TagParser {
|
||||
private static final String TAG = "SysuiMultiActionParser";
|
||||
private static final int EVENTLOG_TAG = 524292;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
try {
|
||||
logger.addEvent(new LogBuilder(operands).setTimestamp(eventTimeMs));
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
/**
|
||||
* Parse the Android framework sysui search query logs.
|
||||
* For now just treat them like actions.
|
||||
* @hide
|
||||
*/
|
||||
public class SysuiQueryParser extends SysuiActionParser {
|
||||
private static final String TAG = "SysuiQueryParser";
|
||||
|
||||
private static final int EVENTLOG_TAG = 524289;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Parse the Android framework sysui view visibility logs.
|
||||
* @hide
|
||||
*/
|
||||
public class SysuiViewVisibilityParser extends TagParser {
|
||||
private static final String TAG = "SysuiViewVisibility";
|
||||
private static final int EVENTLOG_TAG = 524287;
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return EVENTLOG_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
|
||||
final boolean debug = Util.debug();
|
||||
if (operands.length >= 2) {
|
||||
try {
|
||||
int category = ((Integer) operands[0]).intValue();
|
||||
boolean visibility = ((Integer) operands[1]).intValue() != 0;
|
||||
|
||||
LogBuilder proto = logger.obtain();
|
||||
proto.setCategory(category);
|
||||
proto.setType(visibility ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
|
||||
proto.setTimestamp(eventTimeMs);
|
||||
logger.addEvent(proto);
|
||||
} catch (ClassCastException e) {
|
||||
if (debug) {
|
||||
Log.e(TAG, "unexpected operand type: ", e);
|
||||
}
|
||||
}
|
||||
} else if (debug) {
|
||||
Log.w(TAG, "wrong number of operands: " + operands.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
104
core/java/com/android/internal/logging/legacy/TagParser.java
Executable file
104
core/java/com/android/internal/logging/legacy/TagParser.java
Executable file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
/**
|
||||
* Abstraction layer between EventLog static classes and the actual TagParsers.
|
||||
* @hide
|
||||
*/
|
||||
public abstract class TagParser {
|
||||
private static final String TAG = "TagParser";
|
||||
|
||||
protected int mSinceCreationMillis;
|
||||
protected int mSinceUpdateMillis;
|
||||
protected int mSinceVisibleMillis;
|
||||
|
||||
abstract int getTag();
|
||||
|
||||
@VisibleForTesting
|
||||
abstract public void parseEvent(TronLogger logger, long eventTimeMs, Object[] objects);
|
||||
|
||||
/**
|
||||
* Parse the event into the proto: return true if proto was modified.
|
||||
*/
|
||||
public void parseEvent(TronLogger logger, EventLogCollector.Event event) {
|
||||
final boolean debug = Util.debug();
|
||||
Object data = event.getData();
|
||||
Object[] objects;
|
||||
if (data instanceof Object[]) {
|
||||
objects = (Object[]) data;
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
if (objects[i] == null) {
|
||||
if (debug) {
|
||||
Log.d(TAG, "unexpected null value:" + event.getTag());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// wrap scalar objects
|
||||
objects = new Object[1];
|
||||
objects[0] = data;
|
||||
}
|
||||
|
||||
parseEvent(logger, event.getTimeNanos() / 1000000, objects);
|
||||
}
|
||||
|
||||
protected void resetTimes() {
|
||||
mSinceCreationMillis = 0;
|
||||
mSinceUpdateMillis = 0;
|
||||
mSinceVisibleMillis = 0;
|
||||
}
|
||||
|
||||
public void parseTimes(Object[] operands, int index) {
|
||||
resetTimes();
|
||||
|
||||
if (operands.length > index && operands[index] instanceof Integer) {
|
||||
mSinceCreationMillis = (Integer) operands[index];
|
||||
}
|
||||
|
||||
index++;
|
||||
if (operands.length > index && operands[index] instanceof Integer) {
|
||||
mSinceUpdateMillis = (Integer) operands[index];
|
||||
}
|
||||
|
||||
index++;
|
||||
if (operands.length > index && operands[index] instanceof Integer) {
|
||||
mSinceVisibleMillis = (Integer) operands[index];
|
||||
}
|
||||
}
|
||||
|
||||
public void filltimes(LogBuilder proto) {
|
||||
if (mSinceCreationMillis != 0) {
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS,
|
||||
mSinceCreationMillis);
|
||||
}
|
||||
if (mSinceUpdateMillis != 0) {
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS,
|
||||
mSinceUpdateMillis);
|
||||
}
|
||||
if (mSinceVisibleMillis != 0) {
|
||||
proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS,
|
||||
mSinceVisibleMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
/**
|
||||
* Names of the counters that the Tron package defines.
|
||||
*
|
||||
* Other counter names may be generated by AOSP code.
|
||||
* @hide
|
||||
*/
|
||||
public class TronCounters {
|
||||
|
||||
static final String TRON_COLLECTIONS = "tron_collections";
|
||||
|
||||
static final String TRON_COLLECTION_PERIOD = "tron_collection_period_minutes";
|
||||
|
||||
static final String TRON_EVENTLOG_LENGTH = "tron_eventlog_horizon";
|
||||
|
||||
static final String TRON_NOTE_DISMISS = "tron_note_dismiss";
|
||||
|
||||
static final String TRON_NOTE_DISMISS_BY_USER = "tron_note_dismiss_user";
|
||||
|
||||
static final String TRON_NOTE_DISMISS_BY_CLICK = "tron_note_dismiss_click";
|
||||
|
||||
static final String TRON_NOTE_DISMISS_BY_LISTENER = "tron_note_dismiss_listener";
|
||||
|
||||
static final String TRON_NOTE_DISMISS_BY_BAN = "tron_note_dismiss_ban";
|
||||
|
||||
static final String TRON_NOTE_REVEALED = "tron_note_revealed";
|
||||
|
||||
static final String TRON_NOTIFICATION_LOAD = "tron_notification_load";
|
||||
|
||||
static final String TRON_VIEW = "tron_view";
|
||||
|
||||
static final String TRON_ACTION = "tron_action";
|
||||
|
||||
static final String TRON_DETAIL = "tron_detail";
|
||||
|
||||
static final String TRON_NOTE_LIFETIME = "tron_note_lifetime";
|
||||
|
||||
/** Append the AOSP-generated name */
|
||||
static final String TRON_AOSP_PREFIX = "tron_varz_";
|
||||
|
||||
static final String TRON_ACTION_BAD_INT = "tron_action_bad_int";
|
||||
|
||||
static final String TRON_NOTE_FRESHNESS = "tron_note_freshness";
|
||||
|
||||
static final String TRON_NOTE_BUZZ = "tron_note_buzz";
|
||||
|
||||
static final String TRON_NOTE_BEEP = "tron_note_beep";
|
||||
|
||||
static final String TRON_NOTE_BLINK = "tron_note_blink";
|
||||
|
||||
static final String TRON_DISABLE = "tron_disable";
|
||||
|
||||
static final String TRON_LAST_HEART_AGE = "tron_last_heart_minutes";
|
||||
|
||||
static final String TRON_HEARTS_SEEN = "tron_hearts_seen";
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
|
||||
/**
|
||||
* An entity that knows how to log events and counters.
|
||||
*/
|
||||
public interface TronLogger {
|
||||
/** Add one to the named counter. */
|
||||
void increment(String counterName);
|
||||
|
||||
/** Add an arbitrary value to the named counter. */
|
||||
void incrementBy(String counterName, int value);
|
||||
|
||||
/** Increment a specified bucket on the named histogram by one. */
|
||||
void incrementIntHistogram(String counterName, int bucket);
|
||||
|
||||
/** Increment the specified bucket on the named histogram by one. */
|
||||
void incrementLongHistogram(String counterName, long bucket);
|
||||
|
||||
/** Obtain a SystemUiEvent proto, must release this with dispose() or addEvent(). */
|
||||
LogBuilder obtain();
|
||||
|
||||
void dispose(LogBuilder proto);
|
||||
|
||||
/** Submit an event to be logged. Logger will dispose of proto. */
|
||||
void addEvent(LogBuilder proto);
|
||||
|
||||
/** Get a config flag. */
|
||||
boolean getConfig(String configName);
|
||||
|
||||
/** Set a config flag. */
|
||||
void setConfig(String configName, boolean newValue);
|
||||
}
|
||||
25
core/java/com/android/internal/logging/legacy/Util.java
Normal file
25
core/java/com/android/internal/logging/legacy/Util.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
/**
|
||||
* Created by cwren on 11/21/16.
|
||||
*/
|
||||
public class Util {
|
||||
public static boolean debug() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class LogBuilderTest extends TestCase {
|
||||
@@ -15,6 +31,57 @@ public class LogBuilderTest extends TestCase {
|
||||
assertEquals("two", out[3]);
|
||||
}
|
||||
|
||||
public void testSerializeDeserialize() {
|
||||
int category = 10;
|
||||
int type = 11;
|
||||
int subtype = 12;
|
||||
long timestamp = 1484669007890L;
|
||||
String packageName = "com.foo.bar";
|
||||
String counterName = "sheep";
|
||||
int bucket = 13;
|
||||
int value = 14;
|
||||
|
||||
LogBuilder builder = new LogBuilder(category);
|
||||
builder.setType(type);
|
||||
builder.setSubtype(subtype);
|
||||
builder.setTimestamp(timestamp);
|
||||
builder.setPackageName(packageName);
|
||||
builder.setCounterName(counterName);
|
||||
builder.setCounterBucket(bucket);
|
||||
builder.setCounterValue(value);
|
||||
builder.addTaggedData(1, "one");
|
||||
builder.addTaggedData(2, "two");
|
||||
|
||||
Object[] out = builder.serialize();
|
||||
LogBuilder parsed = new LogBuilder(out);
|
||||
|
||||
assertEquals(category, parsed.getCategory());
|
||||
assertEquals(type, parsed.getType());
|
||||
assertEquals(subtype, parsed.getSubtype());
|
||||
assertEquals(timestamp, parsed.getTimestamp());
|
||||
assertEquals(packageName, parsed.getPackageName());
|
||||
assertEquals(counterName, parsed.getCounterName());
|
||||
assertEquals(bucket, parsed.getCounterBucket());
|
||||
assertEquals(value, parsed.getCounterValue());
|
||||
assertEquals("one", parsed.getTaggedData(1));
|
||||
assertEquals("two", parsed.getTaggedData(2));
|
||||
}
|
||||
|
||||
public void testIntBucket() {
|
||||
LogBuilder builder = new LogBuilder(0);
|
||||
builder.setCounterBucket(100);
|
||||
assertEquals(100, builder.getCounterBucket());
|
||||
assertEquals(false, builder.isLongCounterBucket());
|
||||
}
|
||||
|
||||
public void testLongBucket() {
|
||||
long longBucket = Long.MAX_VALUE;
|
||||
LogBuilder builder = new LogBuilder(0);
|
||||
builder.setCounterBucket(longBucket);
|
||||
assertEquals(longBucket, builder.getCounterBucket());
|
||||
assertEquals(true, builder.isLongCounterBucket());
|
||||
}
|
||||
|
||||
public void testInvalidInputThrows() {
|
||||
LogBuilder builder = new LogBuilder(0);
|
||||
boolean threw = false;
|
||||
@@ -24,7 +91,7 @@ public class LogBuilderTest extends TestCase {
|
||||
threw = true;
|
||||
}
|
||||
assertTrue(threw);
|
||||
assertEquals(0, builder.serialize().length);
|
||||
assertEquals(2, builder.serialize().length);
|
||||
}
|
||||
|
||||
public void testValidInputTypes() {
|
||||
@@ -40,4 +107,11 @@ public class LogBuilderTest extends TestCase {
|
||||
assertEquals(123.0F, out[7]);
|
||||
}
|
||||
|
||||
public void testCategoryDefault() {
|
||||
LogBuilder builder = new LogBuilder(10);
|
||||
Object[] out = builder.serialize();
|
||||
assertEquals(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY, out[0]);
|
||||
assertEquals(10, out[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
public class CounterParserTest extends ParserTest {
|
||||
|
||||
public CounterParserTest() {
|
||||
mParser = new CounterParser();
|
||||
}
|
||||
|
||||
public void testGoodData() throws Throwable {
|
||||
String name = "foo";
|
||||
int value = 5;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = name;
|
||||
objects[1] = value;
|
||||
|
||||
validateGoodData(name, value, objects);
|
||||
}
|
||||
|
||||
private void validateGoodData(String name, int value, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, times(1)).incrementBy(mNameCaptor.capture(), mCountCaptor.capture());
|
||||
|
||||
assertEquals(TronCounters.TRON_AOSP_PREFIX + name, mNameCaptor.getValue());
|
||||
assertEquals(value, mCountCaptor.getValue().intValue());
|
||||
}
|
||||
|
||||
public void testMissingName() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testWrongTypes() throws Throwable {
|
||||
String name = "foo";
|
||||
int value = 5;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = value;
|
||||
objects[1] = name;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreMissingInput() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
String name = "foo";
|
||||
int value = 5;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = name;
|
||||
objects[1] = value;
|
||||
objects[2] = "foo";
|
||||
|
||||
validateGoodData(name, value, objects);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
public class HistogramParserTest extends ParserTest {
|
||||
|
||||
public HistogramParserTest() {
|
||||
mParser = new HistogramParser();
|
||||
}
|
||||
|
||||
public void testGoodData() throws Throwable {
|
||||
String name = "foo";
|
||||
int bucket = 5;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = name;
|
||||
objects[1] = bucket;
|
||||
|
||||
validateGoodData(name, bucket, objects);
|
||||
}
|
||||
|
||||
private void validateGoodData(String name, int bucket, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, times(1))
|
||||
.incrementIntHistogram(mNameCaptor.capture(), mCountCaptor.capture());
|
||||
|
||||
assertEquals(TronCounters.TRON_AOSP_PREFIX + name, mNameCaptor.getValue());
|
||||
assertEquals(bucket, mCountCaptor.getValue().intValue());
|
||||
}
|
||||
|
||||
public void testMissingName() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testWrongTypes() throws Throwable {
|
||||
String name = "foo";
|
||||
int value = 5;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = value;
|
||||
objects[1] = name;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreMissingInput() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
String name = "foo";
|
||||
int bucket = 5;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = name;
|
||||
objects[1] = bucket;
|
||||
objects[2] = "foo";
|
||||
|
||||
validateGoodData(name, bucket, objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class LockscreenGestureParserTest extends ParserTest {
|
||||
|
||||
public LockscreenGestureParserTest() {
|
||||
mParser = new LockscreenGestureParser();
|
||||
}
|
||||
|
||||
public void testSwipeUpUnlock() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_UNLOCK, 1, 359, 6382);
|
||||
}
|
||||
|
||||
public void testSwipeToShade() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_SHADE, 2, 324, 0);
|
||||
}
|
||||
|
||||
public void testTapLockHint() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_HINT, 3, 0, 0);
|
||||
}
|
||||
|
||||
public void testCamera() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_CAMERA, 4, 223, 1756);
|
||||
}
|
||||
|
||||
public void testDialer() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_DIALER, 5, 163, 861);
|
||||
}
|
||||
|
||||
public void testTapToLock() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_LOCK, 6, 0, 0);
|
||||
}
|
||||
|
||||
public void testTapOnNotification() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_NOTE, 7, 0, 0);
|
||||
}
|
||||
|
||||
public void testLockscreenQuickSettings() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_LS_QS, 8, 284, 3824);
|
||||
}
|
||||
|
||||
public void testShadePullQuickSettings() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_SHADE_QS_PULL, 9, 175, 3444);
|
||||
}
|
||||
|
||||
public void testShadeTapQuickSettings() throws Throwable {
|
||||
validate(MetricsEvent.ACTION_SHADE_QS_TAP, 10, 0, 0);
|
||||
}
|
||||
|
||||
private void validate(int view, int type, int len, int vel) {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = type;
|
||||
objects[1] = len;
|
||||
objects[2] = vel;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = 1;
|
||||
objects[1] = 0;
|
||||
objects[2] = 0;
|
||||
objects[3] = "foo";
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class NotificationActionClickedParserTest extends ParserTest {
|
||||
|
||||
public NotificationActionClickedParserTest() {
|
||||
mParser = new NotificationActionClickedParser();
|
||||
}
|
||||
|
||||
public void testGoodData() throws Throwable {
|
||||
int t = 1000;
|
||||
int index = 1;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = mKey;
|
||||
objects[1] = index;
|
||||
|
||||
validateGoodData(t, "", index, objects);
|
||||
}
|
||||
|
||||
public void testTagged() throws Throwable {
|
||||
int t = 1000;
|
||||
int index = 1;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = index;
|
||||
|
||||
validateGoodData(t, mTag, index, objects);
|
||||
}
|
||||
|
||||
private LogBuilder validateGoodData(int t, String tag, int index, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ITEM_ACTION, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, tag);
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
assertEquals(index, proto.getSubtype());
|
||||
return proto;
|
||||
}
|
||||
|
||||
public void testMissingData() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testWrongType() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = 2;
|
||||
objects[1] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testBadKey() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = "foo";
|
||||
objects[1] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testMncTimestamps() throws Throwable {
|
||||
int t = 1000;
|
||||
int index = 1;
|
||||
Object[] objects = new Object[5];
|
||||
objects[0] = mKey;
|
||||
objects[1] = index;
|
||||
objects[2] = mSinceCreationMillis;
|
||||
objects[3] = mSinceUpdateMillis;
|
||||
objects[4] = mSinceVisibleMillis;
|
||||
|
||||
LogBuilder proto = validateGoodData(t, "", index, objects);
|
||||
validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
|
||||
mSinceVisibleMillis);
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int index = 1;
|
||||
Object[] objects = new Object[6];
|
||||
objects[0] = mKey;
|
||||
objects[1] = index;
|
||||
objects[2] = mSinceCreationMillis;
|
||||
objects[3] = mSinceUpdateMillis;
|
||||
objects[4] = mSinceVisibleMillis;
|
||||
objects[5] = "foo";
|
||||
|
||||
validateGoodData(t, "", index, objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
public class NotificationAlertParserTest extends ParserTest {
|
||||
protected ArgumentCaptor<Boolean> mConfigCaptor;
|
||||
|
||||
private final int mTime = 1000;
|
||||
|
||||
public NotificationAlertParserTest() {
|
||||
mParser = new NotificationAlertParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mConfigCaptor = ArgumentCaptor.forClass(Boolean.class);
|
||||
when(mLogger.getConfig(anyString())).thenReturn(false);
|
||||
}
|
||||
|
||||
public void testBuzzOnly() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 1;
|
||||
objects[2] = 0;
|
||||
objects[3] = 0;
|
||||
|
||||
validateInteraction(true, false, false, objects);
|
||||
}
|
||||
|
||||
public void testBeepOnly() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 0;
|
||||
objects[2] = 1;
|
||||
objects[3] = 0;
|
||||
|
||||
validateInteraction(false, true, false, objects);
|
||||
}
|
||||
|
||||
public void testBlinkOnly() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 0;
|
||||
objects[2] = 0;
|
||||
objects[3] = 1;
|
||||
|
||||
validateInteraction(false, false, true, objects);
|
||||
}
|
||||
|
||||
public void testBuzzBlink() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 1;
|
||||
objects[2] = 0;
|
||||
objects[3] = 1;
|
||||
|
||||
validateInteraction(true, false, true, objects);
|
||||
}
|
||||
|
||||
public void testBeepBlink() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 0;
|
||||
objects[2] = 1;
|
||||
objects[3] = 1;
|
||||
|
||||
validateInteraction(false, true, true, objects);
|
||||
}
|
||||
|
||||
public void testIgnoreExtraArgs() throws Throwable {
|
||||
Object[] objects = new Object[5];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 0;
|
||||
objects[2] = 1;
|
||||
objects[3] = 1;
|
||||
objects[4] = "foo";
|
||||
|
||||
validateInteraction(false, true, true, objects);
|
||||
}
|
||||
|
||||
private void validateInteraction(boolean buzz, boolean beep, boolean blink, Object[] objects) {
|
||||
int flags = 0;
|
||||
int counts = 0;
|
||||
if (buzz) {
|
||||
counts++;
|
||||
flags |= NotificationAlertParser.BUZZ;
|
||||
}
|
||||
if (beep) {
|
||||
counts++;
|
||||
flags |= NotificationAlertParser.BEEP;
|
||||
}
|
||||
if (blink) {
|
||||
counts++;
|
||||
flags |= NotificationAlertParser.BLINK;
|
||||
}
|
||||
|
||||
mParser.parseEvent(mLogger, mTime, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(mTime, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ALERT, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, mTag);
|
||||
assertEquals(flags, proto.getSubtype());
|
||||
assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Mockito.anyObject;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NotificationCanceledParserTest extends ParserTest {
|
||||
|
||||
public NotificationCanceledParserTest() {
|
||||
mParser = new NotificationCanceledParser();
|
||||
}
|
||||
|
||||
public void testGoodProto() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
|
||||
validateGoodData(t, "", reason, objects);
|
||||
}
|
||||
|
||||
public void testTagged() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = reason;
|
||||
|
||||
validateGoodData(t, mTag, reason, objects);
|
||||
}
|
||||
|
||||
private void validateGoodData(int t, String tag, int reason, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, tag);
|
||||
assertEquals(MetricsEvent.TYPE_DISMISS, proto.getType());
|
||||
assertEquals(reason, proto.getSubtype());
|
||||
}
|
||||
|
||||
public void testLifetime() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
objects[2] = mSinceCreationMillis;
|
||||
|
||||
validateTimers(t, objects, mSinceCreationMillis, 0, 0);
|
||||
}
|
||||
|
||||
public void testExposure() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
objects[2] = mSinceCreationMillis;
|
||||
objects[3] = mSinceVisibleMillis;
|
||||
|
||||
|
||||
validateTimers(t, objects, mSinceCreationMillis, 0, mSinceVisibleMillis);
|
||||
}
|
||||
|
||||
public void testFreshness() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[5];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
objects[2] = mSinceCreationMillis;
|
||||
objects[3] = mSinceUpdateMillis;
|
||||
objects[4] = mSinceVisibleMillis;
|
||||
|
||||
validateTimers(t, objects, mSinceCreationMillis, mSinceUpdateMillis, mSinceVisibleMillis);
|
||||
}
|
||||
|
||||
private void validateTimers(int t, Object[] objects, int life, int freshness, int exposure) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
validateNotificationTimes(proto, life, freshness, exposure);
|
||||
}
|
||||
|
||||
public void verifyReason(int reason, boolean intentional, boolean important, String counter)
|
||||
throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
if (intentional) {
|
||||
verify(mLogger, times(1)).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDelegateCancel() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_DELEGATE_CANCEL,
|
||||
true, true, TronCounters.TRON_NOTE_DISMISS_BY_USER);
|
||||
}
|
||||
|
||||
public void testDelegateCancelAll() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_DELEGATE_CANCEL_ALL,
|
||||
true, true, TronCounters.TRON_NOTE_DISMISS_BY_USER);
|
||||
}
|
||||
|
||||
public void testListenerCancel() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_LISTENER_CANCEL,
|
||||
false, true, TronCounters.TRON_NOTE_DISMISS_BY_LISTENER);
|
||||
}
|
||||
|
||||
public void testListenerCancelAll() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_LISTENER_CANCEL_ALL,
|
||||
false, true, TronCounters.TRON_NOTE_DISMISS_BY_LISTENER);
|
||||
}
|
||||
|
||||
public void testDelegateClick() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_DELEGATE_CLICK,
|
||||
true, true, TronCounters.TRON_NOTE_DISMISS_BY_CLICK);
|
||||
}
|
||||
|
||||
public void testBanned() throws Throwable {
|
||||
verifyReason(NotificationCanceledParser.REASON_PACKAGE_BANNED,
|
||||
false, true, TronCounters.TRON_NOTE_DISMISS_BY_BAN);
|
||||
}
|
||||
|
||||
public void testUnknownReason() throws Throwable {
|
||||
verifyReason(1001010, false, false, TronCounters.TRON_NOTE_DISMISS_BY_BAN);
|
||||
}
|
||||
|
||||
public void testMissingData() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testWrongType() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = 2;
|
||||
objects[1] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testBadKey() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = "foo";
|
||||
objects[1] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = reason;
|
||||
objects[2] = "foo";
|
||||
|
||||
validateGoodData(t, "", reason, objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class NotificationClickedParserTest extends ParserTest {
|
||||
|
||||
public NotificationClickedParserTest() {
|
||||
mParser = new NotificationClickedParser();
|
||||
}
|
||||
|
||||
public void testGoodData() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = mKey;
|
||||
|
||||
validateGoodData(t, "", objects);
|
||||
}
|
||||
|
||||
public void testTagged() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = mTaggedKey;
|
||||
|
||||
validateGoodData(t, mTag, objects);
|
||||
}
|
||||
|
||||
private LogBuilder validateGoodData(int t, String tag, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, tag);
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
assertEquals(0, proto.getSubtype());
|
||||
return proto;
|
||||
}
|
||||
|
||||
public void testMissingKey() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testWrongType() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = 5;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testBadKey() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = "foo";
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testMncTimestamps() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mKey;
|
||||
objects[1] = mSinceCreationMillis;
|
||||
objects[2] = mSinceUpdateMillis;
|
||||
objects[3] = mSinceVisibleMillis;
|
||||
|
||||
LogBuilder proto = validateGoodData(t, "", objects);
|
||||
validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
|
||||
mSinceVisibleMillis);
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[5];
|
||||
objects[0] = mKey;
|
||||
objects[1] = mSinceCreationMillis;
|
||||
objects[2] = mSinceUpdateMillis;
|
||||
objects[3] = mSinceVisibleMillis;
|
||||
objects[4] = "foo";
|
||||
|
||||
validateGoodData(t, "", objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class NotificationExpansionParserTest extends ParserTest {
|
||||
|
||||
public NotificationExpansionParserTest() {
|
||||
mParser = new NotificationExpansionParser();
|
||||
}
|
||||
|
||||
public void testExpandedByUser() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 1;
|
||||
int expanded = 1;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
|
||||
validateGoodData(t, "", objects);
|
||||
}
|
||||
|
||||
public void testTagged() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 1;
|
||||
int expanded = 1;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
|
||||
validateGoodData(t, mTag, objects);
|
||||
}
|
||||
|
||||
private LogBuilder validateGoodData(int t, String tag, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, tag);
|
||||
assertEquals(MetricsEvent.TYPE_DETAIL, proto.getType());
|
||||
return proto;
|
||||
}
|
||||
|
||||
public void testAutoExpand() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 0;
|
||||
int expanded = 1;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testCollapsedByUser() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 1;
|
||||
int expanded = 0;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testAutoCollapsed() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 0;
|
||||
int expanded = 0;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testMissingData() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testWrongType() throws Throwable {
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = 2;
|
||||
objects[1] = 5;
|
||||
objects[2] = 7;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testBadKey() throws Throwable {
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = "foo";
|
||||
objects[1] = 5;
|
||||
objects[2] = 2;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testMncTimestamps() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 1;
|
||||
int expanded = 1;
|
||||
Object[] objects = new Object[6];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
objects[3] = mSinceCreationMillis;
|
||||
objects[4] = mSinceUpdateMillis;
|
||||
objects[5] = mSinceVisibleMillis;
|
||||
|
||||
LogBuilder proto = validateGoodData(t, "", objects);
|
||||
validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
|
||||
mSinceVisibleMillis);
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int byUser = 1;
|
||||
int expanded = 1;
|
||||
Object[] objects = new Object[7];
|
||||
objects[0] = mKey;
|
||||
objects[1] = byUser;
|
||||
objects[2] = expanded;
|
||||
objects[3] = mSinceCreationMillis;
|
||||
objects[4] = mSinceUpdateMillis;
|
||||
objects[5] = mSinceVisibleMillis;
|
||||
objects[6] = "foo";
|
||||
|
||||
validateGoodData(t, "", objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
public class NotificationKeyTest extends InstrumentationTestCase {
|
||||
|
||||
private final NotificationKey mKey;
|
||||
|
||||
public NotificationKeyTest() {
|
||||
mKey = new NotificationKey();
|
||||
}
|
||||
|
||||
public void testGoodKey() throws Throwable {
|
||||
assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338|null|10090"));
|
||||
|
||||
assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
|
||||
assertEquals("", mKey.mTag);
|
||||
assertEquals(31338, mKey.mId);
|
||||
assertEquals(1, mKey.mUser);
|
||||
assertEquals(10090, mKey.mUid);
|
||||
}
|
||||
|
||||
public void testTaggedKey() throws Throwable {
|
||||
assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338|foo|10090"));
|
||||
|
||||
assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
|
||||
assertEquals("foo", mKey.mTag);
|
||||
assertEquals(31338, mKey.mId);
|
||||
assertEquals(1, mKey.mUser);
|
||||
assertEquals(10090, mKey.mUid);
|
||||
}
|
||||
|
||||
public void testEmptyTag() throws Throwable {
|
||||
assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338||10090"));
|
||||
|
||||
assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
|
||||
assertEquals("", mKey.mTag);
|
||||
assertEquals(31338, mKey.mId);
|
||||
assertEquals(1, mKey.mUser);
|
||||
assertEquals(10090, mKey.mUid);
|
||||
}
|
||||
|
||||
public void testBadKeys() throws Throwable {
|
||||
assertFalse(mKey.parse(null));
|
||||
assertFalse(mKey.parse(""));
|
||||
assertFalse(mKey.parse("foo")); // not a key
|
||||
assertFalse(mKey.parse("1|com.android.example.notificationshowcase|31338|null"));
|
||||
assertFalse(mKey.parse("bar|com.android.example.notificationshowcase|31338|null|10090"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class NotificationPanelHiddenParserTest extends ParserTest {
|
||||
|
||||
public NotificationPanelHiddenParserTest() {
|
||||
mParser = new NotificationPanelHiddenParser();
|
||||
}
|
||||
|
||||
public void testNoInput() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
validateGoodData(t, objects);
|
||||
|
||||
}
|
||||
|
||||
public void testIgnoreExtraneousInput() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = "nothing to see here";
|
||||
|
||||
validateGoodData(0, objects);
|
||||
}
|
||||
|
||||
private void validateGoodData(int t, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_CLOSE, proto.getType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class NotificationPanelRevealedParserTest extends ParserTest {
|
||||
|
||||
public NotificationPanelRevealedParserTest() {
|
||||
mParser = new NotificationPanelRevealedParser();
|
||||
}
|
||||
|
||||
public void testLollipopInput() throws Throwable {
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
|
||||
}
|
||||
|
||||
public void testMncData() throws Throwable {
|
||||
int t = 1000;
|
||||
int n = 5;
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = Integer.valueOf(n);
|
||||
|
||||
validateMncData(t, n, objects);
|
||||
}
|
||||
|
||||
private void validateMncData(int t, int n, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
|
||||
}
|
||||
|
||||
public void testBadInput() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = "This is not the integer you're looking for.";
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent((LogBuilder) anyObject());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int n = 5;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = Integer.valueOf(n);
|
||||
objects[1] = "foo";
|
||||
|
||||
validateMncData(t, n, objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
public class NotificationVisibilityParserTest extends ParserTest {
|
||||
private final int mCreationTime = 23124;
|
||||
private final int mUpdateTime = 3412;
|
||||
private final int mTime = 1000;
|
||||
|
||||
public NotificationVisibilityParserTest() {
|
||||
mParser = new NotificationVisibilityParser();
|
||||
}
|
||||
|
||||
public void testReveal() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 1;
|
||||
objects[2] = mCreationTime;
|
||||
objects[3] = mUpdateTime;
|
||||
|
||||
validateInteraction(true, mUpdateTime, 0, objects);
|
||||
}
|
||||
|
||||
public void testHide() throws Throwable {
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 0;
|
||||
objects[2] = mCreationTime;
|
||||
objects[3] = mUpdateTime;
|
||||
|
||||
validateInteraction(false, mUpdateTime, 0, objects);
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
Object[] objects = new Object[5];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 1;
|
||||
objects[2] = mCreationTime;
|
||||
objects[3] = mUpdateTime;
|
||||
objects[4] = "foo";
|
||||
|
||||
validateInteraction(true, mUpdateTime, 0, objects);
|
||||
}
|
||||
|
||||
public void testMarshmallowIndexData() throws Throwable {
|
||||
Object[] objects = new Object[6];
|
||||
objects[0] = mTaggedKey;
|
||||
objects[1] = 1;
|
||||
objects[2] = mCreationTime;
|
||||
objects[3] = mUpdateTime;
|
||||
objects[4] = 0;
|
||||
objects[5] = 3;
|
||||
|
||||
validateInteraction(true, mUpdateTime, 3, objects);
|
||||
}
|
||||
|
||||
private void validateInteraction(boolean visible, int freshness, int index, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, mTime, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(mTime, proto.getTimestamp());
|
||||
assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
|
||||
assertEquals(mKeyPackage, proto.getPackageName());
|
||||
validateNotificationIdAndTag(proto, mId, mTag);
|
||||
validateNotificationTimes(proto, mCreationTime, mUpdateTime);
|
||||
assertEquals(index, proto.getTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX));
|
||||
assertEquals(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE, proto.getType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.OngoingStubbing;
|
||||
|
||||
/**
|
||||
* Common functions and temporaries for parser tests.
|
||||
*/
|
||||
public class ParserTest extends TestCase {
|
||||
@Mock
|
||||
protected TronLogger mLogger;
|
||||
|
||||
protected TagParser mParser;
|
||||
|
||||
protected LogBuilder[] mProto;
|
||||
protected ArgumentCaptor<LogBuilder> mProtoCaptor;
|
||||
protected ArgumentCaptor<String> mNameCaptor;
|
||||
protected ArgumentCaptor<Integer> mCountCaptor;
|
||||
protected String mKey = "0|com.android.example.notificationshowcase|31338|null|10090";
|
||||
protected String mTaggedKey = "0|com.android.example.notificationshowcase|31338|badger|10090";
|
||||
protected String mKeyPackage = "com.android.example.notificationshowcase";
|
||||
protected String mTag = "badger";
|
||||
protected int mId = 31338;
|
||||
protected int mSinceCreationMillis = 5000;
|
||||
protected int mSinceUpdateMillis = 1012;
|
||||
protected int mSinceVisibleMillis = 323;
|
||||
|
||||
|
||||
public ParserTest() {
|
||||
mProto = new LogBuilder[5];
|
||||
for (int i = 0; i < mProto.length; i++) {
|
||||
mProto[i] = new LogBuilder(MetricsEvent.VIEW_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mProtoCaptor = ArgumentCaptor.forClass(LogBuilder.class);
|
||||
mNameCaptor = ArgumentCaptor.forClass(String.class);
|
||||
mCountCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
OngoingStubbing<LogBuilder> stub = when(mLogger.obtain()).thenReturn(mProto[0]);
|
||||
for (int i = 1; i < mProto.length; i++) {
|
||||
stub.thenReturn(mProto[i]);
|
||||
}
|
||||
doNothing().when(mLogger).addEvent(any(LogBuilder.class));
|
||||
doNothing().when(mLogger).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
protected void validateNotificationTimes(LogBuilder proto, int life, int freshness,
|
||||
int exposure) {
|
||||
validateNotificationTimes(proto, life, freshness);
|
||||
if (exposure != 0) {
|
||||
assertEquals(exposure,
|
||||
proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS));
|
||||
} else {
|
||||
assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS));
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateNotificationTimes(LogBuilder proto, int life, int freshness) {
|
||||
if (life != 0) {
|
||||
assertEquals(life,
|
||||
proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS));
|
||||
} else {
|
||||
assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS));
|
||||
}
|
||||
if (freshness != 0) {
|
||||
assertEquals(freshness,
|
||||
proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS));
|
||||
} else {
|
||||
assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS));
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateNotificationIdAndTag(LogBuilder proto, int id, String tag) {
|
||||
assertEquals(tag, proto.getTaggedData(MetricsEvent.NOTIFICATION_TAG));
|
||||
assertEquals(id, proto.getTaggedData(MetricsEvent.NOTIFICATION_ID));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class PowerScreenStateParserTest extends ParserTest {
|
||||
|
||||
public PowerScreenStateParserTest() {
|
||||
mParser = new PowerScreenStateParser();
|
||||
}
|
||||
|
||||
public void testScreenOn() throws Throwable {
|
||||
validate(MetricsEvent.TYPE_OPEN, 0, "1,0,0,0");
|
||||
}
|
||||
|
||||
public void testTimeout() throws Throwable {
|
||||
validate(MetricsEvent.TYPE_CLOSE, 3, "0,3,0,0");
|
||||
}
|
||||
|
||||
public void testUser() throws Throwable {
|
||||
validate(MetricsEvent.TYPE_CLOSE, 2, "0,2,0,0");
|
||||
}
|
||||
|
||||
public void testAdmin() throws Throwable {
|
||||
validate(MetricsEvent.TYPE_CLOSE, 1, "0,1,0,0");
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
validate(MetricsEvent.TYPE_OPEN, 0, "1,0,0,0,5");
|
||||
}
|
||||
|
||||
private void validate(int type, int subType, String log) {
|
||||
String[] parts = log.split(",");
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
objects[i] = Integer.valueOf(parts[i]);
|
||||
}
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(type, proto.getType());
|
||||
assertEquals(MetricsEvent.SCREEN, proto.getCategory());
|
||||
assertEquals(subType, proto.getSubtype());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class StatusBarStateParserTest extends ParserTest {
|
||||
|
||||
public StatusBarStateParserTest() {
|
||||
mParser = new StatusBarStateParser();
|
||||
}
|
||||
|
||||
public void testLockScreen() throws Throwable {
|
||||
validate(MetricsEvent.LOCKSCREEN, MetricsEvent.TYPE_OPEN, 1, "1,1,0,0,1,0");
|
||||
}
|
||||
|
||||
public void testBounce() throws Throwable {
|
||||
validate(MetricsEvent.BOUNCER, MetricsEvent.TYPE_OPEN, 1, "1,1,0,1,1,0");
|
||||
}
|
||||
|
||||
public void testUnlock() throws Throwable {
|
||||
validate(MetricsEvent.LOCKSCREEN, MetricsEvent.TYPE_CLOSE, 1, "0,0,0,0,1,0");
|
||||
}
|
||||
|
||||
public void testSecure() throws Throwable {
|
||||
validate(MetricsEvent.BOUNCER, MetricsEvent.TYPE_OPEN, 1, "2,1,0,1,1,0");
|
||||
}
|
||||
|
||||
public void testInsecure() throws Throwable {
|
||||
validate(MetricsEvent.LOCKSCREEN, MetricsEvent.TYPE_OPEN, 0, "1,1,0,0,0,0");
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
validate(MetricsEvent.LOCKSCREEN, MetricsEvent.TYPE_OPEN, 0, "1,1,0,0,0,0,5");
|
||||
}
|
||||
|
||||
private void validate(int view, int type, int subType, String log) {
|
||||
String[] parts = log.split(",");
|
||||
int t = 1000;
|
||||
Object[] objects = new Object[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
objects[i] = Integer.valueOf(parts[i]);
|
||||
}
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(type, proto.getType());
|
||||
assertEquals(subType, proto.getSubtype());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class SysuiActionParserTest extends ParserTest {
|
||||
|
||||
public SysuiActionParserTest() {
|
||||
mParser = new SysuiActionParser();
|
||||
}
|
||||
|
||||
public void testGoodDatal() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = view;
|
||||
|
||||
validateGoodData(t, view, objects);
|
||||
}
|
||||
|
||||
private void validateGoodData(int t, int view, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
}
|
||||
|
||||
public void testGoodDataWithPackage() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
String packageName = "com.foo";
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = view;
|
||||
objects[1] = packageName;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(packageName, proto.getPackageName());
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
}
|
||||
|
||||
public void testGoodDataWithTrue() throws Throwable {
|
||||
validateSubType(Boolean.toString(true), 1);
|
||||
}
|
||||
|
||||
public void testGoodDataWithFalse() throws Throwable {
|
||||
validateSubType(Boolean.toString(false), 0);
|
||||
}
|
||||
|
||||
public void testGoodDataWithIntZero() throws Throwable {
|
||||
validateSubType(Integer.toString(0), 0);
|
||||
}
|
||||
|
||||
public void testGoodDataWithIntONe() throws Throwable {
|
||||
validateSubType(Integer.toString(1), 1);
|
||||
}
|
||||
|
||||
public void testGoodDataWithIntTwo() throws Throwable {
|
||||
validateSubType(Integer.toString(2), 2);
|
||||
}
|
||||
|
||||
public void testGoodDataWithNegativeInt() throws Throwable {
|
||||
validateSubType(Integer.toString(-1), -1);
|
||||
}
|
||||
|
||||
public void testGoodDataWithIntLarge() throws Throwable {
|
||||
validateSubType(Integer.toString(120312), 120312);
|
||||
}
|
||||
|
||||
public void testGoodDataWithNegativeIntLarge() throws Throwable {
|
||||
validateSubType(Integer.toString(-120312), -120312);
|
||||
}
|
||||
|
||||
private void validateSubType(String arg, int expectedValue) {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = view;
|
||||
objects[1] = arg;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(expectedValue, proto.getSubtype());
|
||||
assertNull(proto.getPackageName());
|
||||
assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
|
||||
}
|
||||
|
||||
public void testIgnoreMissingInput() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreWrongInputs() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = "nothing to see here";
|
||||
objects[1] = 10;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreStringViewInput() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = "this is not the input you are looking for";
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = view;
|
||||
objects[1] = "foo";
|
||||
|
||||
validateGoodData(t, view, objects);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class SysuiMultiActionParserTest extends ParserTest {
|
||||
|
||||
public SysuiMultiActionParserTest() {
|
||||
mParser = new SysuiMultiActionParser();
|
||||
}
|
||||
|
||||
public void testParseAllFields() {
|
||||
int category = 10;
|
||||
int type = 11;
|
||||
int subtype = 12;
|
||||
long timestamp = 1484669007890L;
|
||||
String packageName = "com.foo.bar";
|
||||
String counterName = "sheep";
|
||||
int bucket = 13;
|
||||
int value = 14;
|
||||
LogBuilder builder = new LogBuilder(category);
|
||||
builder.setType(type);
|
||||
builder.setSubtype(subtype);
|
||||
builder.setPackageName(packageName);
|
||||
builder.setCounterName(counterName);
|
||||
builder.setCounterBucket(bucket);
|
||||
builder.setCounterValue(value);
|
||||
builder.addTaggedData(1, "one");
|
||||
builder.addTaggedData(2, "two");
|
||||
Object[] out = builder.serialize();
|
||||
int t = 1000;
|
||||
|
||||
mParser.parseEvent(mLogger, timestamp, out);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(category, proto.getCategory());
|
||||
assertEquals(type, proto.getType());
|
||||
assertEquals(subtype, proto.getSubtype());
|
||||
assertEquals(timestamp, proto.getTimestamp());
|
||||
assertEquals(packageName, proto.getPackageName());
|
||||
assertEquals(counterName, proto.getCounterName());
|
||||
assertEquals(bucket, proto.getCounterBucket());
|
||||
assertEquals(value, proto.getCounterValue());
|
||||
assertEquals("one", proto.getTaggedData(1));
|
||||
assertEquals("two", proto.getTaggedData(2));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.logging.legacy;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
import com.android.internal.logging.LogBuilder;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
public class SysuiViewVisibilityParserTest extends ParserTest {
|
||||
|
||||
public SysuiViewVisibilityParserTest() {
|
||||
mParser = new SysuiViewVisibilityParser();
|
||||
}
|
||||
|
||||
public void testViewReveal() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = view;
|
||||
objects[1] = 100;
|
||||
|
||||
validateViewReveal(t, view, objects);
|
||||
}
|
||||
|
||||
private void validateViewReveal(int t, int view, Object[] objects) {
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(t, proto.getTimestamp());
|
||||
assertEquals(view, proto.getCategory());
|
||||
assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
|
||||
}
|
||||
|
||||
public void testViewHidden() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = view;
|
||||
objects[1] = 0;
|
||||
|
||||
mParser.parseEvent(mLogger, t, objects);
|
||||
|
||||
verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
|
||||
|
||||
LogBuilder proto = mProtoCaptor.getValue();
|
||||
assertEquals(MetricsEvent.TYPE_CLOSE, proto.getType());
|
||||
}
|
||||
|
||||
public void testIgnoreMissingInput() throws Throwable {
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreStringInARgOne() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = "nothing to see here";
|
||||
objects[1] = 100;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreStringInArgTwo() throws Throwable {
|
||||
Object[] objects = new Object[2];
|
||||
objects[0] = 100;
|
||||
objects[1] = "nothing to see here";
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testOneInput() throws Throwable {
|
||||
Object[] objects = new Object[1];
|
||||
objects[0] = 100;
|
||||
|
||||
mParser.parseEvent(mLogger, 0, objects);
|
||||
|
||||
verify(mLogger, never()).addEvent((LogBuilder) anyObject());
|
||||
verify(mLogger, never()).incrementBy(anyString(), anyInt());
|
||||
}
|
||||
|
||||
public void testIgnoreUnexpectedData() throws Throwable {
|
||||
int t = 1000;
|
||||
int view = 10;
|
||||
Object[] objects = new Object[3];
|
||||
objects[0] = view;
|
||||
objects[1] = 100;
|
||||
objects[2] = "foo";
|
||||
|
||||
validateViewReveal(t, view, objects);
|
||||
}
|
||||
}
|
||||
@@ -3173,9 +3173,9 @@ message MetricsEvent {
|
||||
|
||||
// These values should never appear in log outputs - they are reserved for
|
||||
// internal Tron use.
|
||||
RESERVED_FOR_LOGBUILDER_VIEW = 757;
|
||||
RESERVED_FOR_LOGBUILDER_CATEGORY = 758;
|
||||
RESERVED_FOR_LOGBUILDER_TYPE = 759;
|
||||
RESERVED_FOR_LOGBUILDER_CATEGORY = 757;
|
||||
RESERVED_FOR_LOGBUILDER_TYPE = 758;
|
||||
RESERVED_FOR_LOGBUILDER_SUBTYPE = 759;
|
||||
|
||||
// ACTION: "Do not show again" was enabled in the support disclaimer and the
|
||||
// user accepted
|
||||
@@ -3275,16 +3275,36 @@ message MetricsEvent {
|
||||
// OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection
|
||||
DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791;
|
||||
|
||||
|
||||
// OPEN: Settings > Apps > Default Apps > Default auto-fill app
|
||||
DEFAULT_AUTO_FILL_PICKER = 792;
|
||||
|
||||
// ---- End O Constants, all O constants go above this line ----
|
||||
// These values should never appear in log outputs - they are reserved for
|
||||
// internal Tron use.
|
||||
NOTIFICATION_SINCE_CREATE_MILLIS = 793;
|
||||
NOTIFICATION_SINCE_VISIBLE_MILLIS = 794;
|
||||
NOTIFICATION_SINCE_UPDATE_MILLIS = 795;
|
||||
NOTIFICATION_ID = 796;
|
||||
NOTIFICATION_TAG = 797;
|
||||
NOTIFICATION_SHADE_INDEX = 798;
|
||||
RESERVED_FOR_LOGBUILDER_NAME = 799;
|
||||
|
||||
// OPEN: QS NFC tile shown
|
||||
// ACTION: QS NFC tile tapped
|
||||
// CATEGORY: QUICK_SETTINGS
|
||||
QS_NFC = 800;
|
||||
|
||||
// These values should never appear in log outputs - they are reserved for
|
||||
// internal Tron use.
|
||||
RESERVED_FOR_LOGBUILDER_BUCKET = 801;
|
||||
RESERVED_FOR_LOGBUILDER_VALUE = 802;
|
||||
RESERVED_FOR_LOGBUILDER_COUNTER = 803;
|
||||
RESERVED_FOR_LOGBUILDER_HISTOGRAM = 804;
|
||||
RESERVED_FOR_LOGBUILDER_TIMESTAMP = 805;
|
||||
RESERVED_FOR_LOGBUILDER_PACKAGENAME = 806;
|
||||
|
||||
// ---- End O Constants, all O constants go above this line ----
|
||||
|
||||
// Add new aosp constants above this line.
|
||||
// END OF AOSP CONSTANTS
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user