1 /*
2 **
3 ** Copyright (C) 2014, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 package com.android.providers.telephony;
19 
20 import android.content.ContentProvider;
21 import android.content.ContentUris;
22 import android.content.ContentValues;
23 import android.content.UriMatcher;
24 import android.database.sqlite.SQLiteDatabase;
25 import android.database.sqlite.SQLiteQueryBuilder;
26 import android.database.Cursor;
27 import android.database.SQLException;
28 import android.net.Uri;
29 import android.text.TextUtils;
30 import android.util.Log;
31 import java.util.HashMap;
32 
33 import com.android.internal.telephony.HbpcdLookup;
34 import com.android.internal.telephony.HbpcdLookup.MccIdd;
35 import com.android.internal.telephony.HbpcdLookup.MccLookup;
36 import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
37 import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
38 import com.android.internal.telephony.HbpcdLookup.MccSidRange;
39 import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
40 
41 public class HbpcdLookupProvider extends ContentProvider {
42     private static boolean DBG = false;
43     private static final String TAG = "HbpcdLookupProvider";
44 
45     public static final String TABLE_MCC_IDD = "mcc_idd";
46     public static final String TABLE_MCC_LOOKUP_TABLE = "mcc_lookup_table";
47     public static final String TABLE_MCC_SID_CONFLICT = "mcc_sid_conflict";
48     public static final String TABLE_MCC_SID_RANGE = "mcc_sid_range";
49     public static final String TABLE_NANP_AREA_CODE = "nanp_area_code";
50     public static final String TABLE_ARBITRARY_MCC_SID_MATCH= "arbitrary_mcc_sid_match";
51 
52     private static final int MCC_IDD = 1;
53     private static final int MCC_LOOKUP_TABLE = 2;
54     private static final int MCC_SID_CONFLICT = 3;
55     private static final int MCC_SID_RANGE = 4;
56     private static final int NANP_AREA_CODE = 5;
57     private static final int ARBITRARY_MCC_SID_MATCH = 6;
58     private static final int MCC_IDD_ID = 8;
59     private static final int MCC_LOOKUP_TABLE_ID = 9;
60     private static final int MCC_SID_CONFLICT_ID = 10;
61     private static final int MCC_SID_RANGE_ID = 11;
62     private static final int NANP_AREA_CODE_ID = 12;
63     private static final int ARBITRARY_MCC_SID_MATCH_ID = 13;
64 
65     private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
66 
67     private static final HashMap<String, String> sIddProjectionMap;
68     private static final HashMap<String, String> sLookupProjectionMap;
69     private static final HashMap<String, String> sConflictProjectionMap;
70     private static final HashMap<String, String> sRangeProjectionMap;
71     private static final HashMap<String, String> sNanpProjectionMap;
72     private static final HashMap<String, String> sArbitraryProjectionMap;
73 
74     static {
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD, MCC_IDD)75         sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD, MCC_IDD);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_LOOKUP_TABLE, MCC_LOOKUP_TABLE)76         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
77                 HbpcdLookup.PATH_MCC_LOOKUP_TABLE, MCC_LOOKUP_TABLE);
78         // following URI is a joint table of MCC_LOOKUP_TABLE and MCC_SID_CONFLIct.
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_CONFLICT, MCC_SID_CONFLICT)79         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
80                 HbpcdLookup.PATH_MCC_SID_CONFLICT, MCC_SID_CONFLICT);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_RANGE, MCC_SID_RANGE)81         sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_RANGE, MCC_SID_RANGE);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_NANP_AREA_CODE, NANP_AREA_CODE)82         sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_NANP_AREA_CODE, NANP_AREA_CODE);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_ARBITRARY_MCC_SID_MATCH, ARBITRARY_MCC_SID_MATCH)83         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
84                 HbpcdLookup.PATH_ARBITRARY_MCC_SID_MATCH, ARBITRARY_MCC_SID_MATCH);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD + "/#", MCC_IDD_ID)85         sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD + "/#", MCC_IDD_ID);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_LOOKUP_TABLE + "/#", MCC_LOOKUP_TABLE_ID)86         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
87                 HbpcdLookup.PATH_MCC_LOOKUP_TABLE + "/#", MCC_LOOKUP_TABLE_ID);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_CONFLICT + "/#", MCC_SID_CONFLICT_ID)88         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
89                 HbpcdLookup.PATH_MCC_SID_CONFLICT + "/#", MCC_SID_CONFLICT_ID);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_RANGE + "/#", MCC_SID_RANGE_ID)90         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
91                 HbpcdLookup.PATH_MCC_SID_RANGE + "/#", MCC_SID_RANGE_ID);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_NANP_AREA_CODE + "/#", NANP_AREA_CODE_ID)92         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
93                 HbpcdLookup.PATH_NANP_AREA_CODE + "/#", NANP_AREA_CODE_ID);
sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_ARBITRARY_MCC_SID_MATCH + "/#", ARBITRARY_MCC_SID_MATCH_ID)94         sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
95                 HbpcdLookup.PATH_ARBITRARY_MCC_SID_MATCH + "/#", ARBITRARY_MCC_SID_MATCH_ID);
96 
97         sIddProjectionMap = new HashMap<String, String>();
sIddProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID)98         sIddProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
sIddProjectionMap.put(MccIdd.MCC, MccIdd.MCC)99         sIddProjectionMap.put(MccIdd.MCC, MccIdd.MCC);
sIddProjectionMap.put(MccIdd.IDD, MccIdd.IDD)100         sIddProjectionMap.put(MccIdd.IDD, MccIdd.IDD);
101 
102         sLookupProjectionMap = new HashMap<String, String>();
sLookupProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID)103         sLookupProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
sLookupProjectionMap.put(MccLookup.MCC, MccLookup.MCC)104         sLookupProjectionMap.put(MccLookup.MCC, MccLookup.MCC);
sLookupProjectionMap.put(MccLookup.COUNTRY_CODE, MccLookup.COUNTRY_CODE)105         sLookupProjectionMap.put(MccLookup.COUNTRY_CODE, MccLookup.COUNTRY_CODE);
sLookupProjectionMap.put(MccLookup.COUNTRY_NAME, MccLookup.COUNTRY_NAME)106         sLookupProjectionMap.put(MccLookup.COUNTRY_NAME, MccLookup.COUNTRY_NAME);
sLookupProjectionMap.put(MccLookup.NDD, MccLookup.NDD)107         sLookupProjectionMap.put(MccLookup.NDD, MccLookup.NDD);
sLookupProjectionMap.put(MccLookup.NANPS, MccLookup.NANPS)108         sLookupProjectionMap.put(MccLookup.NANPS, MccLookup.NANPS);
sLookupProjectionMap.put(MccLookup.GMT_OFFSET_LOW, MccLookup.GMT_OFFSET_LOW)109         sLookupProjectionMap.put(MccLookup.GMT_OFFSET_LOW, MccLookup.GMT_OFFSET_LOW);
sLookupProjectionMap.put(MccLookup.GMT_OFFSET_HIGH, MccLookup.GMT_OFFSET_HIGH)110         sLookupProjectionMap.put(MccLookup.GMT_OFFSET_HIGH, MccLookup.GMT_OFFSET_HIGH);
sLookupProjectionMap.put(MccLookup.GMT_DST_LOW, MccLookup.GMT_DST_LOW)111         sLookupProjectionMap.put(MccLookup.GMT_DST_LOW, MccLookup.GMT_DST_LOW);
sLookupProjectionMap.put(MccLookup.GMT_DST_HIGH, MccLookup.GMT_DST_HIGH)112         sLookupProjectionMap.put(MccLookup.GMT_DST_HIGH, MccLookup.GMT_DST_HIGH);
113 
114         // when we do query, we will join it with MccLookup table
115         sConflictProjectionMap = new HashMap<String, String>();
116         // MccLookup.MCC is duped to MccSidConflicts.MCC
sConflictProjectionMap.put(MccLookup.GMT_OFFSET_LOW, TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_LOW)117         sConflictProjectionMap.put(MccLookup.GMT_OFFSET_LOW,
118                 TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_LOW);
sConflictProjectionMap.put(MccLookup.GMT_OFFSET_HIGH, TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_HIGH)119         sConflictProjectionMap.put(MccLookup.GMT_OFFSET_HIGH,
120                 TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_HIGH);
sConflictProjectionMap.put(MccLookup.GMT_DST_LOW, TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_LOW)121         sConflictProjectionMap.put(MccLookup.GMT_DST_LOW,
122                 TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_LOW);
sConflictProjectionMap.put(MccLookup.GMT_DST_HIGH, TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_HIGH)123         sConflictProjectionMap.put(MccLookup.GMT_DST_HIGH,
124                 TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_HIGH);
sConflictProjectionMap.put(MccSidConflicts.MCC, TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.MCC)125         sConflictProjectionMap.put(MccSidConflicts.MCC,
126                 TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.MCC);
sConflictProjectionMap.put(MccSidConflicts.SID_CONFLICT, TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.SID_CONFLICT)127         sConflictProjectionMap.put(MccSidConflicts.SID_CONFLICT,
128                 TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.SID_CONFLICT);
129 
130         sRangeProjectionMap = new HashMap<String, String>();
sRangeProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID)131         sRangeProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
sRangeProjectionMap.put(MccSidRange.MCC, MccSidRange.MCC)132         sRangeProjectionMap.put(MccSidRange.MCC, MccSidRange.MCC);
sRangeProjectionMap.put(MccSidRange.RANGE_LOW, MccSidRange.RANGE_LOW)133         sRangeProjectionMap.put(MccSidRange.RANGE_LOW, MccSidRange.RANGE_LOW);
sRangeProjectionMap.put(MccSidRange.RANGE_HIGH, MccSidRange.RANGE_HIGH)134         sRangeProjectionMap.put(MccSidRange.RANGE_HIGH, MccSidRange.RANGE_HIGH);
135 
136         sNanpProjectionMap = new HashMap<String, String>();
sNanpProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID)137         sNanpProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
sNanpProjectionMap.put(NanpAreaCode.AREA_CODE, NanpAreaCode.AREA_CODE)138         sNanpProjectionMap.put(NanpAreaCode.AREA_CODE, NanpAreaCode.AREA_CODE);
139 
140         sArbitraryProjectionMap = new HashMap<String, String>();
sArbitraryProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID)141         sArbitraryProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
sArbitraryProjectionMap.put(ArbitraryMccSidMatch.MCC, ArbitraryMccSidMatch.MCC)142         sArbitraryProjectionMap.put(ArbitraryMccSidMatch.MCC, ArbitraryMccSidMatch.MCC);
sArbitraryProjectionMap.put(ArbitraryMccSidMatch.SID, ArbitraryMccSidMatch.SID)143         sArbitraryProjectionMap.put(ArbitraryMccSidMatch.SID, ArbitraryMccSidMatch.SID);
144     }
145 
146     private HbpcdLookupDatabaseHelper mDbHelper;
147 
148     @Override
onCreate()149     public boolean onCreate() {
150         if (DBG) {
151             Log.d(TAG, "onCreate");
152         }
153         mDbHelper = new HbpcdLookupDatabaseHelper(getContext());
154 
155         mDbHelper.getReadableDatabase();
156         return true;
157     }
158 
159     @Override
getType(Uri uri)160     public String getType(Uri uri) {
161         if (DBG) {
162             Log.d(TAG, "getType");
163         }
164 
165         return null;
166     }
167 
168     @Override
query(Uri uri, String[] projectionIn, String selection, String[] selectionArgs, String sortOrder)169     public Cursor query(Uri uri, String[] projectionIn, String selection,
170                         String[] selectionArgs, String sortOrder) {
171         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
172         String orderBy = null;
173         String groupBy = null;
174         boolean useDefaultOrder = TextUtils.isEmpty(sortOrder);
175 
176         int match = sURIMatcher.match(uri);
177         switch (match) {
178             case MCC_IDD: {
179                 qb.setTables(TABLE_MCC_IDD);
180                 qb.setProjectionMap(sIddProjectionMap);
181                 if (useDefaultOrder) {
182                     orderBy = MccIdd.DEFAULT_SORT_ORDER;
183                 }
184                 break;
185             }
186             case MCC_LOOKUP_TABLE: {
187                 qb.setTables(TABLE_MCC_LOOKUP_TABLE);
188                 qb.setProjectionMap(sLookupProjectionMap);
189                 if (useDefaultOrder) {
190                     orderBy = MccLookup.DEFAULT_SORT_ORDER;
191                 }
192                 groupBy = MccLookup.COUNTRY_NAME;
193                 break;
194             }
195             case MCC_SID_CONFLICT: {
196                 StringBuilder joinT = new StringBuilder();
197                 joinT.append(TABLE_MCC_LOOKUP_TABLE);
198                 joinT.append(" INNER JOIN ");
199                 joinT.append(TABLE_MCC_SID_CONFLICT);
200                 joinT.append(" ON (");
201                 joinT.append(TABLE_MCC_LOOKUP_TABLE); // table name
202                 joinT.append(".");
203                 joinT.append(MccLookup.MCC); // column name
204                 joinT.append(" = ");
205                 joinT.append(TABLE_MCC_SID_CONFLICT); // table name
206                 joinT.append(".");
207                 joinT.append(MccSidConflicts.MCC); //column name
208                 joinT.append(")");
209                 qb.setTables(joinT.toString());
210                 qb.setProjectionMap(sConflictProjectionMap);
211                 break;
212             }
213             case MCC_SID_RANGE: {
214                 qb.setTables(TABLE_MCC_SID_RANGE);
215                 qb.setProjectionMap(sRangeProjectionMap);
216                 if (useDefaultOrder) {
217                     orderBy = MccIdd.DEFAULT_SORT_ORDER;
218                 }
219                 break;
220             }
221             case NANP_AREA_CODE: {
222                 qb.setTables(TABLE_NANP_AREA_CODE);
223                 qb.setProjectionMap(sNanpProjectionMap);
224                 if (useDefaultOrder) {
225                     orderBy = NanpAreaCode.DEFAULT_SORT_ORDER;
226                 }
227                 break;
228             }
229             case ARBITRARY_MCC_SID_MATCH: {
230                 qb.setTables(TABLE_ARBITRARY_MCC_SID_MATCH);
231                 qb.setProjectionMap(sArbitraryProjectionMap);
232                 if (useDefaultOrder) {
233                     orderBy = ArbitraryMccSidMatch.DEFAULT_SORT_ORDER;
234                 }
235                 break;
236             }
237             case MCC_IDD_ID: {
238                 qb.setTables(TABLE_MCC_IDD);
239                 qb.setProjectionMap(sIddProjectionMap);
240                 qb.appendWhere(TABLE_MCC_IDD + "._id=");
241                 qb.appendWhere(uri.getPathSegments().get(1));
242                 if (useDefaultOrder) {
243                     orderBy = MccIdd.DEFAULT_SORT_ORDER;
244                 }
245                 break;
246             }
247             case MCC_LOOKUP_TABLE_ID: {
248                 qb.setTables(TABLE_MCC_LOOKUP_TABLE);
249                 qb.setProjectionMap(sLookupProjectionMap);
250                 qb.appendWhere(TABLE_MCC_LOOKUP_TABLE + "._id=");
251                 qb.appendWhere(uri.getPathSegments().get(1));
252                 if (useDefaultOrder) {
253                     orderBy = MccLookup.DEFAULT_SORT_ORDER;
254                 }
255                 break;
256             }
257             case MCC_SID_CONFLICT_ID: {
258                 qb.setTables(TABLE_MCC_SID_CONFLICT);
259                 qb.appendWhere(TABLE_MCC_SID_CONFLICT + "._id=");
260                 qb.appendWhere(uri.getPathSegments().get(1));
261                 if (useDefaultOrder) {
262                     orderBy = MccSidConflicts.DEFAULT_SORT_ORDER;
263                 }
264                 break;
265             }
266             case MCC_SID_RANGE_ID: {
267                 qb.setTables(TABLE_MCC_SID_RANGE);
268                 qb.setProjectionMap(sRangeProjectionMap);
269                 qb.appendWhere(TABLE_MCC_SID_RANGE + "._id=");
270                 qb.appendWhere(uri.getPathSegments().get(1));
271                 if (useDefaultOrder) {
272                     orderBy = MccIdd.DEFAULT_SORT_ORDER;
273                 }
274                 break;
275             }
276             case NANP_AREA_CODE_ID: {
277                 qb.setTables(TABLE_NANP_AREA_CODE);
278                 qb.setProjectionMap(sNanpProjectionMap);
279                 qb.appendWhere(TABLE_NANP_AREA_CODE + "._id=");
280                 qb.appendWhere(uri.getPathSegments().get(1));
281                 if (useDefaultOrder) {
282                     orderBy = NanpAreaCode.DEFAULT_SORT_ORDER;
283                 }
284                 break;
285             }
286             case ARBITRARY_MCC_SID_MATCH_ID: {
287                 qb.setTables(TABLE_ARBITRARY_MCC_SID_MATCH);
288                 qb.setProjectionMap(sArbitraryProjectionMap);
289                 qb.appendWhere(TABLE_ARBITRARY_MCC_SID_MATCH + "._id=");
290                 qb.appendWhere(uri.getPathSegments().get(1));
291                 if (useDefaultOrder) {
292                     orderBy = ArbitraryMccSidMatch.DEFAULT_SORT_ORDER;
293                 }
294                 break;
295             }
296             default:
297                 throw new IllegalArgumentException("Unknown URI " + uri);
298         }
299 
300         if (!useDefaultOrder) {
301             orderBy = sortOrder;
302         }
303 
304         SQLiteDatabase db = mDbHelper.getReadableDatabase();
305         Cursor c = qb.query(db, projectionIn, selection, selectionArgs, groupBy, null, orderBy);
306         if (c != null) {
307             c.setNotificationUri(getContext().getContentResolver(), uri);
308         }
309 
310         return c;
311     }
312 
313     @Override
insert(Uri uri, ContentValues values)314     public Uri insert(Uri uri, ContentValues values) {
315         throw new UnsupportedOperationException("Failed to insert row into " + uri);
316     }
317 
318     @Override
delete(Uri uri, String selection, String[] selectionArgs)319     public int delete(Uri uri, String selection, String[] selectionArgs) {
320         throw new UnsupportedOperationException("Cannot delete URL: " + uri);
321     }
322 
323     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)324     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
325         int count = 0;
326         final SQLiteDatabase db = mDbHelper.getWritableDatabase();
327 
328         final int match= sURIMatcher.match(uri);
329         switch (match) {
330             case MCC_LOOKUP_TABLE:
331                 count = db.update(TABLE_MCC_LOOKUP_TABLE, values, selection, selectionArgs);
332                 break;
333             default:
334                 throw new UnsupportedOperationException("Cannot update URL: " + uri);
335         }
336 
337         return count;
338     }
339 }
340