• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 android.database.sqlite;
18 
19 import android.annotation.TestApi;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.os.Build;
22 import android.os.Process;
23 import android.os.SystemProperties;
24 import android.util.Log;
25 import android.util.Printer;
26 
27 import java.util.ArrayList;
28 
29 /**
30  * Provides debugging info about all SQLite databases running in the current process.
31  *
32  * {@hide}
33  */
34 @TestApi
35 public final class SQLiteDebug {
nativeGetPagerStats(PagerStats stats)36     private static native void nativeGetPagerStats(PagerStats stats);
37 
38     /**
39      * Inner class to avoid getting the value frozen in zygote.
40      *
41      * {@hide}
42      */
43     public static final class NoPreloadHolder {
44         /**
45          * Controls the printing of informational SQL log messages.
46          *
47          * Enable using "adb shell setprop log.tag.SQLiteLog VERBOSE".
48          */
49         public static final boolean DEBUG_SQL_LOG =
50                 Log.isLoggable("SQLiteLog", Log.VERBOSE);
51 
52         /**
53          * Controls the printing of SQL statements as they are executed.
54          *
55          * Enable using "adb shell setprop log.tag.SQLiteStatements VERBOSE".
56          */
57         public static final boolean DEBUG_SQL_STATEMENTS =
58                 Log.isLoggable("SQLiteStatements", Log.VERBOSE);
59 
60         /**
61          * Controls the printing of wall-clock time taken to execute SQL statements
62          * as they are executed.
63          *
64          * Enable using "adb shell setprop log.tag.SQLiteTime VERBOSE".
65          */
66         public static final boolean DEBUG_SQL_TIME =
67                 Log.isLoggable("SQLiteTime", Log.VERBOSE);
68 
69 
70         /**
71          * True to enable database performance testing instrumentation.
72          */
73         public static final boolean DEBUG_LOG_SLOW_QUERIES =
74                 Log.isLoggable("SQLiteSlowQueries", Log.VERBOSE);
75 
76         private static final String SLOW_QUERY_THRESHOLD_PROP = "db.log.slow_query_threshold";
77 
78         private static final String SLOW_QUERY_THRESHOLD_UID_PROP =
79                 SLOW_QUERY_THRESHOLD_PROP + "." + Process.myUid();
80 
81         /**
82          * Whether to add detailed information to slow query log.
83          */
84         public static final boolean DEBUG_LOG_DETAILED = Build.IS_DEBUGGABLE
85                 && SystemProperties.getBoolean("db.log.detailed", false);
86     }
87 
SQLiteDebug()88     private SQLiteDebug() {
89     }
90 
91     /**
92      * Determines whether a query should be logged.
93      *
94      * Reads the "db.log.slow_query_threshold" system property, which can be changed
95      * by the user at any time.  If the value is zero, then all queries will
96      * be considered slow.  If the value does not exist or is negative, then no queries will
97      * be considered slow.
98      *
99      * To enable it for a specific UID, "db.log.slow_query_threshold.UID" could also be used.
100      *
101      * This value can be changed dynamically while the system is running.
102      * For example, "adb shell setprop db.log.slow_query_threshold 200" will
103      * log all queries that take 200ms or longer to run.
104      * @hide
105      */
shouldLogSlowQuery(long elapsedTimeMillis)106     public static boolean shouldLogSlowQuery(long elapsedTimeMillis) {
107         final int slowQueryMillis = Math.min(
108                 SystemProperties.getInt(NoPreloadHolder.SLOW_QUERY_THRESHOLD_PROP,
109                         Integer.MAX_VALUE),
110                 SystemProperties.getInt(NoPreloadHolder.SLOW_QUERY_THRESHOLD_UID_PROP,
111                         Integer.MAX_VALUE));
112         return elapsedTimeMillis >= slowQueryMillis;
113     }
114 
115     /**
116      * Contains statistics about the active pagers in the current process.
117      *
118      * @see #nativeGetPagerStats(PagerStats)
119      */
120     public static class PagerStats {
121 
122         @UnsupportedAppUsage
PagerStats()123         public PagerStats() {
124         }
125 
126         /** the current amount of memory checked out by sqlite using sqlite3_malloc().
127          * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html
128          */
129         @UnsupportedAppUsage
130         public int memoryUsed;
131 
132         /** the number of bytes of page cache allocation which could not be sattisfied by the
133          * SQLITE_CONFIG_PAGECACHE buffer and where forced to overflow to sqlite3_malloc().
134          * The returned value includes allocations that overflowed because they where too large
135          * (they were larger than the "sz" parameter to SQLITE_CONFIG_PAGECACHE) and allocations
136          * that overflowed because no space was left in the page cache.
137          * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html
138          */
139         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
140         public int pageCacheOverflow;
141 
142         /** records the largest memory allocation request handed to sqlite3.
143          * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html
144          */
145         @UnsupportedAppUsage
146         public int largestMemAlloc;
147 
148         /** a list of {@link DbStats} - one for each main database opened by the applications
149          * running on the android device
150          */
151         @UnsupportedAppUsage
152         public ArrayList<DbStats> dbStats;
153     }
154 
155     /**
156      * contains statistics about a database
157      */
158     public static class DbStats {
159         /** name of the database */
160         @UnsupportedAppUsage
161         public String dbName;
162 
163         /** the page size for the database */
164         @UnsupportedAppUsage
165         public long pageSize;
166 
167         /** the database size */
168         @UnsupportedAppUsage
169         public long dbSize;
170 
171         /**
172          * Number of lookaside slots: http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html */
173         @UnsupportedAppUsage
174         public int lookaside;
175 
176         /** statement cache stats: hits/misses/cachesize */
177         public String cache;
178 
DbStats(String dbName, long pageCount, long pageSize, int lookaside, int hits, int misses, int cachesize)179         public DbStats(String dbName, long pageCount, long pageSize, int lookaside,
180             int hits, int misses, int cachesize) {
181             this.dbName = dbName;
182             this.pageSize = pageSize / 1024;
183             dbSize = (pageCount * pageSize) / 1024;
184             this.lookaside = lookaside;
185             this.cache = hits + "/" + misses + "/" + cachesize;
186         }
187     }
188 
189     /**
190      * return all pager and database stats for the current process.
191      * @return {@link PagerStats}
192      */
193     @UnsupportedAppUsage
getDatabaseInfo()194     public static PagerStats getDatabaseInfo() {
195         PagerStats stats = new PagerStats();
196         nativeGetPagerStats(stats);
197         stats.dbStats = SQLiteDatabase.getDbStats();
198         return stats;
199     }
200 
201     /**
202      * Dumps detailed information about all databases used by the process.
203      * @param printer The printer for dumping database state.
204      * @param args Command-line arguments supplied to dumpsys dbinfo
205      */
dump(Printer printer, String[] args)206     public static void dump(Printer printer, String[] args) {
207         dump(printer, args, false);
208     }
209 
210     /** @hide */
dump(Printer printer, String[] args, boolean isSystem)211     public static void dump(Printer printer, String[] args, boolean isSystem) {
212         boolean verbose = false;
213         for (String arg : args) {
214             if (arg.equals("-v")) {
215                 verbose = true;
216             }
217         }
218 
219         SQLiteDatabase.dumpAll(printer, verbose, isSystem);
220     }
221 }
222