Loading api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -11956,6 +11956,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -11969,6 +11970,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12026,6 +12028,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); } api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12752,6 +12752,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -12765,6 +12766,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12822,6 +12824,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); } api/test-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12000,6 +12000,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -12013,6 +12014,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12095,6 +12097,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); } core/java/android/database/sqlite/SQLiteConnectionPool.java +23 −28 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.database.sqlite; import android.app.ActivityManager; import android.database.sqlite.SQLiteDebug.DbStats; import android.os.CancellationSignal; import android.os.Handler; Loading @@ -24,7 +23,6 @@ import android.os.Looper; import android.os.Message; import android.os.OperationCanceledException; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; import android.util.PrefixPrinter; import android.util.Printer; Loading Loading @@ -84,15 +82,6 @@ public final class SQLiteConnectionPool implements Closeable { // and logging a message about the connection pool being busy. private static final long CONNECTION_POOL_BUSY_MILLIS = 30 * 1000; // 30 seconds // TODO b/63398887 Move to SQLiteGlobal private static final long IDLE_CONNECTION_CLOSE_DELAY_MILLIS = SystemProperties .getInt("persist.debug.sqlite.idle_connection_close_delay", 30000); // TODO b/63398887 STOPSHIP. // Temporarily enabled for testing across a broader set of dogfood devices. private static final boolean CLOSE_IDLE_CONNECTIONS = SystemProperties .getBoolean("persist.debug.sqlite.close_idle_connections", true); private final CloseGuard mCloseGuard = CloseGuard.get(); private final Object mLock = new Object(); Loading Loading @@ -167,16 +156,12 @@ public final class SQLiteConnectionPool implements Closeable { private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) { mConfiguration = new SQLiteDatabaseConfiguration(configuration); // Disable lookaside allocator on low-RAM devices if (ActivityManager.isLowRamDeviceStatic()) { mConfiguration.lookasideSlotCount = 0; mConfiguration.lookasideSlotSize = 0; } setMaxConnectionPoolSizeLocked(); // Do not close idle connections for in-memory databases if (CLOSE_IDLE_CONNECTIONS && !configuration.isInMemoryDb()) { setupIdleConnectionHandler(Looper.getMainLooper(), IDLE_CONNECTION_CLOSE_DELAY_MILLIS); // If timeout is set, setup idle connection handler // In case of MAX_VALUE - idle connections are never closed if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) { setupIdleConnectionHandler(Looper.getMainLooper(), mConfiguration.idleConnectionTimeoutMs); } } Loading Loading @@ -214,6 +199,12 @@ public final class SQLiteConnectionPool implements Closeable { // This might throw if the database is corrupt. mAvailablePrimaryConnection = openConnectionLocked(mConfiguration, true /*primaryConnection*/); // might throw // Mark it released so it can be closed after idle timeout synchronized (mLock) { if (mIdleConnectionHandler != null) { mIdleConnectionHandler.connectionReleased(mAvailablePrimaryConnection); } } // Mark the pool as being open for business. mIsOpen = true; Loading Loading @@ -1023,12 +1014,12 @@ public final class SQLiteConnectionPool implements Closeable { } /** * Set up the handler based on the provided looper and delay. * Set up the handler based on the provided looper and timeout. */ @VisibleForTesting public void setupIdleConnectionHandler(Looper looper, long delayMs) { public void setupIdleConnectionHandler(Looper looper, long timeoutMs) { synchronized (mLock) { mIdleConnectionHandler = new IdleConnectionHandler(looper, delayMs); mIdleConnectionHandler = new IdleConnectionHandler(looper, timeoutMs); } } Loading Loading @@ -1089,6 +1080,10 @@ public final class SQLiteConnectionPool implements Closeable { printer.println(" Lookaside config: sz=" + mConfiguration.lookasideSlotSize + " cnt=" + mConfiguration.lookasideSlotCount); } if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) { printer.println( " Idle connection timeout: " + mConfiguration.idleConnectionTimeoutMs); } printer.println(" Available primary connection:"); if (mAvailablePrimaryConnection != null) { mAvailablePrimaryConnection.dump(indentedPrinter, verbose); Loading Loading @@ -1155,11 +1150,11 @@ public final class SQLiteConnectionPool implements Closeable { } private class IdleConnectionHandler extends Handler { private final long mDelay; private final long mTimeout; IdleConnectionHandler(Looper looper, long delay) { IdleConnectionHandler(Looper looper, long timeout) { super(looper); mDelay = delay; mTimeout = timeout; } @Override Loading @@ -1172,14 +1167,14 @@ public final class SQLiteConnectionPool implements Closeable { if (closeAvailableConnectionLocked(msg.what)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Closed idle connection " + mConfiguration.label + " " + msg.what + " after " + mDelay); + " after " + mTimeout); } } } } void connectionReleased(SQLiteConnection con) { sendEmptyMessageDelayed(con.getConnectionId(), mDelay); sendEmptyMessageDelayed(con.getConnectionId(), mTimeout); } void connectionAcquired(SQLiteConnection con) { Loading core/java/android/database/sqlite/SQLiteDatabase.java +64 −13 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.ContentValues; import android.database.Cursor; import android.database.DatabaseErrorHandler; Loading @@ -30,6 +31,7 @@ import android.database.sqlite.SQLiteDebug.DbStats; import android.os.CancellationSignal; import android.os.Looper; import android.os.OperationCanceledException; import android.os.SystemProperties; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; Loading Loading @@ -77,21 +79,21 @@ public final class SQLiteDatabase extends SQLiteClosable { private static final int EVENT_DB_CORRUPT = 75004; // TODO b/63398887 STOPSHIP. // Temporarily enabled for testing across a broader set of dogfood devices. private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties .getBoolean("persist.debug.sqlite.close_idle_connections", true); // Stores reference to all databases opened in the current process. // (The referent Object is not used at this time.) // INVARIANT: Guarded by sActiveDatabases. private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<SQLiteDatabase, Object>(); private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>(); // Thread-local for database sessions that belong to this database. // Each thread has its own database session. // INVARIANT: Immutable. private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() { @Override protected SQLiteSession initialValue() { return createSession(); } }; private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal .withInitial(this::createSession); // The optional factory to use when creating new Cursors. May be null. // INVARIANT: Immutable. Loading Loading @@ -261,12 +263,29 @@ public final class SQLiteDatabase extends SQLiteClosable { private SQLiteDatabase(final String path, final int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) { int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs) { mCursorFactory = cursorFactory; mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler(); mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags); mConfigurationLocked.lookasideSlotSize = lookasideSlotSize; mConfigurationLocked.lookasideSlotCount = lookasideSlotCount; // Disable lookaside allocator on low-RAM devices if (ActivityManager.isLowRamDeviceStatic()) { mConfigurationLocked.lookasideSlotCount = 0; mConfigurationLocked.lookasideSlotSize = 0; } long effectiveTimeoutMs = Long.MAX_VALUE; // Never close idle connections for in-memory databases if (!mConfigurationLocked.isInMemoryDb()) { // First, check app-specific value. Otherwise use defaults // -1 in idleConnectionTimeoutMs indicates unset value if (idleConnectionTimeoutMs >= 0) { effectiveTimeoutMs = idleConnectionTimeoutMs; } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) { effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout(); } } mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs; } @Override Loading Loading @@ -694,7 +713,8 @@ public final class SQLiteDatabase extends SQLiteClosable { Preconditions.checkArgument(openParams != null, "OpenParams cannot be null"); SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags, openParams.mCursorFactory, openParams.mErrorHandler, openParams.mLookasideSlotSize, openParams.mLookasideSlotCount); openParams.mLookasideSlotSize, openParams.mLookasideSlotCount, openParams.mIdleConnectionTimeout); db.open(); return db; } Loading @@ -720,7 +740,7 @@ public final class SQLiteDatabase extends SQLiteClosable { */ public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) { SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1); SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1); db.open(); return db; } Loading Loading @@ -2267,14 +2287,17 @@ public final class SQLiteDatabase extends SQLiteClosable { private final DatabaseErrorHandler mErrorHandler; private final int mLookasideSlotSize; private final int mLookasideSlotCount; private long mIdleConnectionTimeout; private OpenParams(int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) { DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeout) { mOpenFlags = openFlags; mCursorFactory = cursorFactory; mErrorHandler = errorHandler; mLookasideSlotSize = lookasideSlotSize; mLookasideSlotCount = lookasideSlotCount; mIdleConnectionTimeout = idleConnectionTimeout; } /** Loading Loading @@ -2329,6 +2352,17 @@ public final class SQLiteDatabase extends SQLiteClosable { return mErrorHandler; } /** * Returns maximum number of milliseconds that SQLite connection is allowed to be idle * before it is closed and removed from the pool. * <p>If the value isn't set, the timeout defaults to the system wide timeout * * @return timeout in milliseconds or -1 if the value wasn't set. */ public long getIdleConnectionTimeout() { return mIdleConnectionTimeout; } /** * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with * {@code this} parameters. Loading @@ -2345,6 +2379,7 @@ public final class SQLiteDatabase extends SQLiteClosable { public static final class Builder { private int mLookasideSlotSize = -1; private int mLookasideSlotCount = -1; private long mIdleConnectionTimeout = -1; private int mOpenFlags; private CursorFactory mCursorFactory; private DatabaseErrorHandler mErrorHandler; Loading Loading @@ -2473,6 +2508,22 @@ public final class SQLiteDatabase extends SQLiteClosable { return this; } /** * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle * before it is closed and removed from the pool. * * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} * to allow unlimited idle connections. */ @NonNull public Builder setIdleConnectionTimeout( @IntRange(from = 0) long idleConnectionTimeoutMs) { Preconditions.checkArgument(idleConnectionTimeoutMs >= 0, "idle connection timeout cannot be negative"); mIdleConnectionTimeout = idleConnectionTimeoutMs; return this; } /** * Creates an instance of {@link OpenParams} with the options that were previously set * on this builder Loading @@ -2480,7 +2531,7 @@ public final class SQLiteDatabase extends SQLiteClosable { @NonNull public OpenParams build() { return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize, mLookasideSlotCount); mLookasideSlotCount, mIdleConnectionTimeout); } } } Loading Loading
api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -11956,6 +11956,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -11969,6 +11970,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12026,6 +12028,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); }
api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12752,6 +12752,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -12765,6 +12766,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12822,6 +12824,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); }
api/test-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12000,6 +12000,7 @@ package android.database.sqlite { public static final class SQLiteDatabase.OpenParams { method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory(); method public android.database.DatabaseErrorHandler getErrorHandler(); method public long getIdleConnectionTimeout(); method public int getLookasideSlotCount(); method public int getLookasideSlotSize(); method public int getOpenFlags(); Loading @@ -12013,6 +12014,7 @@ package android.database.sqlite { method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(long); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int); method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int); } Loading Loading @@ -12095,6 +12097,7 @@ package android.database.sqlite { method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int); method public void onOpen(android.database.sqlite.SQLiteDatabase); method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int); method public void setIdleConnectionTimeout(long); method public void setLookasideConfig(int, int); method public void setWriteAheadLoggingEnabled(boolean); }
core/java/android/database/sqlite/SQLiteConnectionPool.java +23 −28 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.database.sqlite; import android.app.ActivityManager; import android.database.sqlite.SQLiteDebug.DbStats; import android.os.CancellationSignal; import android.os.Handler; Loading @@ -24,7 +23,6 @@ import android.os.Looper; import android.os.Message; import android.os.OperationCanceledException; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; import android.util.PrefixPrinter; import android.util.Printer; Loading Loading @@ -84,15 +82,6 @@ public final class SQLiteConnectionPool implements Closeable { // and logging a message about the connection pool being busy. private static final long CONNECTION_POOL_BUSY_MILLIS = 30 * 1000; // 30 seconds // TODO b/63398887 Move to SQLiteGlobal private static final long IDLE_CONNECTION_CLOSE_DELAY_MILLIS = SystemProperties .getInt("persist.debug.sqlite.idle_connection_close_delay", 30000); // TODO b/63398887 STOPSHIP. // Temporarily enabled for testing across a broader set of dogfood devices. private static final boolean CLOSE_IDLE_CONNECTIONS = SystemProperties .getBoolean("persist.debug.sqlite.close_idle_connections", true); private final CloseGuard mCloseGuard = CloseGuard.get(); private final Object mLock = new Object(); Loading Loading @@ -167,16 +156,12 @@ public final class SQLiteConnectionPool implements Closeable { private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) { mConfiguration = new SQLiteDatabaseConfiguration(configuration); // Disable lookaside allocator on low-RAM devices if (ActivityManager.isLowRamDeviceStatic()) { mConfiguration.lookasideSlotCount = 0; mConfiguration.lookasideSlotSize = 0; } setMaxConnectionPoolSizeLocked(); // Do not close idle connections for in-memory databases if (CLOSE_IDLE_CONNECTIONS && !configuration.isInMemoryDb()) { setupIdleConnectionHandler(Looper.getMainLooper(), IDLE_CONNECTION_CLOSE_DELAY_MILLIS); // If timeout is set, setup idle connection handler // In case of MAX_VALUE - idle connections are never closed if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) { setupIdleConnectionHandler(Looper.getMainLooper(), mConfiguration.idleConnectionTimeoutMs); } } Loading Loading @@ -214,6 +199,12 @@ public final class SQLiteConnectionPool implements Closeable { // This might throw if the database is corrupt. mAvailablePrimaryConnection = openConnectionLocked(mConfiguration, true /*primaryConnection*/); // might throw // Mark it released so it can be closed after idle timeout synchronized (mLock) { if (mIdleConnectionHandler != null) { mIdleConnectionHandler.connectionReleased(mAvailablePrimaryConnection); } } // Mark the pool as being open for business. mIsOpen = true; Loading Loading @@ -1023,12 +1014,12 @@ public final class SQLiteConnectionPool implements Closeable { } /** * Set up the handler based on the provided looper and delay. * Set up the handler based on the provided looper and timeout. */ @VisibleForTesting public void setupIdleConnectionHandler(Looper looper, long delayMs) { public void setupIdleConnectionHandler(Looper looper, long timeoutMs) { synchronized (mLock) { mIdleConnectionHandler = new IdleConnectionHandler(looper, delayMs); mIdleConnectionHandler = new IdleConnectionHandler(looper, timeoutMs); } } Loading Loading @@ -1089,6 +1080,10 @@ public final class SQLiteConnectionPool implements Closeable { printer.println(" Lookaside config: sz=" + mConfiguration.lookasideSlotSize + " cnt=" + mConfiguration.lookasideSlotCount); } if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) { printer.println( " Idle connection timeout: " + mConfiguration.idleConnectionTimeoutMs); } printer.println(" Available primary connection:"); if (mAvailablePrimaryConnection != null) { mAvailablePrimaryConnection.dump(indentedPrinter, verbose); Loading Loading @@ -1155,11 +1150,11 @@ public final class SQLiteConnectionPool implements Closeable { } private class IdleConnectionHandler extends Handler { private final long mDelay; private final long mTimeout; IdleConnectionHandler(Looper looper, long delay) { IdleConnectionHandler(Looper looper, long timeout) { super(looper); mDelay = delay; mTimeout = timeout; } @Override Loading @@ -1172,14 +1167,14 @@ public final class SQLiteConnectionPool implements Closeable { if (closeAvailableConnectionLocked(msg.what)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Closed idle connection " + mConfiguration.label + " " + msg.what + " after " + mDelay); + " after " + mTimeout); } } } } void connectionReleased(SQLiteConnection con) { sendEmptyMessageDelayed(con.getConnectionId(), mDelay); sendEmptyMessageDelayed(con.getConnectionId(), mTimeout); } void connectionAcquired(SQLiteConnection con) { Loading
core/java/android/database/sqlite/SQLiteDatabase.java +64 −13 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.ContentValues; import android.database.Cursor; import android.database.DatabaseErrorHandler; Loading @@ -30,6 +31,7 @@ import android.database.sqlite.SQLiteDebug.DbStats; import android.os.CancellationSignal; import android.os.Looper; import android.os.OperationCanceledException; import android.os.SystemProperties; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; Loading Loading @@ -77,21 +79,21 @@ public final class SQLiteDatabase extends SQLiteClosable { private static final int EVENT_DB_CORRUPT = 75004; // TODO b/63398887 STOPSHIP. // Temporarily enabled for testing across a broader set of dogfood devices. private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties .getBoolean("persist.debug.sqlite.close_idle_connections", true); // Stores reference to all databases opened in the current process. // (The referent Object is not used at this time.) // INVARIANT: Guarded by sActiveDatabases. private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<SQLiteDatabase, Object>(); private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>(); // Thread-local for database sessions that belong to this database. // Each thread has its own database session. // INVARIANT: Immutable. private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() { @Override protected SQLiteSession initialValue() { return createSession(); } }; private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal .withInitial(this::createSession); // The optional factory to use when creating new Cursors. May be null. // INVARIANT: Immutable. Loading Loading @@ -261,12 +263,29 @@ public final class SQLiteDatabase extends SQLiteClosable { private SQLiteDatabase(final String path, final int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) { int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs) { mCursorFactory = cursorFactory; mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler(); mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags); mConfigurationLocked.lookasideSlotSize = lookasideSlotSize; mConfigurationLocked.lookasideSlotCount = lookasideSlotCount; // Disable lookaside allocator on low-RAM devices if (ActivityManager.isLowRamDeviceStatic()) { mConfigurationLocked.lookasideSlotCount = 0; mConfigurationLocked.lookasideSlotSize = 0; } long effectiveTimeoutMs = Long.MAX_VALUE; // Never close idle connections for in-memory databases if (!mConfigurationLocked.isInMemoryDb()) { // First, check app-specific value. Otherwise use defaults // -1 in idleConnectionTimeoutMs indicates unset value if (idleConnectionTimeoutMs >= 0) { effectiveTimeoutMs = idleConnectionTimeoutMs; } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) { effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout(); } } mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs; } @Override Loading Loading @@ -694,7 +713,8 @@ public final class SQLiteDatabase extends SQLiteClosable { Preconditions.checkArgument(openParams != null, "OpenParams cannot be null"); SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags, openParams.mCursorFactory, openParams.mErrorHandler, openParams.mLookasideSlotSize, openParams.mLookasideSlotCount); openParams.mLookasideSlotSize, openParams.mLookasideSlotCount, openParams.mIdleConnectionTimeout); db.open(); return db; } Loading @@ -720,7 +740,7 @@ public final class SQLiteDatabase extends SQLiteClosable { */ public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) { SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1); SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1); db.open(); return db; } Loading Loading @@ -2267,14 +2287,17 @@ public final class SQLiteDatabase extends SQLiteClosable { private final DatabaseErrorHandler mErrorHandler; private final int mLookasideSlotSize; private final int mLookasideSlotCount; private long mIdleConnectionTimeout; private OpenParams(int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) { DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeout) { mOpenFlags = openFlags; mCursorFactory = cursorFactory; mErrorHandler = errorHandler; mLookasideSlotSize = lookasideSlotSize; mLookasideSlotCount = lookasideSlotCount; mIdleConnectionTimeout = idleConnectionTimeout; } /** Loading Loading @@ -2329,6 +2352,17 @@ public final class SQLiteDatabase extends SQLiteClosable { return mErrorHandler; } /** * Returns maximum number of milliseconds that SQLite connection is allowed to be idle * before it is closed and removed from the pool. * <p>If the value isn't set, the timeout defaults to the system wide timeout * * @return timeout in milliseconds or -1 if the value wasn't set. */ public long getIdleConnectionTimeout() { return mIdleConnectionTimeout; } /** * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with * {@code this} parameters. Loading @@ -2345,6 +2379,7 @@ public final class SQLiteDatabase extends SQLiteClosable { public static final class Builder { private int mLookasideSlotSize = -1; private int mLookasideSlotCount = -1; private long mIdleConnectionTimeout = -1; private int mOpenFlags; private CursorFactory mCursorFactory; private DatabaseErrorHandler mErrorHandler; Loading Loading @@ -2473,6 +2508,22 @@ public final class SQLiteDatabase extends SQLiteClosable { return this; } /** * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle * before it is closed and removed from the pool. * * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} * to allow unlimited idle connections. */ @NonNull public Builder setIdleConnectionTimeout( @IntRange(from = 0) long idleConnectionTimeoutMs) { Preconditions.checkArgument(idleConnectionTimeoutMs >= 0, "idle connection timeout cannot be negative"); mIdleConnectionTimeout = idleConnectionTimeoutMs; return this; } /** * Creates an instance of {@link OpenParams} with the options that were previously set * on this builder Loading @@ -2480,7 +2531,7 @@ public final class SQLiteDatabase extends SQLiteClosable { @NonNull public OpenParams build() { return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize, mLookasideSlotCount); mLookasideSlotCount, mIdleConnectionTimeout); } } } Loading