create a metrics log reader for tests

Add parallel logs using the new format for the old MetricsLogger
calls. Deduplicate these after the new reader implementation is
complete.

Test: ./vendor/google/tools/systemui/systemui_test_cookbook.sh
Change-Id: If12e1b66b0ec5ac23bd65e44df4f3c6d6931e722
This commit is contained in:
Chris Wren
2016-11-29 10:43:28 -05:00
parent c45df0d7c1
commit 26ca65d425
47 changed files with 4032 additions and 19 deletions

View File

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

View File

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

View 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();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View 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;
}
}