Add stats logging to ServiceManager and NPMS

ServiceManager:
- Do an event log every N getService() calls with total time spent
in getService().
where N = 100 for core UIDs and 200 for other apps.

- Do an event log if getService() takes longer than N ms.
where N = 10 for core UIDs and 50 for other apps.

... with some extra throttling.

NPMS:
- Do the basic "stats logger" log for updateNetworkEnabledNL() and
isUidNetworkingBlocked()

This CL also enhances StatsLogegr so it now can show the slowest call
and the max # of calls per-second.

Bug: 77853238
Test: Manual test:
- Insert a SIM card
- Set data limit
- toggle airplane mode
- toggle wifi
- toggle mobile data

Then
- "dumpsys netpolicy" and "dumpsys activity processes" and check the stats
- also check "adb logcat -b all | grep ' service_manager'"

Change-Id: I5789541063f95d0eac501189816c8604a4571ba0
diff --git a/Android.bp b/Android.bp
index 9c76e14..22fe23d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -603,6 +603,7 @@
         "core/java/android/content/EventLogTags.logtags",
         "core/java/android/speech/tts/EventLogTags.logtags",
         "core/java/android/net/EventLogTags.logtags",
+        "core/java/android/os/EventLogTags.logtags",
         "core/java/android/webkit/EventLogTags.logtags",
         "core/java/com/android/internal/app/EventLogTags.logtags",
         "core/java/com/android/internal/logging/EventLogTags.logtags",
diff --git a/core/java/android/os/EventLogTags.logtags b/core/java/android/os/EventLogTags.logtags
new file mode 100644
index 0000000..b143a74
--- /dev/null
+++ b/core/java/android/os/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.os
+
+230000 service_manager_stats (call_count|1),(total_time|1|3),(duration|1|3)
+230001 service_manager_slow (time|1|3),(service|3)
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 3be76d6..165276d 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -18,7 +18,9 @@
 
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.util.StatLogger;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -26,9 +28,76 @@
 /** @hide */
 public final class ServiceManager {
     private static final String TAG = "ServiceManager";
+    private static final Object sLock = new Object();
+
     private static IServiceManager sServiceManager;
+
+    /**
+     * Cache for the "well known" services, such as WM and AM.
+     */
     private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
 
+    /**
+     * We do the "slow log" at most once every this interval.
+     */
+    private static final int SLOW_LOG_INTERVAL_MS = 5000;
+
+    /**
+     * We do the "stats log" at most once every this interval.
+     */
+    private static final int STATS_LOG_INTERVAL_MS = 5000;
+
+    /**
+     * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to
+     * avoid logspam.
+     */
+    private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE =
+            SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000;
+
+    /**
+     * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to
+     * avoid logspam.
+     */
+    private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE =
+            SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000;
+
+    /**
+     * We log stats logging ever this many getService() calls.
+     */
+    private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE =
+            SystemProperties.getInt("debug.servicemanager.log_calls_core", 100);
+
+    /**
+     * We log stats logging ever this many getService() calls.
+     */
+    private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE =
+            SystemProperties.getInt("debug.servicemanager.log_calls", 200);
+
+    @GuardedBy("sLock")
+    private static int sGetServiceAccumulatedUs;
+
+    @GuardedBy("sLock")
+    private static int sGetServiceAccumulatedCallCount;
+
+    @GuardedBy("sLock")
+    private static long sLastStatsLogUptime;
+
+    @GuardedBy("sLock")
+    private static long sLastSlowLogUptime;
+
+    @GuardedBy("sLock")
+    private static long sLastSlowLogActualTime;
+
+    interface Stats {
+        int GET_SERVICE = 0;
+
+        int COUNT = GET_SERVICE + 1;
+    }
+
+    public static final StatLogger sStatLogger = new StatLogger(new String[] {
+            "getService()",
+    });
+
     private static IServiceManager getIServiceManager() {
         if (sServiceManager != null) {
             return sServiceManager;
@@ -52,7 +121,7 @@
             if (service != null) {
                 return service;
             } else {
-                return Binder.allowBlocking(getIServiceManager().getService(name));
+                return Binder.allowBlocking(rawGetService(name));
             }
         } catch (RemoteException e) {
             Log.e(TAG, "error in getService", e);
@@ -177,4 +246,59 @@
             super("No service published for: " + name);
         }
     }
+
+    private static IBinder rawGetService(String name) throws RemoteException {
+        final long start = sStatLogger.getTime();
+
+        final IBinder binder = getIServiceManager().getService(name);
+
+        final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);
+
+        final int myUid = Process.myUid();
+        final boolean isCore = UserHandle.isCore(myUid);
+
+        final long slowThreshold = isCore
+                ? GET_SERVICE_SLOW_THRESHOLD_US_CORE
+                : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE;
+
+        synchronized (sLock) {
+            sGetServiceAccumulatedUs += time;
+            sGetServiceAccumulatedCallCount++;
+
+            final long nowUptime = SystemClock.uptimeMillis();
+
+            // Was a slow call?
+            if (time >= slowThreshold) {
+                // We do a slow log:
+                // - At most once in every SLOW_LOG_INTERVAL_MS
+                // - OR it was slower than the previously logged slow call.
+                if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS))
+                        || (sLastSlowLogActualTime < time)) {
+                    EventLogTags.writeServiceManagerSlow(time / 1000, name);
+
+                    sLastSlowLogUptime = nowUptime;
+                    sLastSlowLogActualTime = time;
+                }
+            }
+
+            // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService().
+
+            final int logInterval = isCore
+                    ? GET_SERVICE_LOG_EVERY_CALLS_CORE
+                    : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE;
+
+            if ((sGetServiceAccumulatedCallCount >= logInterval)
+                    && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) {
+
+                EventLogTags.writeServiceManagerStats(
+                        sGetServiceAccumulatedCallCount, // Total # of getService() calls.
+                        sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls.
+                        (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log.
+                sGetServiceAccumulatedCallCount = 0;
+                sGetServiceAccumulatedUs = 0;
+                sLastStatsLogUptime = nowUptime;
+            }
+        }
+        return binder;
+    }
 }
