Home | History | Annotate | Download | only in keyguard
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.keyguard;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.os.Build;
     24 import android.os.SystemClock;
     25 import android.os.SystemProperties;
     26 import android.os.Trace;
     27 import android.util.EventLog;
     28 import android.util.Log;
     29 import android.util.SparseLongArray;
     30 
     31 import com.android.systemui.EventLogTags;
     32 
     33 /**
     34  * Class to track various latencies in SystemUI. It then outputs the latency to logcat so these
     35  * latencies can be captured by tests and then used for dashboards.
     36  * <p>
     37  * This is currently only in Keyguard so it can be shared between SystemUI and Keyguard, but
     38  * eventually we'd want to merge these two packages together so Keyguard can use common classes
     39  * that are shared with SystemUI.
     40  */
     41 public class LatencyTracker {
     42 
     43     private static final String ACTION_RELOAD_PROPERTY =
     44             "com.android.systemui.RELOAD_LATENCY_TRACKER_PROPERTY";
     45 
     46     private static final String TAG = "LatencyTracker";
     47 
     48     /**
     49      * Time it takes until the first frame of the notification panel to be displayed while expanding
     50      */
     51     public static final int ACTION_EXPAND_PANEL = 0;
     52 
     53     /**
     54      * Time it takes until the first frame of recents is drawn after invoking it with the button.
     55      */
     56     public static final int ACTION_TOGGLE_RECENTS = 1;
     57 
     58     /**
     59      * Time between we get a fingerprint acquired signal until we start with the unlock animation
     60      */
     61     public static final int ACTION_FINGERPRINT_WAKE_AND_UNLOCK = 2;
     62 
     63     /**
     64      * Time it takes to check PIN/Pattern/Password.
     65      */
     66     public static final int ACTION_CHECK_CREDENTIAL = 3;
     67 
     68     /**
     69      * Time it takes to check fully PIN/Pattern/Password, i.e. that's the time spent including the
     70      * actions to unlock a user.
     71      */
     72     public static final int ACTION_CHECK_CREDENTIAL_UNLOCKED = 4;
     73 
     74     /**
     75      * Time it takes to turn on the screen.
     76      */
     77     public static final int ACTION_TURN_ON_SCREEN = 5;
     78 
     79     private static final String[] NAMES = new String[] {
     80             "expand panel",
     81             "toggle recents",
     82             "fingerprint wake-and-unlock",
     83             "check credential",
     84             "check credential unlocked",
     85             "turn on screen" };
     86 
     87     private static LatencyTracker sLatencyTracker;
     88 
     89     private final SparseLongArray mStartRtc = new SparseLongArray();
     90     private boolean mEnabled;
     91 
     92     public static LatencyTracker getInstance(Context context) {
     93         if (sLatencyTracker == null) {
     94             sLatencyTracker = new LatencyTracker(context);
     95         }
     96         return sLatencyTracker;
     97     }
     98 
     99     private LatencyTracker(Context context) {
    100         context.registerReceiver(new BroadcastReceiver() {
    101             @Override
    102             public void onReceive(Context context, Intent intent) {
    103                 reloadProperty();
    104             }
    105         }, new IntentFilter(ACTION_RELOAD_PROPERTY));
    106         reloadProperty();
    107     }
    108 
    109     private void reloadProperty() {
    110         mEnabled = SystemProperties.getBoolean("debug.systemui.latency_tracking", false);
    111     }
    112 
    113     public static boolean isEnabled(Context ctx) {
    114         return Build.IS_DEBUGGABLE && getInstance(ctx).mEnabled;
    115     }
    116 
    117     /**
    118      * Notifies that an action is starting. This needs to be called from the main thread.
    119      *
    120      * @param action The action to start. One of the ACTION_* values.
    121      */
    122     public void onActionStart(int action) {
    123         if (!mEnabled) {
    124             return;
    125         }
    126         Trace.asyncTraceBegin(Trace.TRACE_TAG_APP, NAMES[action], 0);
    127         mStartRtc.put(action, SystemClock.elapsedRealtime());
    128     }
    129 
    130     /**
    131      * Notifies that an action has ended. This needs to be called from the main thread.
    132      *
    133      * @param action The action to end. One of the ACTION_* values.
    134      */
    135     public void onActionEnd(int action) {
    136         if (!mEnabled) {
    137             return;
    138         }
    139         long endRtc = SystemClock.elapsedRealtime();
    140         long startRtc = mStartRtc.get(action, -1);
    141         if (startRtc == -1) {
    142             return;
    143         }
    144         mStartRtc.delete(action);
    145         Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0);
    146         long duration = endRtc - startRtc;
    147         Log.i(TAG, "action=" + action + " latency=" + duration);
    148         EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, (int) duration);
    149     }
    150 }
    151