Merge "Move provider access stats to frameworks/base" into pi-dev
diff --git a/core/java/com/android/internal/util/ProviderAccessStats.java b/core/java/com/android/internal/util/ProviderAccessStats.java
new file mode 100644
index 0000000..c3ffb02
--- /dev/null
+++ b/core/java/com/android/internal/util/ProviderAccessStats.java
@@ -0,0 +1,134 @@
+/*
+ * 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.SparseBooleanArray;
+import android.util.SparseLongArray;
+
+import java.io.PrintWriter;
+
+public class ProviderAccessStats {
+ private final Object mLock = new Object();
+
+ private final long mStartUptime = SystemClock.uptimeMillis();
+
+ private final SparseBooleanArray mAllCallingUids = new SparseBooleanArray();
+ private final SparseLongArray mQueryStats = new SparseLongArray(16);
+ private final SparseLongArray mBatchStats = new SparseLongArray(0);
+ private final SparseLongArray mInsertStats = new SparseLongArray(0);
+ private final SparseLongArray mUpdateStats = new SparseLongArray(0);
+ private final SparseLongArray mDeleteStats = new SparseLongArray(0);
+ private final SparseLongArray mInsertInBatchStats = new SparseLongArray(0);
+ private final SparseLongArray mUpdateInBatchStats = new SparseLongArray(0);
+ private final SparseLongArray mDeleteInBatchStats = new SparseLongArray(0);
+
+ private final SparseLongArray mOperationDurationMillis = new SparseLongArray(16);
+
+ private static class PerThreadData {
+ public int nestCount;
+ public long startUptimeMillis;
+ }
+
+ private final ThreadLocal<PerThreadData> mThreadLocal =
+ ThreadLocal.withInitial(() -> new PerThreadData());
+
+ private void incrementStats(int callingUid, SparseLongArray stats) {
+ synchronized (mLock) {
+ stats.put(callingUid, stats.get(callingUid) + 1);
+ mAllCallingUids.put(callingUid, true);
+ }
+
+ final PerThreadData data = mThreadLocal.get();
+ data.nestCount++;
+ if (data.nestCount == 1) {
+ data.startUptimeMillis = SystemClock.uptimeMillis();
+ }
+ }
+
+ private void incrementStats(int callingUid, boolean inBatch,
+ SparseLongArray statsNonBatch, SparseLongArray statsInBatch) {
+ incrementStats(callingUid, inBatch ? statsInBatch : statsNonBatch);
+ }
+
+ public final void incrementInsertStats(int callingUid, boolean inBatch) {
+ incrementStats(callingUid, inBatch, mInsertStats, mInsertInBatchStats);
+ }
+
+ public final void incrementUpdateStats(int callingUid, boolean inBatch) {
+ incrementStats(callingUid, inBatch, mUpdateStats, mUpdateInBatchStats);
+ }
+
+ public final void incrementDeleteStats(int callingUid, boolean inBatch) {
+ incrementStats(callingUid, inBatch, mDeleteStats, mDeleteInBatchStats);
+ }
+
+ public final void incrementQueryStats(int callingUid) {
+ incrementStats(callingUid, mQueryStats);
+ }
+
+ public final void incrementBatchStats(int callingUid) {
+ incrementStats(callingUid, mBatchStats);
+ }
+
+ public void finishOperation(int callingUid) {
+ final PerThreadData data = mThreadLocal.get();
+ data.nestCount--;
+ if (data.nestCount == 0) {
+ // Because we only have millisecond granularity, let's always attribute at least 1ms
+ // for each operation.
+ final long duration = Math.max(1, SystemClock.uptimeMillis() - data.startUptimeMillis);
+
+ synchronized (mLock) {
+ mOperationDurationMillis.put(callingUid,
+ mOperationDurationMillis.get(callingUid) + duration);
+ }
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ synchronized (mLock) {
+ pw.print(" Process uptime: ");
+ pw.print((SystemClock.uptimeMillis() - mStartUptime) / (60 * 1000));
+ pw.println(" minutes");
+ pw.println();
+
+ pw.print(prefix);
+ pw.println("Client activities:");
+ pw.print(prefix);
+ pw.println(" UID Query Insert Update Delete Batch Insert Update Delete"
+ + " Sec");
+ for (int i = 0; i < mAllCallingUids.size(); i++) {
+ final int uid = mAllCallingUids.keyAt(i);
+ pw.print(prefix);
+ pw.println(String.format(
+ " %-9d %6d %6d %6d %6d %6d %6d %6d %6d %12.3f",
+ uid,
+ mQueryStats.get(uid),
+ mInsertStats.get(uid),
+ mUpdateStats.get(uid),
+ mDeleteStats.get(uid),
+ mBatchStats.get(uid),
+ mInsertInBatchStats.get(uid),
+ mUpdateInBatchStats.get(uid),
+ mDeleteInBatchStats.get(uid),
+ (mOperationDurationMillis.get(uid) / 1000.0)
+ ));
+ }
+ pw.println();
+ }
+ }
+}