• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015, Motorola Mobility LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     - Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     - Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     - Neither the name of Motorola Mobility nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26  * DAMAGE.
27  */
28 
29 package com.android.service.ims.presence;
30 
31 import java.io.FileNotFoundException;
32 
33 import android.content.ContentUris;
34 import android.content.ContentValues;
35 import android.content.Intent;
36 import android.content.UriMatcher;
37 import android.database.Cursor;
38 import android.database.SQLException;
39 import android.database.sqlite.SQLiteDatabase;
40 import android.database.sqlite.SQLiteQueryBuilder;
41 import android.net.Uri;
42 import android.os.ParcelFileDescriptor;
43 import android.provider.BaseColumns;
44 import android.provider.ContactsContract.Contacts;
45 import android.content.ComponentName;
46 
47 import com.android.ims.RcsPresenceInfo;
48 import com.android.ims.internal.EABContract;
49 import com.android.ims.internal.Logger;
50 
51 /**
52  * @author Vishal Patil (A22809)
53  */
54 
55 public class EABProvider extends DatabaseContentProvider{
56     private Logger logger = Logger.getLogger(this.getClass().getName());
57 
58     private static final String EAB_DB_NAME = "rcseab.db";
59 
60     private static final int EAB_DB_VERSION = 2;
61 
62     private static final int EAB_TABLE = 1;
63 
64     private static final int EAB_TABLE_ID = 2;
65 
66     private static final int EAB_GROUPITEMS_TABLE = 3;
67 
68     private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH) {
69         {
70             addURI(EABContract.AUTHORITY, EABContract.EABColumns.TABLE_NAME, EAB_TABLE);
71             addURI(EABContract.AUTHORITY, EABContract.EABColumns.TABLE_NAME + "/#", EAB_TABLE_ID);
72             addURI(EABContract.AUTHORITY, EABContract.EABColumns.GROUPITEMS_NAME,
73                     EAB_GROUPITEMS_TABLE);
74         }
75     };
76 
77     /* Statement to create VMM Album table. */
78     private static final String EAB_CREATE_STATEMENT = "create table if not exists "
79             + EABContract.EABColumns.TABLE_NAME
80             + "("
81             + EABContract.EABColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
82             + EABContract.EABColumns.CONTACT_NAME + " TEXT, "
83             + EABContract.EABColumns.CONTACT_NUMBER + " TEXT, "
84             + EABContract.EABColumns.RAW_CONTACT_ID + " TEXT, "
85             + EABContract.EABColumns.CONTACT_ID + " TEXT, "
86             + EABContract.EABColumns.DATA_ID + " TEXT, "
87             + EABContract.EABColumns.ACCOUNT_TYPE  + " TEXT, "
88             + EABContract.EABColumns.VOLTE_CALL_SERVICE_CONTACT_ADDRESS + " TEXT, "
89             + EABContract.EABColumns.VOLTE_CALL_CAPABILITY + " INTEGER, "
90             + EABContract.EABColumns.VOLTE_CALL_CAPABILITY_TIMESTAMP + " LONG, "
91             + EABContract.EABColumns.VOLTE_CALL_AVAILABILITY + " INTEGER, "
92             + EABContract.EABColumns.VOLTE_CALL_AVAILABILITY_TIMESTAMP + " LONG, "
93             + EABContract.EABColumns.VIDEO_CALL_SERVICE_CONTACT_ADDRESS + " TEXT, "
94             + EABContract.EABColumns.VIDEO_CALL_CAPABILITY + " INTEGER, "
95             + EABContract.EABColumns.VIDEO_CALL_CAPABILITY_TIMESTAMP + " LONG, "
96             + EABContract.EABColumns.VIDEO_CALL_AVAILABILITY + " INTEGER, "
97             + EABContract.EABColumns.VIDEO_CALL_AVAILABILITY_TIMESTAMP + " LONG, "
98             + EABContract.EABColumns.CONTACT_LAST_UPDATED_TIMESTAMP + " LONG "
99             + ");";
100 
101     private static final String EAB_DROP_STATEMENT = "drop table if exists "
102             + EABContract.EABColumns.TABLE_NAME + ";";
103 
EABProvider()104     public EABProvider() {
105         super(EAB_DB_NAME, EAB_DB_VERSION);
106     }
107 
108     @Override
bootstrapDatabase(SQLiteDatabase db)109     public void bootstrapDatabase(SQLiteDatabase db) {
110         logger.info("Enter: bootstrapDatabase() Creating new EAB database");
111         upgradeDatabase(db, 0, EAB_DB_VERSION);
112         logger.info("Exit: bootstrapDatabase()");
113     }
114 
115     /*
116      * In upgradeDatabase,
117      * oldVersion - the current version of Provider on the phone.
118      * newVersion - the version of Provider where the phone will be upgraded to.
119      */
120     @Override
upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion)121     public boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
122         logger.debug("Enter: upgradeDatabase() - oldVersion = " + oldVersion +
123                 " newVersion = " + newVersion);
124 
125         if (oldVersion == newVersion) {
126             logger.debug("upgradeDatabase oldVersion == newVersion, No Upgrade Required");
127             return true;
128         }
129 
130         try {
131             if (oldVersion == 0) {
132                 db.execSQL(EAB_CREATE_STATEMENT);
133 
134                 oldVersion++;
135                 logger.debug("upgradeDatabase : DB has been upgraded to " + oldVersion);
136             }
137             if (oldVersion == 1) {
138                 addColumn(db, EABContract.EABColumns.TABLE_NAME,
139                         EABContract.EABColumns.VOLTE_STATUS, "INTEGER NOT NULL DEFAULT -1");
140 
141                 oldVersion++;
142                 logger.debug("upgradeDatabase : DB has been upgraded to " + oldVersion);
143             }
144         } catch (SQLException exception) {
145             logger.error("Exception during upgradeDatabase. " + exception.getMessage());
146             // DB file had problem
147             throw new InvalidDBException();
148         }
149 
150         // add further upgrade code above this
151         if (oldVersion == newVersion) {
152             logger.debug("DB upgrade complete : to " + newVersion);
153         }
154 
155         logger.debug("Exit: upgradeDatabase()");
156         return true;
157     }
158 
159     @Override
downgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion)160     protected boolean downgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
161         // throwing the custom created Exception to catch it in
162         // getWritableDatabase or getReadableDatabase
163         throw new InvalidDBException();
164     }
165 
166     @Override
deleteInternal(SQLiteDatabase db, Uri uri, String selection, String[] selectionArgs)167     protected int deleteInternal(SQLiteDatabase db, Uri uri, String selection,
168             String[] selectionArgs) {
169         logger.info("Enter: deleteInternal()");
170         final int match = URI_MATCHER.match(uri);
171         String table = null;
172         switch (match) {
173             case EAB_TABLE_ID:
174                 if (selection == null) {
175                     selection = "_id=?";
176                     selectionArgs = new String[] {uri.getPathSegments().get(1)};
177                 }
178             case EAB_TABLE:
179                 table = EABContract.EABColumns.TABLE_NAME;
180                 break;
181             default:
182                 logger.info("No match for " + uri);
183                 logger.info("Exit: deleteInternal()");
184                 return 0;
185         }
186         logger.debug("Deleting from the table" + table + " selection= " + selection);
187         printDeletingValues(uri, selection, selectionArgs);
188         logger.info("Exit: deleteInternal()");
189         return db.delete(table, selection, selectionArgs);
190     }
191 
192     @Override
insertInternal(SQLiteDatabase db, Uri uri, ContentValues values)193     protected Uri insertInternal(SQLiteDatabase db, Uri uri, ContentValues values) {
194         logger.info("Enter: insertInternal()");
195         final int match = URI_MATCHER.match(uri);
196         String table = null;
197         String nullColumnHack = null;
198         switch (match) {
199             case EAB_TABLE:
200                 table = EABContract.EABColumns.TABLE_NAME;
201                 break;
202             default:
203                 logger.warn("No match for " + uri);
204                 logger.info("Exit: insertInternal() with null");
205                 return null;
206         }
207         values = verifyIfMdnExists(values);
208         // Do the insert.
209         logger.debug("Inserting to the table" + table + " values=" + values.toString());
210 
211         final long id = db.insert(table, nullColumnHack, values);
212         if (id > 0) {
213             String contactNumber = values.getAsString(EABContract.EABColumns.CONTACT_NUMBER);
214             sendInsertBroadcast(contactNumber);
215             logger.info("Exit: insertInternal()");
216             return ContentUris.withAppendedId(uri, id);
217         } else {
218             logger.info("Exit: insertInternal() with null");
219             return null;
220         }
221     }
222 
223     @Override
queryInternal(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)224     protected Cursor queryInternal(SQLiteDatabase db, Uri uri, String[] projection,
225             String selection, String[] selectionArgs, String sortOrder) {
226         logger.info("Enter: queryInternal()");
227         final int match = URI_MATCHER.match(uri);
228 
229         switch (match) {
230             case EAB_TABLE_ID:
231                 long id = ContentUris.parseId(uri);
232                 logger.debug("queryInternal id=" + id);
233                 String idSelection = BaseColumns._ID + "=" + id;
234                 if(null != selection) {
235                     selection = "((" + idSelection + ") AND (" + selection + "))";
236                 } else {
237                     selection = idSelection;
238                 }
239                 break;
240             case EAB_GROUPITEMS_TABLE:
241                 SQLiteQueryBuilder sqb = new SQLiteQueryBuilder();
242                 sqb.setTables(EABContract.EABColumns.TABLE_NAME);
243                 String rawquery = "select DISTINCT " + EABContract.EABColumns.CONTACT_ID
244                         + " from " + EABContract.EABColumns.TABLE_NAME
245                         + " where " + EABContract.EABColumns.VOLTE_CALL_CAPABILITY + " >'" +
246                         RcsPresenceInfo.ServiceState.OFFLINE+"' AND "
247                         + EABContract.EABColumns.VIDEO_CALL_CAPABILITY + " >'"
248                         + RcsPresenceInfo.ServiceState.OFFLINE + "'";
249                 StringBuffer sb = new StringBuffer();
250                 Cursor cursor = db.rawQuery(rawquery, null);
251                 if (cursor != null && cursor.moveToFirst()) {
252                     do {
253                         if (sb.length() != 0) sb.append(",");
254                         String contactId = cursor.getString(cursor
255                                 .getColumnIndex(EABContract.EABColumns.CONTACT_ID));
256                         sb.append(contactId);
257                     } while (cursor.moveToNext());
258                 }
259                 if (cursor != null) cursor.close();
260                 String contactSel = Contacts._ID + " IN ( " + sb.toString() + ")";
261                 return getContext().getContentResolver().query(Contacts.CONTENT_URI, projection,
262                                 contactSel, null, sortOrder);
263         }
264 
265         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
266 
267         String groupBy = uri.getQueryParameter("groupby");
268         String having = null;
269 
270         switch (match) {
271             case EAB_TABLE:
272             case EAB_TABLE_ID:
273                 qb.setTables(EABContract.EABColumns.TABLE_NAME);
274                 break;
275             default:
276                 logger.warn("No match for " + uri);
277                 logger.info("Exit: queryInternal()");
278                 return null;
279         }
280         logger.info("Exit: queryInternal()");
281         return qb.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder);
282     }
283 
284     @Override
updateInternal(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs)285     protected int updateInternal(SQLiteDatabase db, Uri uri, ContentValues values,
286             String selection, String[] selectionArgs) {
287         logger.info("Enter: updateInternal()");
288         int result = 0;
289         final int match = URI_MATCHER.match(uri);
290 
291         switch (match) {
292             case EAB_TABLE_ID:
293                 long id = ContentUris.parseId(uri);
294                 logger.debug("updateInternal id=" + id);
295                 String idSelection = BaseColumns._ID + "=" + id;
296                 if(null != selection){
297                     selection = "((" + idSelection + ") AND (" + selection + "))";
298                 } else {
299                     selection = idSelection;
300                 }
301                 break;
302         }
303 
304         String table = null;
305         switch (match) {
306             case EAB_TABLE:
307             case EAB_TABLE_ID:
308                 table = EABContract.EABColumns.TABLE_NAME;
309                 break;
310             default:
311                 logger.warn("No match for " + uri);
312                 break;
313         }
314 
315         if (table != null && values != null) {
316             logger.debug("Updating the table " + table + " values= " + values.toString());
317             result = db.update(table, values, selection, selectionArgs);
318         }
319         logger.info("Exit: updateInternal()");
320         return result;
321     }
322 
323     @Override
getType(Uri uri)324     public String getType(Uri uri) {
325         logger.info("Enter: getType()");
326         final int match = URI_MATCHER.match(uri);
327         switch (match) {
328             case EAB_TABLE:
329                 return EABContract.EABColumns.CONTENT_TYPE;
330             case EAB_TABLE_ID:
331                 return EABContract.EABColumns.CONTENT_ITEM_TYPE;
332             default:
333                 throw (new IllegalArgumentException("EABProvider URI: " + uri));
334         }
335     }
336 
337     @Override
openFile(Uri uri, String mode)338     public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
339         return null;
340     }
341 
sendInsertBroadcast(String contactNumber)342     private void sendInsertBroadcast(String contactNumber) {
343         Intent intent = new Intent(com.android.service.ims.presence.Contacts
344             .ACTION_NEW_CONTACT_INSERTED);
345         ComponentName component = new ComponentName("com.android.service.ims.presence",
346                 "com.android.service.ims.presence.AlarmBroadcastReceiver");
347         intent.setComponent(component);
348 
349         intent.putExtra(com.android.service.ims.presence.Contacts.NEW_PHONE_NUMBER, contactNumber);
350         getContext().sendBroadcast(intent);
351     }
352 
verifyIfMdnExists(ContentValues cvalues)353     private ContentValues verifyIfMdnExists(ContentValues cvalues) {
354         String phoneNumber = null;
355         if (cvalues.containsKey(EABContract.EABColumns.CONTACT_NUMBER)) {
356             phoneNumber = cvalues.getAsString(EABContract.EABColumns.CONTACT_NUMBER);
357         } else {
358             return cvalues;
359         }
360         if (null == phoneNumber) {
361             return cvalues;
362         }
363         String[] projection = new String[] {
364                 EABContract.EABColumns.VOLTE_CALL_SERVICE_CONTACT_ADDRESS,
365                 EABContract.EABColumns.VOLTE_CALL_CAPABILITY,
366                 EABContract.EABColumns.VOLTE_CALL_CAPABILITY_TIMESTAMP,
367                 EABContract.EABColumns.VOLTE_CALL_AVAILABILITY,
368                 EABContract.EABColumns.VOLTE_CALL_AVAILABILITY_TIMESTAMP,
369                 EABContract.EABColumns.VIDEO_CALL_SERVICE_CONTACT_ADDRESS,
370                 EABContract.EABColumns.VIDEO_CALL_CAPABILITY,
371                 EABContract.EABColumns.VIDEO_CALL_CAPABILITY_TIMESTAMP,
372                 EABContract.EABColumns.VIDEO_CALL_AVAILABILITY,
373                 EABContract.EABColumns.VIDEO_CALL_AVAILABILITY_TIMESTAMP};
374         String whereClause = "PHONE_NUMBERS_EQUAL(" +
375                 EABContract.EABColumns.CONTACT_NUMBER + ", ?, 0)";
376         String[] selectionArgs = new String[] { phoneNumber };
377         Cursor cursor = getContext().getContentResolver().query(EABContract.EABColumns.CONTENT_URI,
378                         projection, whereClause, selectionArgs, null);
379         if ((null != cursor) && (cursor.getCount() > 0)) {
380             logger.error("Inserting another copy of MDN to EAB DB.");
381             // Update data only from first cursor element.
382             cursor.moveToNext();
383             cvalues.put(EABContract.EABColumns.VOLTE_CALL_SERVICE_CONTACT_ADDRESS,
384                     cursor.getString(cursor.
385                     getColumnIndex(EABContract.EABColumns.VOLTE_CALL_SERVICE_CONTACT_ADDRESS)));
386             cvalues.put(EABContract.EABColumns.VOLTE_CALL_CAPABILITY, cursor.getString(cursor
387                     .getColumnIndex(EABContract.EABColumns.VOLTE_CALL_CAPABILITY)));
388             cvalues.put(EABContract.EABColumns.VOLTE_CALL_CAPABILITY_TIMESTAMP,
389                     cursor.getLong(cursor
390                     .getColumnIndex(EABContract.EABColumns.VOLTE_CALL_CAPABILITY_TIMESTAMP)));
391             cvalues.put(EABContract.EABColumns.VOLTE_CALL_AVAILABILITY, cursor.getString(cursor
392                     .getColumnIndex(EABContract.EABColumns.VOLTE_CALL_AVAILABILITY)));
393             cvalues.put(EABContract.EABColumns.VOLTE_CALL_AVAILABILITY_TIMESTAMP,
394                     cursor.getLong(cursor
395                     .getColumnIndex(EABContract.EABColumns.VOLTE_CALL_AVAILABILITY_TIMESTAMP)));
396             cvalues.put(EABContract.EABColumns.VIDEO_CALL_SERVICE_CONTACT_ADDRESS,
397                     cursor.getString(cursor
398                     .getColumnIndex(EABContract.EABColumns.VIDEO_CALL_SERVICE_CONTACT_ADDRESS)));
399             cvalues.put(EABContract.EABColumns.VIDEO_CALL_CAPABILITY, cursor.getString(cursor
400                     .getColumnIndex(EABContract.EABColumns.VIDEO_CALL_CAPABILITY)));
401             cvalues.put(EABContract.EABColumns.VIDEO_CALL_CAPABILITY_TIMESTAMP,
402                     cursor.getLong(cursor
403                     .getColumnIndex(EABContract.EABColumns.VIDEO_CALL_CAPABILITY_TIMESTAMP)));
404             cvalues.put(EABContract.EABColumns.VIDEO_CALL_AVAILABILITY, cursor.getString(cursor
405                     .getColumnIndex(EABContract.EABColumns.VIDEO_CALL_AVAILABILITY)));
406             cvalues.put(EABContract.EABColumns.VIDEO_CALL_AVAILABILITY_TIMESTAMP,
407                     cursor.getLong(cursor
408                     .getColumnIndex(EABContract.EABColumns.VIDEO_CALL_AVAILABILITY_TIMESTAMP)));
409             cvalues.put(EABContract.EABColumns.CONTACT_LAST_UPDATED_TIMESTAMP, 0);
410         }
411         if (null != cursor) {
412             cursor.close();
413         }
414         return cvalues;
415     }
416 
printDeletingValues(Uri uri, String selection, String[] selectionArgs)417     private void printDeletingValues(Uri uri, String selection, String[] selectionArgs) {
418         String[] projection = new String[] {
419                 EABContract.EABColumns.CONTACT_NUMBER,
420                 EABContract.EABColumns.CONTACT_NAME,
421                 EABContract.EABColumns.RAW_CONTACT_ID,
422                 EABContract.EABColumns.CONTACT_ID,
423                 EABContract.EABColumns.DATA_ID};
424         Cursor cursor = getContext().getContentResolver().query(EABContract.EABColumns.CONTENT_URI,
425                         projection, selection, selectionArgs, null);
426         if ((null != cursor) && (cursor.getCount() > 0)) {
427             logger.debug("Before deleting the cursor count is " + cursor.getCount());
428             // Update data only from first cursor element.
429             while (cursor.moveToNext()) {
430                 long dataId = cursor.getLong(cursor.getColumnIndex(
431                         EABContract.EABColumns.DATA_ID));
432                 long contactId = cursor.getLong(cursor.getColumnIndex(
433                         EABContract.EABColumns.CONTACT_ID));
434                 long rawContactId = cursor.getLong(cursor.getColumnIndex(
435                         EABContract.EABColumns.RAW_CONTACT_ID));
436                 String phoneNumber = cursor.getString(cursor.getColumnIndex(
437                         EABContract.EABColumns.CONTACT_NUMBER));
438                 String displayName = cursor.getString(cursor.getColumnIndex(
439                         EABContract.EABColumns.CONTACT_NAME));
440             }
441         } else {
442             logger.error("cursor is null!");
443         }
444         if (null != cursor) {
445             cursor.close();
446         }
447     }
448 }
449