1 /*
2  * Copyright (C) 2016 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 package com.android.providers.blockednumber;
17 
18 import android.content.Context;
19 import android.database.sqlite.SQLiteDatabase;
20 import android.database.sqlite.SQLiteOpenHelper;
21 import android.provider.BlockedNumberContract.BlockedNumbers;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 import com.android.internal.util.Preconditions;
25 
26 public class BlockedNumberDatabaseHelper {
27     private static final int DATABASE_VERSION = 2;
28 
29     private static final String DATABASE_NAME = "blockednumbers.db";
30 
31     private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
32 
33     private static BlockedNumberDatabaseHelper sInstance;
34 
35     private final Context mContext;
36 
37     private final OpenHelper mOpenHelper;
38 
39     public interface Tables {
40         String BLOCKED_NUMBERS = "blocked";
41     }
42 
43     private static final class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)44         public OpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
45                           int version) {
46             super(context, name, factory, version);
47             // Memory optimization - close idle connections after 30s of inactivity
48             setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
49         }
50 
51         @Override
onCreate(SQLiteDatabase db)52         public void onCreate(SQLiteDatabase db) {
53             createTables(db);
54         }
55 
56         @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)57         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
58             if (oldVersion < 2) {
59                 db.execSQL("DROP TABLE IF EXISTS blocked");
60                 createTables(db);
61             }
62         }
63 
createTables(SQLiteDatabase db)64         private void createTables(SQLiteDatabase db) {
65             db.execSQL("CREATE TABLE " + Tables.BLOCKED_NUMBERS + " (" +
66                     BlockedNumbers.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
67                     BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " TEXT NOT NULL UNIQUE," +
68                     BlockedNumbers.COLUMN_E164_NUMBER + " TEXT" +
69                     ")");
70 
71             db.execSQL("CREATE INDEX blocked_number_idx_original ON " + Tables.BLOCKED_NUMBERS +
72                     " (" + BlockedNumbers.COLUMN_ORIGINAL_NUMBER + ");");
73             db.execSQL("CREATE INDEX blocked_number_idx_e164 ON " + Tables.BLOCKED_NUMBERS + " (" +
74                     BlockedNumbers.COLUMN_E164_NUMBER +
75                     ");");
76         }
77     }
78 
79     @VisibleForTesting
newInstanceForTest(Context context)80     public static BlockedNumberDatabaseHelper newInstanceForTest(Context context) {
81         return new BlockedNumberDatabaseHelper(context, /* instanceIsForTesting =*/ true);
82     }
83 
BlockedNumberDatabaseHelper(Context context, boolean instanceIsForTesting)84     private BlockedNumberDatabaseHelper(Context context, boolean instanceIsForTesting) {
85         Preconditions.checkNotNull(context);
86         mContext = context;
87         mOpenHelper = new OpenHelper(mContext,
88                 instanceIsForTesting ? null : DATABASE_NAME, null, DATABASE_VERSION);
89     }
90 
getInstance(Context context)91     public static synchronized BlockedNumberDatabaseHelper getInstance(Context context) {
92         if (sInstance == null) {
93             sInstance = new BlockedNumberDatabaseHelper(
94                     context,
95                     /* instanceIsForTesting = */ false);
96         }
97         return sInstance;
98     }
99 
getReadableDatabase()100     public SQLiteDatabase getReadableDatabase() {
101         return mOpenHelper.getReadableDatabase();
102     }
103 
getWritableDatabase()104     public SQLiteDatabase getWritableDatabase() {
105         return mOpenHelper.getWritableDatabase();
106     }
107 
wipeForTest()108     public void wipeForTest() {
109         getWritableDatabase().execSQL("DELETE FROM " + Tables.BLOCKED_NUMBERS);
110     }
111 }
112