2 * Copyright (C) 2006 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.internal.telephony;
19 import android.content.ContentProvider;
20 import android.content.UriMatcher;
21 import android.content.ContentValues;
22 import android.database.Cursor;
23 import android.database.MatrixCursor;
24 import android.net.Uri;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
27 import android.text.TextUtils;
28 import android.util.Log;
30 import java.util.List;
32 import com.android.internal.telephony.IccConstants;
33 import com.android.internal.telephony.AdnRecord;
34 import com.android.internal.telephony.IIccPhoneBook;
40 public class IccProvider extends ContentProvider {
41 private static final String TAG = "IccProvider";
42 private static final boolean DBG = false;
45 private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
52 private static final int ADN = 1;
53 private static final int FDN = 2;
54 private static final int SDN = 3;
56 private static final String STR_TAG = "tag";
57 private static final String STR_NUMBER = "number";
58 private static final String STR_EMAILS = "emails";
59 private static final String STR_PIN2 = "pin2";
61 private static final UriMatcher URL_MATCHER =
62 new UriMatcher(UriMatcher.NO_MATCH);
65 URL_MATCHER.addURI("icc", "adn", ADN);
66 URL_MATCHER.addURI("icc", "fdn", FDN);
67 URL_MATCHER.addURI("icc", "sdn", SDN);
72 public boolean onCreate() {
77 public Cursor query(Uri url, String[] projection, String selection,
78 String[] selectionArgs, String sort) {
79 switch (URL_MATCHER.match(url)) {
81 return loadFromEf(IccConstants.EF_ADN);
84 return loadFromEf(IccConstants.EF_FDN);
87 return loadFromEf(IccConstants.EF_SDN);
90 throw new IllegalArgumentException("Unknown URL " + url);
95 public String getType(Uri url) {
96 switch (URL_MATCHER.match(url)) {
100 return "vnd.android.cursor.dir/sim-contact";
103 throw new IllegalArgumentException("Unknown URL " + url);
108 public Uri insert(Uri url, ContentValues initialValues) {
113 if (DBG) log("insert");
115 int match = URL_MATCHER.match(url);
118 efType = IccConstants.EF_ADN;
122 efType = IccConstants.EF_FDN;
123 pin2 = initialValues.getAsString("pin2");
127 throw new UnsupportedOperationException(
128 "Cannot insert into URL: " + url);
131 String tag = initialValues.getAsString("tag");
132 String number = initialValues.getAsString("number");
133 // TODO(): Read email instead of sending null.
134 boolean success = addIccRecordToEf(efType, tag, number, null, pin2);
140 StringBuilder buf = new StringBuilder("content://icc/");
151 // TODO: we need to find out the rowId for the newly added record
154 resultUri = Uri.parse(buf.toString());
157 // notify interested parties that an insertion happened
158 getContext().getContentResolver().notifyInsert(
159 resultUri, rowID, null);
165 private String normalizeValue(String inVal) {
166 int len = inVal.length();
167 String retVal = inVal;
169 if (inVal.charAt(0) == '\'' && inVal.charAt(len-1) == '\'') {
170 retVal = inVal.substring(1, len-1);
177 public int delete(Uri url, String where, String[] whereArgs) {
180 if (DBG) log("delete");
182 int match = URL_MATCHER.match(url);
185 efType = IccConstants.EF_ADN;
189 efType = IccConstants.EF_FDN;
193 throw new UnsupportedOperationException(
194 "Cannot insert into URL: " + url);
197 // parse where clause
199 String number = null;
200 String[] emails = null;
203 String[] tokens = where.split("AND");
204 int n = tokens.length;
207 String param = tokens[n];
208 if (DBG) log("parsing '" + param + "'");
210 String[] pair = param.split("=");
212 if (pair.length != 2) {
213 Log.e(TAG, "resolve: bad whereClause parameter: " + param);
217 String key = pair[0].trim();
218 String val = pair[1].trim();
220 if (STR_TAG.equals(key)) {
221 tag = normalizeValue(val);
222 } else if (STR_NUMBER.equals(key)) {
223 number = normalizeValue(val);
224 } else if (STR_EMAILS.equals(key)) {
225 //TODO(): Email is null.
227 } else if (STR_PIN2.equals(key)) {
228 pin2 = normalizeValue(val);
232 if (TextUtils.isEmpty(number)) {
236 if (efType == IccConstants.EF_FDN && TextUtils.isEmpty(pin2)) {
240 boolean success = deleteIccRecordFromEf(efType, tag, number, emails, pin2);
249 public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
253 if (DBG) log("update");
255 int match = URL_MATCHER.match(url);
258 efType = IccConstants.EF_ADN;
262 efType = IccConstants.EF_FDN;
263 pin2 = values.getAsString("pin2");
267 throw new UnsupportedOperationException(
268 "Cannot insert into URL: " + url);
271 String tag = values.getAsString("tag");
272 String number = values.getAsString("number");
273 String[] emails = null;
274 String newTag = values.getAsString("newTag");
275 String newNumber = values.getAsString("newNumber");
276 String[] newEmails = null;
277 // TODO(): Update for email.
278 boolean success = updateIccRecordInEf(efType, tag, number,
279 newTag, newNumber, pin2);
288 private MatrixCursor loadFromEf(int efType) {
289 if (DBG) log("loadFromEf: efType=" + efType);
291 List<AdnRecord> adnRecords = null;
293 IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
294 ServiceManager.getService("simphonebook"));
295 if (iccIpb != null) {
296 adnRecords = iccIpb.getAdnRecordsInEf(efType);
298 } catch (RemoteException ex) {
300 } catch (SecurityException ex) {
301 if (DBG) log(ex.toString());
304 if (adnRecords != null) {
306 final int N = adnRecords.size();
307 final MatrixCursor cursor = new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES, N);
308 if (DBG) log("adnRecords.size=" + N);
309 for (int i = 0; i < N ; i++) {
310 loadRecord(adnRecords.get(i), cursor, i);
314 // No results to load
315 Log.w(TAG, "Cannot load ADN records");
316 return new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES);
321 addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {
322 if (DBG) log("addIccRecordToEf: efType=" + efType + ", name=" + name +
323 ", number=" + number + ", emails=" + emails);
325 boolean success = false;
327 // TODO: do we need to call getAdnRecordsInEf() before calling
328 // updateAdnRecordsInEfBySearch()? In any case, we will leave
329 // the UI level logic to fill that prereq if necessary. But
330 // hopefully, we can remove this requirement.
333 IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
334 ServiceManager.getService("simphonebook"));
335 if (iccIpb != null) {
336 success = iccIpb.updateAdnRecordsInEfBySearch(efType, "", "",
339 } catch (RemoteException ex) {
341 } catch (SecurityException ex) {
342 if (DBG) log(ex.toString());
344 if (DBG) log("addIccRecordToEf: " + success);
349 updateIccRecordInEf(int efType, String oldName, String oldNumber,
350 String newName, String newNumber, String pin2) {
351 if (DBG) log("updateIccRecordInEf: efType=" + efType +
352 ", oldname=" + oldName + ", oldnumber=" + oldNumber +
353 ", newname=" + newName + ", newnumber=" + newNumber);
354 boolean success = false;
357 IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
358 ServiceManager.getService("simphonebook"));
359 if (iccIpb != null) {
360 success = iccIpb.updateAdnRecordsInEfBySearch(efType,
361 oldName, oldNumber, newName, newNumber, pin2);
363 } catch (RemoteException ex) {
365 } catch (SecurityException ex) {
366 if (DBG) log(ex.toString());
368 if (DBG) log("updateIccRecordInEf: " + success);
373 private boolean deleteIccRecordFromEf(int efType, String name, String number, String[] emails,
375 if (DBG) log("deleteIccRecordFromEf: efType=" + efType +
376 ", name=" + name + ", number=" + number + ", emails=" + emails + ", pin2=" + pin2);
378 boolean success = false;
381 IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
382 ServiceManager.getService("simphonebook"));
383 if (iccIpb != null) {
384 success = iccIpb.updateAdnRecordsInEfBySearch(efType,
385 name, number, "", "", pin2);
387 } catch (RemoteException ex) {
389 } catch (SecurityException ex) {
390 if (DBG) log(ex.toString());
392 if (DBG) log("deleteIccRecordFromEf: " + success);
397 * Loads an AdnRecord into a MatrixCursor. Must be called with mLock held.
399 * @param record the ADN record to load from
400 * @param cursor the cursor to receive the results
402 private void loadRecord(AdnRecord record, MatrixCursor cursor, int id) {
403 if (!record.isEmpty()) {
404 Object[] contact = new Object[4];
405 String alphaTag = record.getAlphaTag();
406 String number = record.getNumber();
408 if (DBG) log("loadRecord: " + alphaTag + ", " + number + ",");
409 contact[0] = alphaTag;
412 String[] emails = record.getEmails();
413 if (emails != null) {
414 StringBuilder emailString = new StringBuilder();
415 for (String email: emails) {
416 if (DBG) log("Adding email:" + email);
417 emailString.append(email);
418 emailString.append(",");
420 contact[2] = emailString.toString();
423 cursor.addRow(contact);
427 private void log(String msg) {
428 Log.d(TAG, "[IccProvider] " + msg);