1937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar/* 2937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * Copyright (C) 2016 The Android Open Source Project 3937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * 4937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * you may not use this file except in compliance with the License. 6937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * You may obtain a copy of the License at 7937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * 8937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * 10937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * See the License for the specific language governing permissions and 14937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar * limitations under the License. 15937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar */ 16937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 17ba069d50913c3fb250bb60ec310439db36895337Alan Viverettepackage androidx.sqlite.db.framework; 18937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 19937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarimport android.content.Context; 20937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarimport android.database.DatabaseErrorHandler; 21937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarimport android.database.sqlite.SQLiteDatabase; 22937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarimport android.database.sqlite.SQLiteOpenHelper; 23937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarimport android.os.Build; 24ba069d50913c3fb250bb60ec310439db36895337Alan Viverette 25ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.sqlite.db.SupportSQLiteDatabase; 26ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.sqlite.db.SupportSQLiteOpenHelper; 27937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 28937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyarclass FrameworkSQLiteOpenHelper implements SupportSQLiteOpenHelper { 29937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar private final OpenHelper mDelegate; 3064db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar 312b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar FrameworkSQLiteOpenHelper(Context context, String name, 322b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar Callback callback) { 332b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mDelegate = createDelegate(context, name, callback); 34937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 35937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 362b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar private OpenHelper createDelegate(Context context, String name, Callback callback) { 372b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar final FrameworkSQLiteDatabase[] dbRef = new FrameworkSQLiteDatabase[1]; 382b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar return new OpenHelper(context, name, dbRef, callback); 39937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 40937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 41937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 42937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public String getDatabaseName() { 43937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar return mDelegate.getDatabaseName(); 44937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 45937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 46937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 47fbdf0efb750162aa24df0f1a24c8420f1c780ac7Aurimas Liutikas @androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) 48937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public void setWriteAheadLoggingEnabled(boolean enabled) { 49937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar mDelegate.setWriteAheadLoggingEnabled(enabled); 50937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 51937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 52937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 53937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public SupportSQLiteDatabase getWritableDatabase() { 54937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar return mDelegate.getWritableSupportDatabase(); 55937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 56937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 57937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 58937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public SupportSQLiteDatabase getReadableDatabase() { 59937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar return mDelegate.getReadableSupportDatabase(); 60937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 61937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 62937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 63937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public void close() { 64937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar mDelegate.close(); 65937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 66937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 672b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar static class OpenHelper extends SQLiteOpenHelper { 682b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar /** 692b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar * This is used as an Object reference so that we can access the wrapped database inside 702b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar * the constructor. SQLiteOpenHelper requires the error handler to be passed in the 712b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar * constructor. 722b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar */ 732b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar final FrameworkSQLiteDatabase[] mDbRef; 742b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar final Callback mCallback; 75f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar // see b/78359448 76f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar private boolean mMigrated; 772b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 782b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar OpenHelper(Context context, String name, final FrameworkSQLiteDatabase[] dbRef, 792b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar final Callback callback) { 802b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar super(context, name, null, callback.version, 812b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar new DatabaseErrorHandler() { 822b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 832b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onCorruption(SQLiteDatabase dbObj) { 842b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar FrameworkSQLiteDatabase db = dbRef[0]; 852b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar if (db != null) { 862b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar callback.onCorruption(db); 872b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 882b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 892b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar }); 902b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mCallback = callback; 912b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mDbRef = dbRef; 92937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 93937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 94f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar synchronized SupportSQLiteDatabase getWritableSupportDatabase() { 95f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar mMigrated = false; 96937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar SQLiteDatabase db = super.getWritableDatabase(); 97f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar if (mMigrated) { 98f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar // there might be a connection w/ stale structure, we should re-open. 99f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar close(); 100f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar return getWritableSupportDatabase(); 101f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar } 102937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar return getWrappedDb(db); 103937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 104937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 105f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar synchronized SupportSQLiteDatabase getReadableSupportDatabase() { 106f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar mMigrated = false; 107937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar SQLiteDatabase db = super.getReadableDatabase(); 108f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar if (mMigrated) { 109f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar // there might be a connection w/ stale structure, we should re-open. 110f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar close(); 111f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar return getReadableSupportDatabase(); 112f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar } 113937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar return getWrappedDb(db); 114937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 115937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 116937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar FrameworkSQLiteDatabase getWrappedDb(SQLiteDatabase sqLiteDatabase) { 1172b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar FrameworkSQLiteDatabase dbRef = mDbRef[0]; 1182b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar if (dbRef == null) { 1192b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar dbRef = new FrameworkSQLiteDatabase(sqLiteDatabase); 1202b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mDbRef[0] = dbRef; 121937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 1222b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar return mDbRef[0]; 1232b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 1242b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 1252b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 1262b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onCreate(SQLiteDatabase sqLiteDatabase) { 1272b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mCallback.onCreate(getWrappedDb(sqLiteDatabase)); 1282b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 1292b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 1302b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 1312b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { 132f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar mMigrated = true; 1332b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mCallback.onUpgrade(getWrappedDb(sqLiteDatabase), oldVersion, newVersion); 1342b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 1352b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 1362b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 1372b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onConfigure(SQLiteDatabase db) { 1382b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mCallback.onConfigure(getWrappedDb(db)); 1392b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 1402b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 1412b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 1422b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 143f841d6b7490821ca9a843a673a89d41b266f280dYigit Boyar mMigrated = true; 1442b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mCallback.onDowngrade(getWrappedDb(db), oldVersion, newVersion); 1452b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar } 1462b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar 1472b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar @Override 1482b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar public void onOpen(SQLiteDatabase db) { 1498c7ba17f0a8d862f2de744e5bf5879a7e175927dYigit Boyar if (!mMigrated) { 1508c7ba17f0a8d862f2de744e5bf5879a7e175927dYigit Boyar // if we've migrated, we'll re-open the db so we should not call the callback. 1518c7ba17f0a8d862f2de744e5bf5879a7e175927dYigit Boyar mCallback.onOpen(getWrappedDb(db)); 1528c7ba17f0a8d862f2de744e5bf5879a7e175927dYigit Boyar } 153937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 154937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar 155937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar @Override 156937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar public synchronized void close() { 157937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar super.close(); 1582b4a201ee53be9d5e3995e62c76f83c07a1ddfddYigit Boyar mDbRef[0] = null; 159937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 160937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar } 161937a77cef9380b6e03e9e3177a563ddcc4fd1fb5Yigit Boyar} 162