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
18package com.android.providers.telephony;
19
20import android.content.ContentProvider;
21import android.content.ContentUris;
22import android.content.ContentValues;
23import android.content.UriMatcher;
24import android.database.sqlite.SQLiteDatabase;
25import android.database.sqlite.SQLiteQueryBuilder;
26import android.database.Cursor;
27import android.database.SQLException;
28import android.net.Uri;
29import android.text.TextUtils;
30import android.util.Log;
31import java.util.HashMap;
32
33import com.android.internal.telephony.HbpcdLookup;
34import com.android.internal.telephony.HbpcdLookup.MccIdd;
35import com.android.internal.telephony.HbpcdLookup.MccLookup;
36import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
37import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
38import com.android.internal.telephony.HbpcdLookup.MccSidRange;
39import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
40
41public 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 {
75        sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD, MCC_IDD);
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.
79        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
80                HbpcdLookup.PATH_MCC_SID_CONFLICT, MCC_SID_CONFLICT);
81        sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_SID_RANGE, MCC_SID_RANGE);
82        sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_NANP_AREA_CODE, NANP_AREA_CODE);
83        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
84                HbpcdLookup.PATH_ARBITRARY_MCC_SID_MATCH, ARBITRARY_MCC_SID_MATCH);
85        sURIMatcher.addURI(HbpcdLookup.AUTHORITY, HbpcdLookup.PATH_MCC_IDD + "/#", MCC_IDD_ID);
86        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
87                HbpcdLookup.PATH_MCC_LOOKUP_TABLE + "/#", MCC_LOOKUP_TABLE_ID);
88        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
89                HbpcdLookup.PATH_MCC_SID_CONFLICT + "/#", MCC_SID_CONFLICT_ID);
90        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
91                HbpcdLookup.PATH_MCC_SID_RANGE + "/#", MCC_SID_RANGE_ID);
92        sURIMatcher.addURI(HbpcdLookup.AUTHORITY,
93                HbpcdLookup.PATH_NANP_AREA_CODE + "/#", NANP_AREA_CODE_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>();
98        sIddProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
99        sIddProjectionMap.put(MccIdd.MCC, MccIdd.MCC);
100        sIddProjectionMap.put(MccIdd.IDD, MccIdd.IDD);
101
102        sLookupProjectionMap = new HashMap<String, String>();
103        sLookupProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
104        sLookupProjectionMap.put(MccLookup.MCC, MccLookup.MCC);
105        sLookupProjectionMap.put(MccLookup.COUNTRY_CODE, MccLookup.COUNTRY_CODE);
106        sLookupProjectionMap.put(MccLookup.COUNTRY_NAME, MccLookup.COUNTRY_NAME);
107        sLookupProjectionMap.put(MccLookup.NDD, MccLookup.NDD);
108        sLookupProjectionMap.put(MccLookup.NANPS, MccLookup.NANPS);
109        sLookupProjectionMap.put(MccLookup.GMT_OFFSET_LOW, MccLookup.GMT_OFFSET_LOW);
110        sLookupProjectionMap.put(MccLookup.GMT_OFFSET_HIGH, MccLookup.GMT_OFFSET_HIGH);
111        sLookupProjectionMap.put(MccLookup.GMT_DST_LOW, MccLookup.GMT_DST_LOW);
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
117        sConflictProjectionMap.put(MccLookup.GMT_OFFSET_LOW,
118                TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_LOW);
119        sConflictProjectionMap.put(MccLookup.GMT_OFFSET_HIGH,
120                TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_OFFSET_HIGH);
121        sConflictProjectionMap.put(MccLookup.GMT_DST_LOW,
122                TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_LOW);
123        sConflictProjectionMap.put(MccLookup.GMT_DST_HIGH,
124                TABLE_MCC_LOOKUP_TABLE + "." + MccLookup.GMT_DST_HIGH);
125        sConflictProjectionMap.put(MccSidConflicts.MCC,
126                TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.MCC);
127        sConflictProjectionMap.put(MccSidConflicts.SID_CONFLICT,
128                TABLE_MCC_SID_CONFLICT + "." + MccSidConflicts.SID_CONFLICT);
129
130        sRangeProjectionMap = new HashMap<String, String>();
131        sRangeProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
132        sRangeProjectionMap.put(MccSidRange.MCC, MccSidRange.MCC);
133        sRangeProjectionMap.put(MccSidRange.RANGE_LOW, MccSidRange.RANGE_LOW);
134        sRangeProjectionMap.put(MccSidRange.RANGE_HIGH, MccSidRange.RANGE_HIGH);
135
136        sNanpProjectionMap = new HashMap<String, String>();
137        sNanpProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
138        sNanpProjectionMap.put(NanpAreaCode.AREA_CODE, NanpAreaCode.AREA_CODE);
139
140        sArbitraryProjectionMap = new HashMap<String, String>();
141        sArbitraryProjectionMap.put(HbpcdLookup.ID, HbpcdLookup.ID);
142        sArbitraryProjectionMap.put(ArbitraryMccSidMatch.MCC, ArbitraryMccSidMatch.MCC);
143        sArbitraryProjectionMap.put(ArbitraryMccSidMatch.SID, ArbitraryMccSidMatch.SID);
144    }
145
146    private HbpcdLookupDatabaseHelper mDbHelper;
147
148    @Override
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
160    public String getType(Uri uri) {
161        if (DBG) {
162            Log.d(TAG, "getType");
163        }
164
165        return null;
166    }
167
168    @Override
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
314    public Uri insert(Uri uri, ContentValues values) {
315        throw new UnsupportedOperationException("Failed to insert row into " + uri);
316    }
317
318    @Override
319    public int delete(Uri uri, String selection, String[] selectionArgs) {
320        throw new UnsupportedOperationException("Cannot delete URL: " + uri);
321    }
322
323    @Override
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