diff --git a/core/java/com/android/internal/util/StatLogger.java b/core/java/com/android/internal/util/StatLogger.java
new file mode 100644
index 0000000..1dac136
--- /dev/null
+++ b/core/java/com/android/internal/util/StatLogger.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 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.util;
+
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.StatLoggerProto;
+import com.android.server.StatLoggerProto.Event;
+
+import java.io.PrintWriter;
+
+/**
+ * Simple class to keep track of the number of times certain events happened and their durations for
+ * benchmarking.
+ *
+ * @hide
+ */
+public class StatLogger {
+    private static final String TAG = "StatLogger";
+
+    private final Object mLock = new Object();
+
+    private final int SIZE;
+
+    @GuardedBy("mLock")
+    private final int[] mCountStats;
+
+    @GuardedBy("mLock")
+    private final long[] mDurationStats;
+
+    @GuardedBy("mLock")
+    private final int[] mCallsPerSecond;
+
+    @GuardedBy("mLock")
+    private final long[] mDurationPerSecond;
+
+    @GuardedBy("mLock")
+    private final int[] mMaxCallsPerSecond;
+
+    @GuardedBy("mLock")
+    private final long[] mMaxDurationPerSecond;
+
+    @GuardedBy("mLock")
+    private final long[] mMaxDurationStats;
+
+    @GuardedBy("mLock")
+    private long mNextTickTime = SystemClock.elapsedRealtime() + 1000;
+
+    private final String[] mLabels;
+
+    public StatLogger(String[] eventLabels) {
+        SIZE = eventLabels.length;
+        mCountStats = new int[SIZE];
+        mDurationStats = new long[SIZE];
+        mCallsPerSecond = new int[SIZE];
+        mMaxCallsPerSecond = new int[SIZE];
+        mDurationPerSecond = new long[SIZE];
+        mMaxDurationPerSecond = new long[SIZE];
+        mMaxDurationStats = new long[SIZE];
+        mLabels = eventLabels;
+    }
+
+    /**
+     * Return the current time in the internal time unit.
+     * Call it before an event happens, and
+     * give it back to the {@link #logDurationStat(int, long)}} after the event.
+     */
+    public long getTime() {
+        return SystemClock.elapsedRealtimeNanos() / 1000;
+    }
+
+    /**
+     * @see {@link #getTime()}
+     *
+     * @return the duration in microseconds.
+     */
+    public long logDurationStat(int eventId, long start) {
+        synchronized (mLock) {
+            final long duration = getTime() - start;
+            if (eventId >= 0 && eventId < SIZE) {
+                mCountStats[eventId]++;
+                mDurationStats[eventId] += duration;
+            } else {
+                Slog.wtf(TAG, "Invalid event ID: " + eventId);
+                return duration;
+            }
+            if (mMaxDurationStats[eventId] < duration) {
+                mMaxDurationStats[eventId] = duration;
+            }
+
+            // Keep track of the per-second max.
+            final long nowRealtime = SystemClock.elapsedRealtime();
+            if (nowRealtime > mNextTickTime) {
+                if (mMaxCallsPerSecond[eventId] < mCallsPerSecond[eventId]) {
+                    mMaxCallsPerSecond[eventId] = mCallsPerSecond[eventId];
+                }
+                if (mMaxDurationPerSecond[eventId] < mDurationPerSecond[eventId]) {
+                    mMaxDurationPerSecond[eventId] = mDurationPerSecond[eventId];
+                }
+
+                mCallsPerSecond[eventId] = 0;
+                mDurationPerSecond[eventId] = 0;
+
+                mNextTickTime = nowRealtime + 1000;
+            }
+
+            mCallsPerSecond[eventId]++;
+            mDurationPerSecond[eventId] += duration;
+
+            return duration;
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        dump(new IndentingPrintWriter(pw, "  ").setIndent(prefix));
+    }
+
+    public void dump(IndentingPrintWriter pw) {
+        synchronized (mLock) {
+            pw.println("Stats:");
+            pw.increaseIndent();
+            for (int i = 0; i < SIZE; i++) {
+                final int count = mCountStats[i];
+                final double durationMs = mDurationStats[i] / 1000.0;
+
+                pw.println(String.format(
+                        "%s: count=%d, total=%.1fms, avg=%.3fms, max calls/s=%d max dur/s=%.1fms"
+                        + " max time=%.1fms",
+                        mLabels[i], count, durationMs,
+                        (count == 0 ? 0 : durationMs / count),
+                        mMaxCallsPerSecond[i], mMaxDurationPerSecond[i] / 1000.0,
+                        mMaxDurationStats[i] / 1000.0));
+            }
+            pw.decreaseIndent();
+        }
+    }
+
+    public void dumpProto(ProtoOutputStream proto, long fieldId) {
+        synchronized (mLock) {
+            final long outer = proto.start(fieldId);
+
+            for (int i = 0; i < mLabels.length; i++) {
+                final long inner = proto.start(StatLoggerProto.EVENTS);
+
+                proto.write(Event.EVENT_ID, i);
+                proto.write(Event.LABEL, mLabels[i]);
+                proto.write(Event.COUNT, mCountStats[i]);
+                proto.write(Event.TOTAL_DURATION_MICROS, mDurationStats[i]);
+
+                proto.end(inner);
+            }
+
+            proto.end(outer);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8ce4e64..6f4ae15 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -88,6 +88,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.LocalLog;
+import com.android.internal.util.StatLogger;
 import com.android.server.AppStateTracker.Listener;
 
 import java.io.ByteArrayOutputStream;
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index cec4f1a..23c5779 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -55,6 +55,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.StatLogger;
 import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
 import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
 
diff --git a/services/core/java/com/android/server/StatLogger.java b/services/core/java/com/android/server/StatLogger.java
deleted file mode 100644
index d85810d..0000000
--- a/services/core/java/com/android/server/StatLogger.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2018 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.server;
-
-import android.os.SystemClock;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.StatLoggerProto.Event;
-
-import java.io.PrintWriter;
-
-/**
- * Simple class to keep track of the number of times certain events happened and their durations for
- * benchmarking.
- *
- * TODO Update shortcut service to switch to it.
- *
- * @hide
- */
-public class StatLogger {
-    private static final String TAG = "StatLogger";
-
-    private final Object mLock = new Object();
-
-    private final int SIZE;
-
-    @GuardedBy("mLock")
-    private final int[] mCountStats;
-
-    @GuardedBy("mLock")
-    private final long[] mDurationStats;
-
-    private final String[] mLabels;
-
-    public StatLogger(String[] eventLabels) {
-        SIZE = eventLabels.length;
-        mCountStats = new int[SIZE];
-        mDurationStats = new long[SIZE];
-        mLabels = eventLabels;
-    }
-
-    /**
-     * Return the current time in the internal time unit.
-     * Call it before an event happens, and
-     * give it back to the {@link #logDurationStat(int, long)}} after the event.
-     */
-    public long getTime() {
-        return SystemClock.elapsedRealtimeNanos() / 1000;
-    }
-
-    /**
-     * @see {@link #getTime()}
-     */
-    public void logDurationStat(int eventId, long start) {
-        synchronized (mLock) {
-            if (eventId >= 0 && eventId < SIZE) {
-                mCountStats[eventId]++;
-                mDurationStats[eventId] += (getTime() - start);
-            } else {
-                Slog.wtf(TAG, "Invalid event ID: " + eventId);
-            }
-        }
-    }
-
-    @Deprecated
-    public void dump(PrintWriter pw, String prefix) {
-        dump(new IndentingPrintWriter(pw, "  ").setIndent(prefix));
-    }
-
-    public void dump(IndentingPrintWriter pw) {
-        synchronized (mLock) {
-            pw.println("Stats:");
-            pw.increaseIndent();
-            for (int i = 0; i < SIZE; i++) {
-                final int count = mCountStats[i];
-                final double durationMs = mDurationStats[i] / 1000.0;
-                pw.println(String.format("%s: count=%d, total=%.1fms, avg=%.3fms",
-                        mLabels[i], count, durationMs,
-                        (count == 0 ? 0 : ((double) durationMs) / count)));
-            }
-            pw.decreaseIndent();
-        }
-    }
-
-    public void dumpProto(ProtoOutputStream proto, long fieldId) {
-        synchronized (mLock) {
-            final long outer = proto.start(fieldId);
-
-            for (int i = 0; i < mLabels.length; i++) {
-                final long inner = proto.start(StatLoggerProto.EVENTS);
-
-                proto.write(Event.EVENT_ID, i);
-                proto.write(Event.LABEL, mLabels[i]);
-                proto.write(Event.COUNT, mCountStats[i]);
-                proto.write(Event.TOTAL_DURATION_MICROS, mDurationStats[i]);
-
-                proto.end(inner);
-            }
-
-            proto.end(outer);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 75bad46..4c1281e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16997,6 +16997,11 @@
                     pw.println("ms");
                 }
                 mUidObservers.finishBroadcast();
+
+                pw.println();
+                pw.println("  ServiceManager statistics:");
+                ServiceManager.sStatLogger.dump(pw, "    ");
+                pw.println();
             }
         }
         pw.println("  mForceBackgroundCheck=" + mForceBackgroundCheck);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 1782ae5..253a19f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -215,6 +215,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.StatLogger;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
@@ -539,6 +540,19 @@
 
     // TODO: migrate notifications to SystemUI
 
+
+    interface Stats {
+        int UPDATE_NETWORK_ENABLED = 0;
+        int IS_UID_NETWORKING_BLOCKED = 1;
+
+        int COUNT = IS_UID_NETWORKING_BLOCKED + 1;
+    }
+
+    public final StatLogger mStatLogger = new StatLogger(new String[] {
+            "updateNetworkEnabledNL()",
+            "isUidNetworkingBlocked()",
+    });
+
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkManagementService networkManagement) {
         this(context, activityManager, networkManagement, AppGlobals.getPackageManager(),
@@ -1551,6 +1565,8 @@
         // TODO: reset any policy-disabled networks when any policy is removed
         // completely, which is currently rare case.
 
+        final long startTime = mStatLogger.getTime();
+
         for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
             final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
             // shortcut when policy has no limit
@@ -1572,6 +1588,8 @@
 
             setNetworkTemplateEnabled(policy.template, networkEnabled);
         }
+
+        mStatLogger.logDurationStat(Stats.UPDATE_NETWORK_ENABLED, startTime);
     }
 
     /**
@@ -3256,6 +3274,9 @@
                 }
                 fout.decreaseIndent();
 
+                fout.println();
+                mStatLogger.dump(fout);
+
                 mLogger.dumpLogs(fout);
             }
         }
@@ -4615,8 +4636,14 @@
 
     @Override
     public boolean isUidNetworkingBlocked(int uid, boolean isNetworkMetered) {
+        final long startTime = mStatLogger.getTime();
+
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-        return isUidNetworkingBlockedInternal(uid, isNetworkMetered);
+        final boolean ret = isUidNetworkingBlockedInternal(uid, isNetworkMetered);
+
+        mStatLogger.logDurationStat(Stats.IS_UID_NETWORKING_BLOCKED, startTime);
+
+        return ret;
     }
 
     private boolean isUidNetworkingBlockedInternal(int uid, boolean isNetworkMetered) {
@@ -4691,11 +4718,17 @@
          */
         @Override
         public boolean isUidNetworkingBlocked(int uid, String ifname) {
+            final long startTime = mStatLogger.getTime();
+
             final boolean isNetworkMetered;
             synchronized (mNetworkPoliciesSecondLock) {
                 isNetworkMetered = mMeteredIfaces.contains(ifname);
             }
-            return isUidNetworkingBlockedInternal(uid, isNetworkMetered);
+            final boolean ret = isUidNetworkingBlockedInternal(uid, isNetworkMetered);
+
+            mStatLogger.logDurationStat(Stats.IS_UID_NETWORKING_BLOCKED, startTime);
+
+            return ret;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 15b4617..599e5a5 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -48,7 +48,6 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
@@ -100,7 +99,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
-import com.android.server.StatLogger;
+import com.android.internal.util.StatLogger;
 import com.android.server.SystemService;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 82d2f3c..e07b89f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -220,7 +220,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
-import com.android.server.StatLogger;
+import com.android.internal.util.StatLogger;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;