Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 813552cc authored by John Spurlock's avatar John Spurlock
Browse files

When dozing, re-enable falsing threshold and log events.

- Reactivate our configured keyguard falsing swipe threshold
  for secure keyguards, but only when dozing.
- Add DozeLog helper to capture/maintain interesting events
  about the doze + unlock process, enabled by default, but
  only on devices that start dozing at least once.
- Dump summary counts + logged events to dumpsys output.
- Pass notification pulse "instance" as an extra to the scheduled
  intent, so we can log accordingly.

Bug:17496795
Change-Id: I7e88f93bfc967bdc06550cf1fe5e74d535edd774
parent 7bfa3574
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ public class KeyguardUpdateMonitorCallback {
    /**
     * Called when the emergency call button is pressed.
     */
    void onEmergencyCallAction() { }
    public void onEmergencyCallAction() { }

    /**
     * Called when the transport background changes.
+211 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.doze;

import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.util.TimeUtils;

import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;

import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DozeLog {
    private static final String TAG = "DozeLog";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean ENABLED = true;
    private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");

    private static long[] sTimes;
    private static String[] sMessages;
    private static int sPosition;
    private static int sCount;
    private static boolean sPulsing;

    private static long sSince;
    private static SummaryStats sPickupPulseNearVibrationStats;
    private static SummaryStats sPickupPulseNotNearVibrationStats;
    private static SummaryStats sNotificationPulseStats;
    private static SummaryStats sScreenOnPulsingStats;
    private static SummaryStats sScreenOnNotPulsingStats;
    private static SummaryStats sEmergencyCallStats;

    public static void tracePickupPulse(boolean withinVibrationThreshold) {
        if (!ENABLED) return;
        log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
        (withinVibrationThreshold ? sPickupPulseNearVibrationStats
                : sPickupPulseNotNearVibrationStats).append();
    }

    public static void tracePulseStart() {
        if (!ENABLED) return;
        sPulsing = true;
        log("pulseStart");
    }

    public static void tracePulseFinish() {
        if (!ENABLED) return;
        sPulsing = false;
        log("pulseFinish");
    }

    public static void traceNotificationPulse(long instance) {
        if (!ENABLED) return;
        log("notificationPulse instance=" + instance);
        sNotificationPulseStats.append();
    }

    public static void traceDozing(Context context, boolean dozing) {
        if (!ENABLED) return;
        sPulsing = false;
        synchronized (DozeLog.class) {
            if (dozing && sMessages == null) {
                sTimes = new long[SIZE];
                sMessages = new String[SIZE];
                sSince = System.currentTimeMillis();
                sPickupPulseNearVibrationStats = new SummaryStats();
                sPickupPulseNotNearVibrationStats = new SummaryStats();
                sNotificationPulseStats = new SummaryStats();
                sScreenOnPulsingStats = new SummaryStats();
                sScreenOnNotPulsingStats = new SummaryStats();
                sEmergencyCallStats = new SummaryStats();
                log("init");
                KeyguardUpdateMonitor.getInstance(context)
                        .registerCallback(new KeyguardUpdateMonitorCallback() {
                    @Override
                    public void onEmergencyCallAction() {
                        traceEmergencyCall();
                    }
                    @Override
                    public void onKeyguardBouncerChanged(boolean bouncer) {
                        traceKeyguardBouncerChanged(bouncer);
                    }
                    @Override
                    public void onScreenTurnedOn() {
                        traceScreenOn();
                    }
                    @Override
                    public void onScreenTurnedOff(int why) {
                        traceScreenOff(why);
                    }
                    @Override
                    public void onKeyguardVisibilityChanged(boolean showing) {
                        traceKeyguard(showing);
                    }
                });
            }
        }
        log("dozing " + dozing);
    }

    public static void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded) {
        if (!ENABLED) return;
        log("fling expand=" + expand + " aboveThreshold=" + aboveThreshold + " thresholdNeeded="
                + thresholdNeeded);
    }

    public static void traceEmergencyCall() {
        if (!ENABLED) return;
        log("emergencyCall");
    }

    public static void traceKeyguardBouncerChanged(boolean showing) {
        if (!ENABLED) return;
        log("bouncer " + showing);
    }

    public static void traceScreenOn() {
        if (!ENABLED) return;
        log("screenOn pulsing=" + sPulsing);
        (sPulsing ? sScreenOnPulsingStats : sScreenOnNotPulsingStats).append();
        sPulsing = false;
    }

    public static void traceScreenOff(int why) {
        if (!ENABLED) return;
        log("screenOff why=" + why);
    }

    public static void traceKeyguard(boolean showing) {
        if (!ENABLED) return;
        log("keyguard " + showing);
        if (!showing) {
            sPulsing = false;
        }
    }

    public static void dump(PrintWriter pw) {
        synchronized (DozeLog.class) {
            if (sMessages == null) return;
            pw.println("  Doze log:");
            final int start = (sPosition - sCount + SIZE) % SIZE;
            for (int i = 0; i < sCount; i++) {
                final int j = (start + i) % SIZE;
                pw.print("    ");
                pw.print(FORMAT.format(new Date(sTimes[j])));
                pw.print(' ');
                pw.println(sMessages[j]);
            }
            pw.print("  Doze summary stats (for ");
            TimeUtils.formatDuration(System.currentTimeMillis() - sSince, pw);
            pw.println("):");
            sPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)");
            sPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)");
            sNotificationPulseStats.dump(pw, "Notification pulse");
            sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
            sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
            sEmergencyCallStats.dump(pw, "Emergency call");
        }
    }

    private static void log(String msg) {
        synchronized (DozeLog.class) {
            if (sMessages == null) return;
            sTimes[sPosition] = System.currentTimeMillis();
            sMessages[sPosition] = msg;
            sPosition = (sPosition + 1) % SIZE;
            sCount = Math.min(sCount + 1, SIZE);
        }
        if (DEBUG) Log.d(TAG, msg);
    }

    private static class SummaryStats {
        private int mCount;

        public void append() {
            mCount++;
        }

        public void dump(PrintWriter pw, String type) {
            pw.print("    ");
            pw.print(type);
            pw.print(": n=");
            pw.print(mCount);
            pw.print(" (");
            final double perHr = (double) mCount / (System.currentTimeMillis() - sSince)
                    * 1000 * 60 * 60;
            pw.print(perHr);
            pw.print("/hr)");
            pw.println();
        }
    }
}
+23 −9
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ public class DozeService extends DreamService {
    private static final String ACTION_BASE = "com.android.systemui.doze";
    private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
    private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse";
    private static final String EXTRA_INSTANCE = "instance";

    private final String mTag = String.format(TAG + ".%08x", hashCode());
    private final Context mContext = this;
@@ -67,7 +68,6 @@ public class DozeService extends DreamService {
    private boolean mDisplayStateSupported;
    private int mDisplayStateWhenOn;
    private boolean mNotificationLightOn;
    private PendingIntent mNotificationPulseIntent;
    private boolean mPowerSaveActive;
    private long mNotificationPulseTime;
    private int mScheduleResetsRemaining;
@@ -115,9 +115,6 @@ public class DozeService extends DreamService {
        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        mDisplayStateSupported = mDozeParameters.getDisplayStateSupported();
        mNotificationPulseIntent = PendingIntent.getBroadcast(mContext, 0,
                new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName()),
                PendingIntent.FLAG_UPDATE_CURRENT);
        mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON;
        mDisplayOff.run();
    }
@@ -257,9 +254,17 @@ public class DozeService extends DreamService {
        rescheduleNotificationPulse(true /*predicate*/);
    }

    private PendingIntent notificationPulseIntent(long instance) {
        return PendingIntent.getBroadcast(mContext, 0,
                new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName())
                        .putExtra(EXTRA_INSTANCE, instance),
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private void rescheduleNotificationPulse(boolean predicate) {
        if (DEBUG) Log.d(TAG, "rescheduleNotificationPulse predicate=" + predicate);
        mAlarmManager.cancel(mNotificationPulseIntent);
        final PendingIntent notificationPulseIntent = notificationPulseIntent(0);
        mAlarmManager.cancel(notificationPulseIntent);
        if (!predicate) {
            if (DEBUG) Log.d(TAG, "  don't reschedule: predicate is false");
            return;
@@ -280,8 +285,10 @@ public class DozeService extends DreamService {
            if (DEBUG) Log.d(TAG, "  don't reschedule: delta is " + delta);
            return;
        }
        if (DEBUG) Log.d(TAG, "Scheduling pulse in " + delta + "ms for " + new Date(time));
        mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, mNotificationPulseIntent);
        final long instance = time - mNotificationPulseTime;
        if (DEBUG) Log.d(TAG, "Scheduling pulse " + instance + " in " + delta + "ms for "
                + new Date(time));
        mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, notificationPulseIntent(instance));
    }

    private static String triggerEventToString(TriggerEvent event) {
@@ -313,7 +320,9 @@ public class DozeService extends DreamService {
                requestPulse();
            }
            if (NOTIFICATION_PULSE_ACTION.equals(intent.getAction())) {
                if (DEBUG) Log.d(mTag, "Received notification pulse intent");
                final long instance = intent.getLongExtra(EXTRA_INSTANCE, -1);
                if (DEBUG) Log.d(mTag, "Received notification pulse intent instance=" + instance);
                DozeLog.traceNotificationPulse(instance);
                requestPulse();
                rescheduleNotificationPulse(mNotificationLightOn);
            }
@@ -415,11 +424,16 @@ public class DozeService extends DreamService {
            // reset the notification pulse schedule, but only if we think we were not triggered
            // by a notification-related vibration
            final long timeSinceNotification = System.currentTimeMillis() - mNotificationPulseTime;
            if (timeSinceNotification < mDozeParameters.getPickupVibrationThreshold()) {
            final boolean withinVibrationThreshold =
                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
            if (withinVibrationThreshold) {
               if (DEBUG) Log.d(mTag, "Not resetting schedule, recent notification");
            } else {
                resetNotificationResets();
            }
            if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                DozeLog.tracePickupPulse(withinVibrationThreshold);
            }
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.view.animation.Interpolator;
import android.widget.FrameLayout;

import com.android.systemui.R;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;

@@ -347,6 +348,8 @@ public abstract class PanelView extends FrameLayout {
                    if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD) {
                        Log.i(TAG, "Flinging: expand=" + expand);
                    }
                    DozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
                            mStatusBar.isFalsingThresholdNeeded());
                    fling(vel, expand);
                    mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown;
                    if (mUpdateFlingOnLayout) {
+7 −2
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ import com.android.systemui.DemoMode;
import com.android.systemui.EventLogTags;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeService;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.qs.QSPanel;
@@ -2101,8 +2102,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,

    public boolean isFalsingThresholdNeeded() {
        boolean onKeyguard = getBarState() == StatusBarState.KEYGUARD;
        boolean isMethodInSecure = mUnlockMethodCache.isMethodInsecure();
        return onKeyguard && isMethodInSecure;
        boolean isMethodInsecure = mUnlockMethodCache.isMethodInsecure();
        return onKeyguard && (isMethodInsecure || mDozing);
    }

    @Override  // NotificationData.Environment
@@ -2874,6 +2875,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
            mNotificationPanel.dump(fd, pw, args);
        }

        DozeLog.dump(pw);

        if (DUMPTRUCK) {
            synchronized (mNotificationData) {
                mNotificationData.dump(pw, "  ");
@@ -4108,6 +4111,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
            mCurrentDozeService = dozeService;
            if (!mDozing) {
                mDozing = true;
                DozeLog.traceDozing(mContext, mDozing);
                updateDozingState();
            }
            mCurrentDozeService.startDozing();
@@ -4125,6 +4129,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
            }
            if (mDozing) {
                mDozing = false;
                DozeLog.traceDozing(mContext, mDozing);
                updateDozingState();
            }
        }
Loading