From 27a52fa86bd279407575192fc9842b6a54624cfb Mon Sep 17 00:00:00 2001 From: Chris Wren Date: Wed, 1 Feb 2017 14:21:43 -0500 Subject: [PATCH] port status bar logs to Tron V2 Bug: 33303260 Test: runtest --path frameworks/base/core/tests/coretests/src/com/android/internal/logging/legacy/ && runtest --path frameworks/base/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone Change-Id: I7746b846247e930617f0b440217635e71ed58bb5 --- .../logging/legacy/EventLogCollector.java | 2 - .../legacy/LegacyConversionLogger.java | 8 -- .../legacy/LockscreenGestureParser.java | 80 ----------- .../logging/legacy/StatusBarStateParser.java | 74 ---------- .../legacy/LockscreenGestureParserTest.java | 100 ------------- .../legacy/StatusBarStateParserTest.java | 73 ---------- .../android/systemui/EventLogConstants.java | 36 +++-- .../phone/KeyguardBottomAreaView.java | 6 +- .../phone/LockscreenGestureLogger.java | 59 ++++++++ .../phone/NotificationPanelView.java | 24 ++-- .../systemui/statusbar/phone/PanelView.java | 6 +- .../systemui/statusbar/phone/StatusBar.java | 20 ++- packages/SystemUI/tests/Android.mk | 1 + .../statusbar/phone/StatusBarTest.java | 133 +++++++++++++++++- proto/src/metrics_constants.proto | 14 +- 15 files changed, 262 insertions(+), 374 deletions(-) delete mode 100644 core/java/com/android/internal/logging/legacy/LockscreenGestureParser.java delete mode 100644 core/java/com/android/internal/logging/legacy/StatusBarStateParser.java delete mode 100644 core/tests/coretests/src/com/android/internal/logging/legacy/LockscreenGestureParserTest.java delete mode 100644 core/tests/coretests/src/com/android/internal/logging/legacy/StatusBarStateParserTest.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java diff --git a/core/java/com/android/internal/logging/legacy/EventLogCollector.java b/core/java/com/android/internal/logging/legacy/EventLogCollector.java index 46e70ea9bf7e5..598f0d51c1b95 100644 --- a/core/java/com/android/internal/logging/legacy/EventLogCollector.java +++ b/core/java/com/android/internal/logging/legacy/EventLogCollector.java @@ -45,8 +45,6 @@ public class EventLogCollector { private EventLogCollector() { mTagParsers = new ArrayMap<>(); - addParser(new LockscreenGestureParser()); - addParser(new StatusBarStateParser()); addParser(new PowerScreenStateParser()); addParser(new SysuiMultiActionParser()); diff --git a/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java b/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java index 91e968b5b250d..1209e4d8dc8ce 100644 --- a/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java +++ b/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java @@ -24,14 +24,6 @@ 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 mQueue; private HashMap mConfig; diff --git a/core/java/com/android/internal/logging/legacy/LockscreenGestureParser.java b/core/java/com/android/internal/logging/legacy/LockscreenGestureParser.java deleted file mode 100644 index df08ee0670873..0000000000000 --- a/core/java/com/android/internal/logging/legacy/LockscreenGestureParser.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 android.metrics.LogMaker; -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) { - LogMaker 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); - } - } -} diff --git a/core/java/com/android/internal/logging/legacy/StatusBarStateParser.java b/core/java/com/android/internal/logging/legacy/StatusBarStateParser.java deleted file mode 100644 index 226253f3322fc..0000000000000 --- a/core/java/com/android/internal/logging/legacy/StatusBarStateParser.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 android.metrics.LogMaker; -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; - } - - LogMaker 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); - } - } -} diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/LockscreenGestureParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/LockscreenGestureParserTest.java deleted file mode 100644 index c023b572493fa..0000000000000 --- a/core/tests/coretests/src/com/android/internal/logging/legacy/LockscreenGestureParserTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 android.metrics.LogMaker; -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()); - - LogMaker 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((LogMaker) anyObject()); - } -} diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/StatusBarStateParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/StatusBarStateParserTest.java deleted file mode 100644 index def9628e7fbd9..0000000000000 --- a/core/tests/coretests/src/com/android/internal/logging/legacy/StatusBarStateParserTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 android.metrics.LogMaker; -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()); - - LogMaker proto = mProtoCaptor.getValue(); - assertEquals(t, proto.getTimestamp()); - assertEquals(view, proto.getCategory()); - assertEquals(type, proto.getType()); - assertEquals(subType, proto.getSubtype()); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java index 9238928de9e22..def3c4072d2e0 100644 --- a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java +++ b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java @@ -16,30 +16,46 @@ package com.android.systemui; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + /** * Constants to be passed as sysui_* eventlog parameters. */ public class EventLogConstants { /** The user swiped up on the lockscreen, unlocking the device. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK = 1; + private static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK = 1; /** The user swiped down on the lockscreen, going to the full shade. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE = 2; + private static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE = 2; /** The user tapped in an empty area, causing the unlock hint to be shown. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT = 3; + private static final int SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT = 3; /** The user swiped inward on the camera icon, launching the camera. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA = 4; + private static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA = 4; /** The user swiped inward on the dialer icon, launching the dialer. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER = 5; + private static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER = 5; /** The user tapped the lock, locking the device. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6; + private static final int SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6; /** The user tapped a notification, needs to tap again to launch. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7; + private static final int SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7; /** The user swiped down to open quick settings, from keyguard. */ - public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS = 8; + private static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS = 8; /** The user swiped down to open quick settings, from shade. */ - public static final int SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS = 9; + private static final int SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS = 9; /** The user tapped on the status bar to open quick settings, from shade. */ - public static final int SYSUI_TAP_TO_OPEN_QS = 10; + private static final int SYSUI_TAP_TO_OPEN_QS = 10; + + public static final int[] METRICS_GESTURE_TYPE_MAP = { + MetricsEvent.VIEW_UNKNOWN, // there is no type 0 + MetricsEvent.ACTION_LS_UNLOCK, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK + MetricsEvent.ACTION_LS_SHADE, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE + MetricsEvent.ACTION_LS_HINT, // SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT + MetricsEvent.ACTION_LS_CAMERA, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA + MetricsEvent.ACTION_LS_DIALER, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER + MetricsEvent.ACTION_LS_LOCK, // SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK + MetricsEvent.ACTION_LS_NOTE, // SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE + MetricsEvent.ACTION_LS_QS, // SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS + MetricsEvent.ACTION_SHADE_QS_PULL, // SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS + MetricsEvent.ACTION_SHADE_QS_TAP // SYSUI_TAP_TO_OPEN_QS + }; /** Secondary user tries binding to the system sysui service */ public static final int SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE = 1; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index bfc0a80b31502..d27f38e712370 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -35,6 +35,7 @@ import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.AssetFileDescriptor.AutoCloseOutputStream; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.AsyncTask; @@ -58,6 +59,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; @@ -164,6 +166,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private IntentButton mLeftDefault = mLeftButton; private IntentButton mLeftPlugin; private String mLeftButtonStr; + private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); public KeyguardBottomAreaView(Context context) { this(context, null); @@ -445,8 +448,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private void handleTrustCircleClick() { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK, 0 /* lengthDp - N/A */, + mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_LOCK, 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); mIndicationController.showTransientIndication( R.string.keyguard_indication_trust_disabled); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java new file mode 100644 index 0000000000000..83b96bfc4faf8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java @@ -0,0 +1,59 @@ +/* + * 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.systemui.statusbar.phone; + +import android.metrics.LogMaker; +import android.util.ArrayMap; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.EventLogConstants; +import com.android.systemui.EventLogTags; + +/** + * Wrapper that emits both new- and old-style gesture logs. + * TODO: delete this once the old logs are no longer needed. + */ +public class LockscreenGestureLogger { + private ArrayMap mLegacyMap; + private LogMaker mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN) + .setType(MetricsEvent.TYPE_ACTION); + + public LockscreenGestureLogger() { + mLegacyMap = new ArrayMap<>(EventLogConstants.METRICS_GESTURE_TYPE_MAP.length); + for (int i = 0; i < EventLogConstants.METRICS_GESTURE_TYPE_MAP.length ; i++) { + mLegacyMap.put(EventLogConstants.METRICS_GESTURE_TYPE_MAP[i], i); + } + } + + public void write(int gesture, int length, int velocity) { + MetricsLogger.action(mLogMaker.setCategory(gesture) + .setType(MetricsEvent.TYPE_ACTION) + .addTaggedData(MetricsEvent.FIELD_GESTURE_LENGTH, length) + .addTaggedData(MetricsEvent.FIELD_GESTURE_VELOCITY, velocity)); + // also write old-style logs for backward-0compatibility + EventLogTags.writeSysuiLockscreenGesture(safeLookup(gesture), length, velocity); + } + + private int safeLookup(int gesture) { + Integer value = mLegacyMap.get(gesture); + if (value == null) { + return MetricsEvent.VIEW_UNKNOWN; + } + return value; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index fe7e915f42f6a..ffd1d800fb414 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -43,6 +43,7 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.DejankUtils; import com.android.systemui.EventLogConstants; @@ -212,6 +213,7 @@ public class NotificationPanelView extends PanelView implements private int mIndicationBottomPadding; private boolean mIsFullWidth; private boolean mDark; + private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -710,10 +712,9 @@ public class NotificationPanelView extends PanelView implements private void logQsSwipeDown(float y) { float vel = getCurrentQSVelocity(); final int gesture = mStatusBarState == StatusBarState.KEYGUARD - ? EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS - : EventLogConstants.SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS; - EventLogTags.writeSysuiLockscreenGesture( - gesture, + ? MetricsEvent.ACTION_LS_QS + : MetricsEvent.ACTION_SHADE_QS_PULL; + mLockscreenGestureLogger.write(gesture, (int) ((y - mInitialTouchY) / mStatusBar.getDisplayDensity()), (int) (vel / mStatusBar.getDisplayDensity())); } @@ -1819,9 +1820,7 @@ public class NotificationPanelView extends PanelView implements if (mQsExpanded) { flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */); } else if (mQsExpansionEnabled) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_TAP_TO_OPEN_QS, - 0, 0); + mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0); flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */); } } @@ -1836,8 +1835,7 @@ public class NotificationPanelView extends PanelView implements int lengthDp = Math.abs((int) (translation / displayDensity)); int velocityDp = Math.abs((int) (vel / displayDensity)); if (start) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp); + mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp); mFalsingManager.onLeftAffordanceOn(); if (mFalsingManager.shouldEnforceBouncer()) { @@ -1855,9 +1853,7 @@ public class NotificationPanelView extends PanelView implements } else { if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals( mLastCameraLaunchSource)) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, - lengthDp, velocityDp); + mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp); } mFalsingManager.onCameraOn(); if (mFalsingManager.shouldEnforceBouncer()) { @@ -2152,8 +2148,8 @@ public class NotificationPanelView extends PanelView implements switch (mStatusBar.getBarState()) { case StatusBarState.KEYGUARD: if (!mDozingOnDown) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT, + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_HINT, 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); startUnlockHintAnimation(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 5f674685f885c..fa74cc183b78f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -33,6 +33,7 @@ import android.view.ViewTreeObserver; import android.view.animation.Interpolator; import android.widget.FrameLayout; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.DejankUtils; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; @@ -55,6 +56,7 @@ public abstract class PanelView extends FrameLayout { private static final int PEEK_ANIMATION_DURATION = 360; private long mDownTime; private float mMinExpandHeight; + private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); @@ -423,8 +425,8 @@ public abstract class PanelView extends FrameLayout { float displayDensity = mStatusBar.getDisplayDensity(); int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity); int velocityDp = (int) Math.abs(vel / displayDensity); - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK, + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp); } fling(vel, expand, isFalseTouch(x, y)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 270476e35307e..b385835eda49f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -69,6 +69,7 @@ import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; +import android.metrics.LogMaker; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; @@ -406,7 +407,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected PhoneStatusBarView mStatusBarView; private int mStatusBarWindowState = WINDOW_STATE_SHOWING; protected StatusBarWindowManager mStatusBarWindowManager; - private UnlockMethodCache mUnlockMethodCache; + protected UnlockMethodCache mUnlockMethodCache; private DozeServiceHost mDozeServiceHost; private boolean mWakeUpComingFromTouch; private PointF mWakeUpTouchLocation; @@ -706,6 +707,8 @@ public class StatusBar extends SystemUI implements DemoMode, private NetworkController mNetworkController; private KeyguardMonitorImpl mKeyguardMonitor; private BatteryController mBatteryController; + private LogMaker mStatusBarStateLog; + private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private void recycleAllVisibilityObjects(ArraySet array) { final int N = array.size(); @@ -3828,6 +3831,13 @@ public class StatusBar extends SystemUI implements DemoMode, isSecure, canSkipBouncer); if (stateFingerprint != mLastLoggedStateFingerprint) { + if (mStatusBarStateLog == null) { + mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); + } + MetricsLogger.action(mStatusBarStateLog + .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) + .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) + .setSubtype(isSecure ? 1 : 0)); EventLogTags.writeSysuiStatusBarState(mState, isShowing ? 1 : 0, isOccluded ? 1 : 0, @@ -4508,8 +4518,8 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onActivated(ActivatableNotificationView view) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE, + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_NOTE, 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); @@ -4626,8 +4636,8 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public boolean onDraggedDown(View startingChild, int dragLengthY) { if (hasActiveNotifications() && (!isDozing() || isPulsing())) { - EventLogTags.writeSysuiLockscreenGesture( - EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE, + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_SHADE, (int) (dragLengthY / mDisplayMetrics.density), 0 /* velocityDp - N/A */); diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index c627e224dee87..cefade086795a 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -43,6 +43,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \ android-support-v17-leanback LOCAL_STATIC_JAVA_LIBRARIES := \ + metrics-helper-lib \ android-support-test \ mockito-updated-target-minus-junit4 \ SystemUI-proto \ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 309559b6b3ff2..21c7fce445796 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -22,11 +22,20 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.metrics.LogMaker; +import android.metrics.MetricsReader; import android.support.test.filters.SmallTest; +import android.support.test.metricshelper.MetricsAsserts; import android.support.test.runner.AndroidJUnit4; +import android.util.DisplayMetrics; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.ActivatableNotificationView; +import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import org.junit.Before; import org.junit.Test; @@ -37,12 +46,22 @@ import org.junit.runner.RunWith; public class StatusBarTest extends SysuiTestCase { StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + UnlockMethodCache mUnlockMethodCache; + KeyguardIndicationController mKeyguardIndicationController; + NotificationStackScrollLayout mStackScroller; StatusBar mStatusBar; + private MetricsReader mMetricsReader; + private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); + @Before public void setup() { mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class); - mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager); + mUnlockMethodCache = mock(UnlockMethodCache.class); + mKeyguardIndicationController = mock(KeyguardIndicationController.class); + mStackScroller = mock(NotificationStackScrollLayout.class); + mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache, + mKeyguardIndicationController, mStackScroller); doAnswer(invocation -> { OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0]; @@ -55,6 +74,11 @@ public class StatusBarTest extends SysuiTestCase { runnable.run(); return null; }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any()); + + when(mStackScroller.getActivatedChild()).thenReturn(null); + + mMetricsReader = new MetricsReader(); + mMetricsReader.checkpoint(); // clear out old logs } @Test @@ -81,9 +105,114 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false); } + @Test + public void lockscreenStateMetrics_notShowing() { + // uninteresting state, except that fingerprint must be non-zero + when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false); + when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true); + // interesting state + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + when(mUnlockMethodCache.isMethodSecure()).thenReturn(false); + + mStatusBar.onKeyguardViewManagerStatesUpdated(); + + MetricsAsserts.assertHasLog("missing hidden insecure lockscreen log", mMetricsReader, + new LogMaker(MetricsEvent.LOCKSCREEN) + .setType(MetricsEvent.TYPE_CLOSE) + .setSubtype(0)); + } + + @Test + public void lockscreenStateMetrics_notShowing_secure() { + // uninteresting state, except that fingerprint must be non-zero + when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false); + when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true); + // interesting state + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + when(mUnlockMethodCache.isMethodSecure()).thenReturn(true); + + mStatusBar.onKeyguardViewManagerStatesUpdated(); + + MetricsAsserts.assertHasLog("missing hidden secure lockscreen log", mMetricsReader, + new LogMaker(MetricsEvent.LOCKSCREEN) + .setType(MetricsEvent.TYPE_CLOSE) + .setSubtype(1)); + } + + @Test + public void lockscreenStateMetrics_isShowing() { + // uninteresting state, except that fingerprint must be non-zero + when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false); + when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true); + // interesting state + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + when(mUnlockMethodCache.isMethodSecure()).thenReturn(false); + + mStatusBar.onKeyguardViewManagerStatesUpdated(); + + MetricsAsserts.assertHasLog("missing insecure lockscreen showing", mMetricsReader, + new LogMaker(MetricsEvent.LOCKSCREEN) + .setType(MetricsEvent.TYPE_OPEN) + .setSubtype(0)); + } + + @Test + public void lockscreenStateMetrics_isShowing_secure() { + // uninteresting state, except that fingerprint must be non-zero + when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false); + when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true); + // interesting state + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + when(mUnlockMethodCache.isMethodSecure()).thenReturn(true); + + mStatusBar.onKeyguardViewManagerStatesUpdated(); + + MetricsAsserts.assertHasLog("missing secure lockscreen showing log", mMetricsReader, + new LogMaker(MetricsEvent.LOCKSCREEN) + .setType(MetricsEvent.TYPE_OPEN) + .setSubtype(1)); + } + + @Test + public void lockscreenStateMetrics_isShowingBouncer() { + // uninteresting state, except that fingerprint must be non-zero + when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false); + when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true); + // interesting state + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true); + when(mUnlockMethodCache.isMethodSecure()).thenReturn(true); + + mStatusBar.onKeyguardViewManagerStatesUpdated(); + + MetricsAsserts.assertHasLog("missing bouncer log", mMetricsReader, + new LogMaker(MetricsEvent.BOUNCER) + .setType(MetricsEvent.TYPE_OPEN) + .setSubtype(1)); + } + + @Test + public void onActivatedMetrics() { + ActivatableNotificationView view = mock(ActivatableNotificationView.class); + mStatusBar.onActivated(view); + + MetricsAsserts.assertHasLog("missing lockscreen note tap log", mMetricsReader, + new LogMaker(MetricsEvent.ACTION_LS_NOTE) + .setType(MetricsEvent.TYPE_ACTION)); + } + static class TestableStatusBar extends StatusBar { - public TestableStatusBar(StatusBarKeyguardViewManager man) { + public TestableStatusBar(StatusBarKeyguardViewManager man, + UnlockMethodCache unlock, KeyguardIndicationController key, + NotificationStackScrollLayout stack) { mStatusBarKeyguardViewManager = man; + mUnlockMethodCache = unlock; + mKeyguardIndicationController = key; + mStackScroller = stack; } @Override diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 59d982a5286f7..a590805cf7457 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3275,7 +3275,6 @@ message MetricsEvent { // OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791; - // OPEN: Settings > Apps > Default Apps > Default autofill app DEFAULT_AUTOFILL_PICKER = 792; @@ -3352,7 +3351,8 @@ message MetricsEvent { BACKUP_SETTINGS = 818; // ACTION: Picture-in-picture was explicitly entered for an activity - // VALUE: true if it was entered while hiding as a result of moving to another task, false otherwise + // VALUE: true if it was entered while hiding as a result of moving to + // another task, false otherwise ACTION_PICTURE_IN_PICTURE_ENTERED = 819; // ACTION: The activity currently in picture-in-picture was expanded back to fullscreen @@ -3378,6 +3378,16 @@ message MetricsEvent { // The current aspect ratio of the PiP, logged when it changes. PICTURE_IN_PICTURE_ASPECT_RATIO = 825; + // FIELD - length in dp of ACTION_LS_* gestures, or zero if not applicable + // CATEGORY: GLOBAL_SYSTEM_UI + // OS: O + FIELD_GESTURE_LENGTH = 826; + + // FIELD - velocity in dp (per second?) of ACTION_LS_* gestures, or zero if not applicable + // CATEGORY: GLOBAL_SYSTEM_UI + // OS: O + FIELD_GESTURE_VELOCITY = 827; + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line.