1ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak/*
2ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * Copyright (c) 2015, Motorola Mobility LLC
3ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * All rights reserved.
4ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *
5ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * Redistribution and use in source and binary forms, with or without
6ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * modification, are permitted provided that the following conditions are met:
7ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *     - Redistributions of source code must retain the above copyright
8ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *       notice, this list of conditions and the following disclaimer.
9ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *     - Redistributions in binary form must reproduce the above copyright
10ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *       notice, this list of conditions and the following disclaimer in the
11ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *       documentation and/or other materials provided with the distribution.
12ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *     - Neither the name of Motorola Mobility nor the
13ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *       names of its contributors may be used to endorse or promote products
14ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *       derived from this software without specific prior written permission.
15ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak *
16ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
20ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak * DAMAGE.
27ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak */
28ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
29ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakpackage com.android.service.ims.presence;
30ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
31ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport java.io.File;
32ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
33ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.content.ContentProvider;
34ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.content.ContentValues;
35ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.content.Context;
36ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.content.Intent;
37ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.database.Cursor;
38ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.database.sqlite.SQLiteDatabase;
39ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.database.sqlite.SQLiteException;
40ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.database.sqlite.SQLiteFullException;
41ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.database.sqlite.SQLiteOpenHelper;
42ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport android.net.Uri;
43ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
44ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakimport com.android.ims.internal.Logger;
45ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
46ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiakpublic abstract class DatabaseContentProvider extends ContentProvider {
47ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    static private Logger logger = Logger.getLogger("DatabaseContentProvider");
48ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
49ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    //Constants
50ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public static final String ACTION_DEVICE_STORAGE_FULL = "com.android.vmm.DEVICE_STORAGE_FULL";
51ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
52ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    //Fields
53ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected SQLiteOpenHelper mDbHelper;
54ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /*package*/final int mDbVersion;
55ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    private final String mDbName;
56ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
57ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
58ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * Initializes the DatabaseContentProvider
59ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param dbName the filename of the database
60ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param dbVersion the current version of the database schema
61ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param contentUri The base Uri of the syncable content in this provider
62ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
63ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public DatabaseContentProvider(String dbName, int dbVersion) {
64ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        super();
65ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        mDbName = dbName;
66ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        mDbVersion = dbVersion;
67ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
68ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
69ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
70ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * bootstrapDatabase() allows the implementer to set up their database
71ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * after it is opened for the first time.  this is a perfect place
72ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * to create tables and triggers :)
73ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param db
74ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
75ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected void bootstrapDatabase(SQLiteDatabase db) {
76ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
77ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
78ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
79ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * updgradeDatabase() allows the user to do whatever they like
80ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * when the database is upgraded between versions.
81ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param db - the SQLiteDatabase that will be upgraded
82ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param oldVersion - the old version number as an int
83ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param newVersion - the new version number as an int
84ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return
85ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
86ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);
87ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
88ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
89ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * downgradeDatabase() allows the user to do whatever they like when the
90ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * database is downgraded between versions.
91ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     *
92ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param db - the SQLiteDatabase that will be downgraded
93ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param oldVersion - the old version number as an int
94ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param newVersion - the new version number as an int
95ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return
96ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
97ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract boolean downgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);
98ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
99ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
100ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * Safely wraps an ALTER TABLE table ADD COLUMN columnName columnType
101ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * If columnType == null then it's set to INTEGER DEFAULT 0
102ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param db - db to alter
103ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param table - table to alter
104ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param columnDef
105ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return
106ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
107ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected static boolean addColumn(SQLiteDatabase db, String table, String columnName,
108ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            String columnType) {
109ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        StringBuilder sb = new StringBuilder();
110ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        sb.append("ALTER TABLE ").append(table).append(" ADD COLUMN ").append(columnName).append(
111ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                ' ').append(columnType == null ? "INTEGER DEFAULT 0" : columnType).append(';');
112ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        try {
113ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.execSQL(sb.toString());
114ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (SQLiteException e) {
115ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.debug("Alter table failed : "+ e.getMessage());
116ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return false;
117ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
118ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return true;
119ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
120ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
121ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
122ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * onDatabaseOpened() allows the user to do whatever they might
123ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * need to do whenever the database is opened
124ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param db - SQLiteDatabase that was just opened
125ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
126ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected void onDatabaseOpened(SQLiteDatabase db) {
127ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
128ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
129ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    private class DatabaseHelper extends SQLiteOpenHelper {
130ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        private File mDatabaseFile = null;
131ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
132ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        DatabaseHelper(Context context, String name) {
133ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            // Note: context and name may be null for temp providers
134ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            super(context, name, null, mDbVersion);
135ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            mDatabaseFile = context.getDatabasePath(name);
136ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
137ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
138ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
139ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public void onCreate(SQLiteDatabase db) {
140ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            bootstrapDatabase(db);
141ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
142ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
143ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
144ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
145ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            upgradeDatabase(db, oldVersion, newVersion);
146ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
147ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
148ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
149ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
150ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.debug("Enter: onDowngrade() - oldVersion = " + oldVersion + " newVersion = "
151ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    + newVersion);
152ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            downgradeDatabase(db, oldVersion, newVersion);
153ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
154ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
155ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
156ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public void onOpen(SQLiteDatabase db) {
157ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            onDatabaseOpened(db);
158ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
159ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
160ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
161ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public synchronized SQLiteDatabase getWritableDatabase() {
162ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
163ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                return super.getWritableDatabase();
1648e4834fa676fce0101da34950279b1a2bf8eb81cGao Bing            } catch (Exception e) {
1658e4834fa676fce0101da34950279b1a2bf8eb81cGao Bing                logger.error("getWritableDatabase exception " + e);
166ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
167ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
168ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            // try to delete the database file
169ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            if (null != mDatabaseFile) {
170ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("deleting mDatabaseFile.");
171ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                mDatabaseFile.delete();
172ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
173ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
174ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            // Return a freshly created database.
175ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return super.getWritableDatabase();
176ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
177ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
178ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        @Override
179ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        public synchronized SQLiteDatabase getReadableDatabase() {
180ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
181ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                return super.getReadableDatabase();
1828e4834fa676fce0101da34950279b1a2bf8eb81cGao Bing            } catch (Exception e) {
1838e4834fa676fce0101da34950279b1a2bf8eb81cGao Bing                logger.error("getReadableDatabase exception " + e);
184ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
185ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
186ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            // try to delete the database file
187ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            if (null != mDatabaseFile) {
188ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("deleting mDatabaseFile.");
189ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                mDatabaseFile.delete();
190ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
191ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
192ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            // Return a freshly created database.
193ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return super.getReadableDatabase();
194ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
195ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
196ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
197ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
198ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * deleteInternal allows getContentResolver().delete() to occur atomically
199ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * via transactions and notify the uri automatically upon completion (provided
200ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * rows were deleted) - otherwise, it functions exactly as getContentResolver.delete()
201ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * would on a regular ContentProvider
202ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param uri - uri to delete from
203ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param selection - selection used for the uri
204ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param selectionArgs - selection args replacing ?'s in the selection
205ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return returns the number of rows deleted
206ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
207ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract int deleteInternal(final SQLiteDatabase db, Uri uri, String selection,
208ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            String[] selectionArgs);
209ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
210ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
211ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public int delete(Uri uri, String selection, String[] selectionArgs) {
212ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        int result = 0;
213ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        SQLiteDatabase db = mDbHelper.getWritableDatabase();
214ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (isClosed(db)) {
215ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return result;
216ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
217ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        try {
218ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //acquire reference to prevent from garbage collection
219ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.acquireReference();
220ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //beginTransaction can throw a runtime exception
221ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //so it needs to be moved into the try
222ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.beginTransaction();
223ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            result = deleteInternal(db, uri, selection, selectionArgs);
224ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.setTransactionSuccessful();
225ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (SQLiteFullException fullEx) {
226ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.error("" + fullEx);
227ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            sendStorageFullIntent(getContext());
228ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (Exception e) {
229ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.error("" + e);
230ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } finally {
231ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
232ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.endTransaction();
233ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (SQLiteFullException fullEx) {
234ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + fullEx);
235ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                sendStorageFullIntent(getContext());
236ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (Exception e) {
237ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + e);
238ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
239ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //release reference
240ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.releaseReference();
241ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
242ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        // don't check return value because it may be 0 if all rows deleted
243ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        getContext().getContentResolver().notifyChange(uri, null);
244ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return result;
245ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
246ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
247ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
248ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * insertInternal allows getContentResolver().insert() to occur atomically
249ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * via transactions and notify the uri automatically upon completion (provided
250ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * rows were added to the db) - otherwise, it functions exactly as getContentResolver().insert()
251ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * would on a regular ContentProvider
252ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param uri - uri on which to insert
253ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param values - values to insert
254ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return returns the uri of the row added
255ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
256ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract Uri insertInternal(final SQLiteDatabase db, Uri uri, ContentValues values);
257ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
258ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
259ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public Uri insert(Uri uri, ContentValues values) {
260ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        Uri result = null;
261ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        SQLiteDatabase db = mDbHelper.getWritableDatabase();
262ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (isClosed(db)) {
263ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return result;
264ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
265ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        try {
266ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.acquireReference();
267ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //beginTransaction can throw a runtime exception
268ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //so it needs to be moved into the try
269ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.beginTransaction();
270ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            result = insertInternal(db, uri, values);
271ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.setTransactionSuccessful();
272ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (SQLiteFullException fullEx) {
273ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.warn("" + fullEx);
274ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            sendStorageFullIntent(getContext());
275ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (Exception e) {
276ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.warn("" + e);
277ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } finally {
278ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
279ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.endTransaction();
280ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (SQLiteFullException fullEx) {
281ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.warn("" + fullEx);
282ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                sendStorageFullIntent(getContext());
283ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (Exception e) {
284ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.warn("" + e);
285ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
286ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.releaseReference();
287ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
288ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (result != null) {
289ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            getContext().getContentResolver().notifyChange(uri, null);
290ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
291ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return result;
292ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
293ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
294ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
295ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public boolean onCreate() {
296ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        mDbHelper = new DatabaseHelper(getContext(), mDbName);
297ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return onCreateInternal();
298ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
299ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
300ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
301ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * Called by onCreate.  Should be overridden by any subclasses
302ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * to handle the onCreate lifecycle event.
303ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     *
304ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return
305ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
306ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected boolean onCreateInternal() {
307ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return true;
308ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
309ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
310ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    /**
311ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * queryInternal allows getContentResolver().query() to occur
312ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param uri
313ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param projection
314ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param selection
315ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param selectionArgs
316ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @param sortOrder
317ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     * @return Cursor holding the contents of the requested query
318ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak     */
319ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract Cursor queryInternal(final SQLiteDatabase db, Uri uri, String[] projection,
320ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            String selection, String[] selectionArgs, String sortOrder);
321ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
322ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
323ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
324ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            String sortOrder) {
325ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        SQLiteDatabase db = mDbHelper.getReadableDatabase();
326ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (isClosed(db)) {
327ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return null;
328ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
329ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
330ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        try {
331ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.acquireReference();
332ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return queryInternal(db, uri, projection, selection, selectionArgs, sortOrder);
333ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } finally {
334ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.releaseReference();
335ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
336ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
337ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
338ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    protected abstract int updateInternal(final SQLiteDatabase db, Uri uri, ContentValues values,
339ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            String selection, String[] selectionArgs);
340ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
341ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
342ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
343ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        int result = 0;
344ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        SQLiteDatabase db = mDbHelper.getWritableDatabase();
345ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (isClosed(db)) {
346ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return result;
347ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
348ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        try {
349ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.acquireReference();
350ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //beginTransaction can throw a runtime exception
351ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            //so it needs to be moved into the try
352ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.beginTransaction();
353ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            result = updateInternal(db, uri, values, selection, selectionArgs);
354ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.setTransactionSuccessful();
355ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (SQLiteFullException fullEx) {
356ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.error("" + fullEx);
357ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            sendStorageFullIntent(getContext());
358ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } catch (Exception e) {
359ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.error("" + e);
360ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        } finally {
361ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
362ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.endTransaction();
363ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (SQLiteFullException fullEx) {
364ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + fullEx);
365ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                sendStorageFullIntent(getContext());
366ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (Exception e) {
367ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + e);
368ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
369ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            db.releaseReference();
370ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
371ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (result > 0) {
372ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            getContext().getContentResolver().notifyChange(uri, null);
373ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
374ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return result;
375ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
376ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
377ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    @Override
378ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    public int bulkInsert(Uri uri, ContentValues[] values) {
379ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        int added = 0;
380ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (values != null) {
381ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            int numRows = values.length;
382ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            SQLiteDatabase db = mDbHelper.getWritableDatabase();
383ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            if (isClosed(db)) {
384ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                return added;
385ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
386ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            try {
387ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.acquireReference();
388ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                //beginTransaction can throw a runtime exception
389ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                //so it needs to be moved into the try
390ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.beginTransaction();
391ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
392ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                for (int i = 0; i < numRows; i++) {
393ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    if (insertInternal(db, uri, values[i]) != null) {
394ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                        added++;
395ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    }
396ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                }
397ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.setTransactionSuccessful();
398ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                if (added > 0) {
399ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    getContext().getContentResolver().notifyChange(uri, null);
400ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                }
401ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (SQLiteFullException fullEx) {
402ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + fullEx);
403ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                sendStorageFullIntent(getContext());
404ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } catch (Exception e) {
405ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                logger.error("" + e);
406ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            } finally {
407ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                try {
408ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    db.endTransaction();
409ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                } catch (SQLiteFullException fullEx) {
410ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    logger.error("" + fullEx);
411ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    sendStorageFullIntent(getContext());
412ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                } catch (Exception e) {
413ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                    logger.error("" + e);
414ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                }
415ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak                db.releaseReference();
416ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            }
417ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
418ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return added;
419ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
420ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
421ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    private void sendStorageFullIntent(Context context) {
422ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        Intent fullStorageIntent = new Intent(ACTION_DEVICE_STORAGE_FULL);
423ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        context.sendBroadcast(fullStorageIntent);
424ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
425ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
426ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    private boolean isClosed(SQLiteDatabase db) {
427ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        if (db == null || !db.isOpen()) {
428ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            logger.warn("Null DB returned from DBHelper for a writable/readable database.");
429ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak            return true;
430ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        }
431ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak        return false;
432ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak    }
433ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak
434ac76c57e7a49d4f1431c751db3c810467a60ca48Pavel Zhamaitsiak}
435