From 12e991ed26386d511ec4b93691f2c24cfb4f429b Mon Sep 17 00:00:00 2001 From: David James Date: Sun, 12 Jan 2014 14:51:02 -0600 Subject: [PATCH 1/3] Blacklist Change-Id: I1b96869e3089eb00bac62aca5c44481508bd0af0 --- AndroidManifest.xml | 8 +- .../telephony/BlacklistProvider.java | 368 ++++++++++++++++++ .../telephony/TelephonyBackupAgent.java | 256 ++++++++++++ 3 files changed, 631 insertions(+), 1 deletion(-) create mode 100644 src/com/android/providers/telephony/BlacklistProvider.java create mode 100644 src/com/android/providers/telephony/TelephonyBackupAgent.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7631950..d1b1728 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -24,7 +24,7 @@ @@ -33,6 +33,12 @@ android:exported="true" android:multiprocess="false" /> + + + 0) { + notifyChange(); + } + + return count; + } + + @Override + public int update(Uri uri, ContentValues initialValues, String where, String[] whereArgs) { + int count = 0; + int match = sURIMatcher.match(uri); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + + if (DEBUG) { + Log.v(TAG, "Update uri=" + uri + ", match=" + match); + } + + String uriNumber = match == BL_NUMBER ? uri.getLastPathSegment() : null; + ContentValues values = validateAndPrepareContentValues(initialValues, uriNumber); + if (values == null) { + Log.e(TAG, "Invalid update values " + initialValues); + return 0; + } + + switch (match) { + case BL_ALL: + count = db.update(BLACKLIST_TABLE, values, where, whereArgs); + break; + case BL_NUMBER: + if (where != null || whereArgs != null) { + throw new UnsupportedOperationException( + "Cannot update URI " + uri + " with a where clause"); + } + db.beginTransaction(); + try { + count = db.update(BLACKLIST_TABLE, values, COLUMN_NORMALIZED + " = ?", + new String[] { normalizeNumber(uriNumber) }); + if (count == 0) { + // convenience: fall back to insert if number wasn't present + if (db.insert(BLACKLIST_TABLE, null, values) > 0) { + count = 1; + } + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + break; + case BL_ID: + if (where != null || whereArgs != null) { + throw new UnsupportedOperationException( + "Cannot update URI " + uri + " with a where clause"); + } + count = db.update(BLACKLIST_TABLE, values, Blacklist._ID + " = ?", + new String[] { uri.getLastPathSegment() }); + break; + default: + throw new UnsupportedOperationException("Cannot update that URI: " + uri); + } + + if (DEBUG) Log.d(TAG, "Update result count " + count); + + if (count > 0) { + notifyChange(); + } + + return count; + } + + private ContentValues validateAndPrepareContentValues( + ContentValues initialValues, String uriNumber) { + ContentValues values = new ContentValues(initialValues); + + // apps are not supposed to mess with the normalized number or the regex state + values.remove(COLUMN_NORMALIZED); + values.remove(Blacklist.IS_REGEX); + + // on 'upsert', insert the number passed via URI if no other number was specified + if (uriNumber != null && !values.containsKey(Blacklist.NUMBER)) { + values.put(Blacklist.NUMBER, uriNumber); + } + + if (values.containsKey(Blacklist.NUMBER)) { + String number = values.getAsString(Blacklist.NUMBER); + if (TextUtils.isEmpty(number)) { + return null; + } + + String normalizedNumber = normalizeNumber(number); + boolean isRegex = normalizedNumber.indexOf('%') >= 0 + || normalizedNumber.indexOf('_') >= 0; + + values.put(COLUMN_NORMALIZED, normalizedNumber); + values.put(Blacklist.IS_REGEX, isRegex ? 1 : 0); + } + + return values; + } + + private void notifyChange() { + getContext().getContentResolver().notifyChange(Blacklist.CONTENT_URI, null); + mBackupManager.dataChanged(); + } + + // mostly a copy of PhoneNumberUtils.normalizeNumber, with the exception of + // not converting characters and support for regex characters + private String normalizeNumber(String number) { + int len = number.length(); + StringBuilder ret = new StringBuilder(len); + + for (int i = 0; i < len; i++) { + char c = number.charAt(i); + // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.) + int digit = Character.digit(c, 10); + if (digit != -1) { + ret.append(digit); + } else if (i == 0 && c == '+') { + ret.append(c); + } else if (c == '*') { + // replace regex match-multiple character by SQL equivalent + ret.append('%'); + } else if (c == '.') { + // replace regex-match-single character by SQL equivalent + ret.append('_'); + } + } + + return ret.toString(); + } +} diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java new file mode 100644 index 0000000..677efad --- /dev/null +++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.telephony; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; +import java.util.zip.CRC32; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.app.backup.BackupAgentHelper; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.provider.Telephony.Blacklist; +import android.text.TextUtils; +import android.util.Log; + +/** + * Performs backup and restore of the telephony data. + * At the moment this is restricted to the blacklist data. + */ +public class TelephonyBackupAgent extends BackupAgentHelper { + private static final String TAG = "TelephonyBackupAgent"; + + private static final String KEY_BLACKLIST = "blacklist"; + + private static final int STATE_BLACKLIST = 0; + private static final int STATE_SIZE = 1; + + private static final String SEPARATOR = "|"; + + private static final byte[] EMPTY_DATA = new byte[0]; + + private static final int COLUMN_NUMBER = 0; + private static final int COLUMN_PHONE_MODE = 1; + private static final int COLUMN_MESSAGE_MODE = 2; + + private static final String[] PROJECTION = { + Blacklist.NUMBER, + Blacklist.PHONE_MODE, + Blacklist.MESSAGE_MODE + }; + + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + byte[] blacklistData = getBlacklist(); + long[] stateChecksums = readOldChecksums(oldState); + + stateChecksums[STATE_BLACKLIST] = + writeIfChanged(stateChecksums[STATE_BLACKLIST], KEY_BLACKLIST, + blacklistData, data); + + writeNewChecksums(stateChecksums, newState); + } + + @Override + public void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) throws IOException { + while (data.readNextHeader()) { + final String key = data.getKey(); + final int size = data.getDataSize(); + if (KEY_BLACKLIST.equals(key)) { + restoreBlacklist(data); + } else { + data.skipEntityData(); + } + } + } + + private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException { + long[] stateChecksums = new long[STATE_SIZE]; + + DataInputStream dataInput = new DataInputStream( + new FileInputStream(oldState.getFileDescriptor())); + for (int i = 0; i < STATE_SIZE; i++) { + try { + stateChecksums[i] = dataInput.readLong(); + } catch (EOFException eof) { + break; + } + } + dataInput.close(); + return stateChecksums; + } + + private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState) + throws IOException { + DataOutputStream dataOutput = new DataOutputStream( + new FileOutputStream(newState.getFileDescriptor())); + for (int i = 0; i < STATE_SIZE; i++) { + dataOutput.writeLong(checksums[i]); + } + dataOutput.close(); + } + + private long writeIfChanged(long oldChecksum, String key, byte[] data, + BackupDataOutput output) { + CRC32 checkSummer = new CRC32(); + checkSummer.update(data); + long newChecksum = checkSummer.getValue(); + if (oldChecksum == newChecksum) { + return oldChecksum; + } + try { + output.writeEntityHeader(key, data.length); + output.writeEntityData(data, data.length); + } catch (IOException ioe) { + // Bail + } + return newChecksum; + } + + private byte[] getBlacklist() { + Cursor cursor = getContentResolver().query(Blacklist.CONTENT_URI, PROJECTION, + null, null, Blacklist.DEFAULT_SORT_ORDER); + if (cursor == null) { + return EMPTY_DATA; + } + if (!cursor.moveToFirst()) { + Log.e(TAG, "Couldn't read from the cursor"); + cursor.close(); + return EMPTY_DATA; + } + + byte[] sizeBytes = new byte[4]; + ByteArrayOutputStream baos = new ByteArrayOutputStream(cursor.getCount() * 20); + try { + GZIPOutputStream gzip = new GZIPOutputStream(baos); + while (!cursor.isAfterLast()) { + String number = cursor.getString(COLUMN_NUMBER); + int phoneMode = cursor.getInt(COLUMN_PHONE_MODE); + int messageMode = cursor.getInt(COLUMN_MESSAGE_MODE); + // TODO: escape the string + String out = number + SEPARATOR + phoneMode + SEPARATOR + messageMode; + byte[] line = out.getBytes(); + writeInt(sizeBytes, 0, line.length); + gzip.write(sizeBytes); + gzip.write(line); + cursor.moveToNext(); + } + gzip.finish(); + } catch (IOException ioe) { + Log.e(TAG, "Couldn't compress the blacklist", ioe); + return EMPTY_DATA; + } finally { + cursor.close(); + } + return baos.toByteArray(); + } + + private void restoreBlacklist(BackupDataInput data) { + ContentValues cv = new ContentValues(2); + byte[] blacklistCompressed = new byte[data.getDataSize()]; + byte[] blacklist = null; + try { + data.readEntityData(blacklistCompressed, 0, blacklistCompressed.length); + GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(blacklistCompressed)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] tempData = new byte[1024]; + int got; + while ((got = gzip.read(tempData)) > 0) { + baos.write(tempData, 0, got); + } + gzip.close(); + blacklist = baos.toByteArray(); + } catch (IOException ioe) { + Log.e(TAG, "Couldn't read and uncompress entity data", ioe); + return; + } + + int pos = 0; + while (pos + 4 < blacklist.length) { + int length = readInt(blacklist, pos); + pos += 4; + if (pos + length > blacklist.length) { + Log.e(TAG, "Insufficient data"); + } + String line = new String(blacklist, pos, length); + pos += length; + // TODO: unescape the string + StringTokenizer st = new StringTokenizer(line, SEPARATOR); + try { + String number = st.nextToken(); + int phoneMode = Integer.parseInt(st.nextToken()); + int messageMode = Integer.parseInt(st.nextToken()); + + if (!TextUtils.isEmpty(number)) { + cv.clear(); + cv.put(Blacklist.NUMBER, number); + cv.put(Blacklist.PHONE_MODE, phoneMode); + cv.put(Blacklist.MESSAGE_MODE, messageMode); + + Uri uri = Blacklist.CONTENT_FILTER_BYNUMBER_URI.buildUpon() + .appendPath(number).build(); + getContentResolver().update(uri, cv, null, null); + } + } catch (NoSuchElementException nsee) { + Log.e(TAG, "Token format error\n" + nsee); + } catch (NumberFormatException nfe) { + Log.e(TAG, "Number format error\n" + nfe); + } + } + } + + /** + * Write an int in BigEndian into the byte array. + * @param out byte array + * @param pos current pos in array + * @param value integer to write + * @return the index after adding the size of an int (4) + */ + private int writeInt(byte[] out, int pos, int value) { + out[pos + 0] = (byte) ((value >> 24) & 0xFF); + out[pos + 1] = (byte) ((value >> 16) & 0xFF); + out[pos + 2] = (byte) ((value >> 8) & 0xFF); + out[pos + 3] = (byte) ((value >> 0) & 0xFF); + return pos + 4; + } + + private int readInt(byte[] in, int pos) { + int result = + ((in[pos ] & 0xFF) << 24) | + ((in[pos + 1] & 0xFF) << 16) | + ((in[pos + 2] & 0xFF) << 8) | + ((in[pos + 3] & 0xFF) << 0); + return result; + } +} From de1e301cdc4ecebdeee0f65e46a8a305637dcec4 Mon Sep 17 00:00:00 2001 From: David James Date: Fri, 18 Apr 2014 17:57:14 -0500 Subject: [PATCH 2/3] Update Apr 18 Change-Id: I051c2a67b2a2ab918bcd6bbc189fdc5e004ee5a7 --- AndroidManifest.xml | 5 +- res/values/config.xml | 22 ++ .../telephony/BlacklistProvider.java | 41 +++- .../providers/telephony/MmsProvider.java | 30 ++- .../telephony/MmsSmsDatabaseHelper.java | 139 +++++------ .../providers/telephony/MmsSmsProvider.java | 5 +- .../providers/telephony/SmsProvider.java | 4 +- .../telephony/TelephonyProvider.java | 217 +++++++++++++++++- 8 files changed, 379 insertions(+), 84 deletions(-) create mode 100644 res/values/config.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d1b1728..06372d3 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -33,11 +33,12 @@ android:exported="true" android:multiprocess="false" /> - + android:multiprocess="true" + android:readPermission="android.permission.READ_PHONE_BLACKLIST" + android:writePermission="android.permission.CHANGE_PHONE_BLACKLIST" /> + + + + + + + diff --git a/src/com/android/providers/telephony/BlacklistProvider.java b/src/com/android/providers/telephony/BlacklistProvider.java index 050689a..44b3c92 100644 --- a/src/com/android/providers/telephony/BlacklistProvider.java +++ b/src/com/android/providers/telephony/BlacklistProvider.java @@ -29,6 +29,7 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.provider.Telephony.Blacklist; +import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.Log; @@ -37,7 +38,7 @@ public class BlacklistProvider extends ContentProvider { private static final boolean DEBUG = true; private static final String DATABASE_NAME = "blacklist.db"; - private static final int DATABASE_VERSION = 2; + private static final int DATABASE_VERSION = 3; private static final String BLACKLIST_TABLE = "blacklist"; private static final String COLUMN_NORMALIZED = "normalized_number"; @@ -90,6 +91,36 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("INSERT INTO " + BLACKLIST_TABLE + " SELECT * FROM " + BLACKLIST_TABLE + "_old;"); } + + if (oldVersion < 3) { + // update the normalized number column, v1 and v2 didn't handle + // alphanumeric 'numbers' correctly + + Cursor rows = db.query(BLACKLIST_TABLE, + new String[] { Blacklist._ID, Blacklist.NUMBER }, + null, null, null, null, null); + + try { + db.beginTransaction(); + if (rows != null) { + ContentValues cv = new ContentValues(); + String[] rowId = new String[1]; + + while (rows.moveToNext()) { + rowId[0] = rows.getString(0); + cv.clear(); + cv.put(COLUMN_NORMALIZED, normalizeNumber(rows.getString(1))); + db.update(BLACKLIST_TABLE, cv, Blacklist._ID + "= ?", rowId); + } + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (rows != null) { + rows.close(); + } + } + } } } @@ -340,9 +371,9 @@ private void notifyChange() { mBackupManager.dataChanged(); } - // mostly a copy of PhoneNumberUtils.normalizeNumber, with the exception of - // not converting characters and support for regex characters - private String normalizeNumber(String number) { + // mostly a copy of PhoneNumberUtils.normalizeNumber, + // with the exception of support for regex characters + private static String normalizeNumber(String number) { int len = number.length(); StringBuilder ret = new StringBuilder(len); @@ -352,6 +383,8 @@ private String normalizeNumber(String number) { int digit = Character.digit(c, 10); if (digit != -1) { ret.append(digit); + } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(number)); } else if (i == 0 && c == '+') { ret.append(c); } else if (c == '*') { diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java index ac7c1f9..8094641 100644 --- a/src/com/android/providers/telephony/MmsProvider.java +++ b/src/com/android/providers/telephony/MmsProvider.java @@ -48,6 +48,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.HashSet; import android.provider.Telephony.Threads; /** @@ -595,6 +596,10 @@ public int delete(Uri uri, String selection, selectionArgs, uri); } else if (TABLE_PART.equals(table)) { deletedRows = deleteParts(db, finalSelection, selectionArgs); + // Because the trigger for part table is deleted + // We need to update word and threads table after delete sth in part table + cleanUpWords(db); + updateHasAttachment(db); } else if (TABLE_DRM.equals(table)) { deletedRows = deleteTempDrmData(db, finalSelection, selectionArgs); } else { @@ -609,12 +614,13 @@ public int delete(Uri uri, String selection, static int deleteMessages(Context context, SQLiteDatabase db, String selection, String[] selectionArgs, Uri uri) { - Cursor cursor = db.query(TABLE_PDU, new String[] { Mms._ID }, + Cursor cursor = db.query(TABLE_PDU, new String[] { Mms._ID, Mms.THREAD_ID }, selection, selectionArgs, null, null, null); if (cursor == null) { return 0; } + HashSet threadIds = new HashSet(); try { if (cursor.getCount() == 0) { return 0; @@ -623,12 +629,22 @@ static int deleteMessages(Context context, SQLiteDatabase db, while (cursor.moveToNext()) { deleteParts(db, Part.MSG_ID + " = ?", new String[] { String.valueOf(cursor.getLong(0)) }); + threadIds.add(cursor.getLong(1)); } + // Because the trigger for part table is deleted + // We need to update word and threads table after delete sth in part table + cleanUpWords(db); + updateHasAttachment(db); } finally { cursor.close(); } int count = db.delete(TABLE_PDU, selection, selectionArgs); + // The triggers used to update threads after delete pdu is deleted + // Remenber to update threads which related to the deleted pdus + for (long thread : threadIds) { + MmsSmsDatabaseHelper.updateThread(db, thread); + } if (count > 0) { Intent intent = new Intent(Mms.Intents.CONTENT_CHANGED_ACTION); intent.putExtra(Mms.Intents.DELETED_CONTENTS, uri); @@ -640,6 +656,18 @@ static int deleteMessages(Context context, SQLiteDatabase db, return count; } + private static void cleanUpWords(SQLiteDatabase db) { + db.execSQL("DELETE FROM words WHERE source_id not in (select _id from part) AND " + + "table_to_use = 2"); + } + + private static void updateHasAttachment(SQLiteDatabase db) { + db.execSQL("UPDATE threads SET has_attachment = CASE " + + "(SELECT COUNT(*) FROM part JOIN pdu WHERE part.mid = pdu._id AND " + + "pdu.thread_id = threads._id AND part.ct != 'text/plain' " + + "AND part.ct != 'application/smil') WHEN 0 THEN 0 ELSE 1 END"); + } + private static int deleteParts(SQLiteDatabase db, String selection, String[] selectionArgs) { return deleteDataRows(db, TABLE_PART, selection, selectionArgs); diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java index 4f23be8..ea8b67f 100644 --- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java +++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java @@ -74,19 +74,6 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { " AND " + Mms.MESSAGE_BOX + " != 3) " + " WHERE threads._id = new.thread_id; "; - private static final String UPDATE_THREAD_COUNT_ON_OLD = - " UPDATE threads SET message_count = " + - " (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " + - " ON threads._id = " + Sms.THREAD_ID + - " WHERE " + Sms.THREAD_ID + " = old.thread_id" + - " AND sms." + Sms.TYPE + " != 3) + " + - " (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " + - " ON threads._id = " + Mms.THREAD_ID + - " WHERE " + Mms.THREAD_ID + " = old.thread_id" + - " AND (m_type=132 OR m_type=130 OR m_type=128)" + - " AND " + Mms.MESSAGE_BOX + " != 3) " + - " WHERE threads._id = old.thread_id; "; - private static final String SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE = "BEGIN" + " UPDATE threads SET" + @@ -136,20 +123,6 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { PDU_UPDATE_THREAD_READ_BODY + "END;"; - private static final String UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE = - " UPDATE threads SET snippet = " + - " (SELECT snippet FROM" + - " (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" + - " UNION SELECT date, body AS snippet, thread_id FROM sms)" + - " WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " + - " WHERE threads._id = OLD.thread_id; " + - " UPDATE threads SET snippet_cs = " + - " (SELECT snippet_cs FROM" + - " (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" + - " UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" + - " WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " + - " WHERE threads._id = OLD.thread_id; "; - // When a part is inserted, if it is not text/plain or application/smil // (which both can exist with text-only MMSes), then there is an attachment. @@ -176,28 +149,6 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { " WHERE part._id=new._id LIMIT 1); " + " END"; - - // When a part is deleted (with the same non-text/SMIL constraint as when - // we set has_attachment), update the threads table for all threads. - // Unfortunately we cannot update only the thread that the part was - // attached to, as it is possible that the part has been orphaned and - // the message it was attached to is already gone. - private static final String PART_UPDATE_THREADS_ON_DELETE_TRIGGER = - "CREATE TRIGGER update_threads_on_delete_part " + - " AFTER DELETE ON part " + - " WHEN old.ct != 'text/plain' AND old.ct != 'application/smil' " + - " BEGIN " + - " UPDATE threads SET has_attachment = " + - " CASE " + - " (SELECT COUNT(*) FROM part JOIN pdu " + - " WHERE pdu.thread_id = threads._id " + - " AND part.ct != 'text/plain' AND part.ct != 'application/smil' " + - " AND part.mid = pdu._id)" + - " WHEN 0 THEN 0 " + - " ELSE 1 " + - " END; " + - " END"; - // When the 'thread_id' column in the pdu table is updated, we need to run the trigger to update // the threads table's has_attachment column, if the message has an attachment in 'part' table private static final String PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER = @@ -215,7 +166,7 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { private static boolean sFakeLowStorageTest = false; // for testing only static final String DATABASE_NAME = "mmssms.db"; - static final int DATABASE_VERSION = 57; + static final int DATABASE_VERSION = 60; private final Context mContext; private LowStorageMonitor mLowStorageMonitor; @@ -546,6 +497,7 @@ private void createWordsTables(SQLiteDatabase db) { private void createIndices(SQLiteDatabase db) { createThreadIdIndex(db); + createPduPartIndex(db); } private void createThreadIdIndex(SQLiteDatabase db) { @@ -557,6 +509,15 @@ private void createThreadIdIndex(SQLiteDatabase db) { } } + private void createPduPartIndex(SQLiteDatabase db) { + try { + db.execSQL("CREATE INDEX IF NOT EXISTS index_part ON " + MmsProvider.TABLE_PART + + " (mid);"); + } catch (Exception ex) { + Log.e(TAG, "got exception creating indices: " + ex.toString()); + } + } + private void createMmsTables(SQLiteDatabase db) { // N.B.: Whenever the columns here are changed, the columns in // {@ref MmsSmsProvider} must be changed to match. @@ -593,7 +554,8 @@ private void createMmsTables(SQLiteDatabase db) { Mms.DELIVERY_REPORT + " INTEGER," + Mms.LOCKED + " INTEGER DEFAULT 0," + Mms.SEEN + " INTEGER DEFAULT 0," + - Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + + Mms.TEXT_ONLY + " INTEGER DEFAULT 0," + + Mms.SUB_ID + " INTEGER DEFAULT 0" + ");"); db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + @@ -667,9 +629,6 @@ private void createMmsTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_part"); db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER); - db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_delete_part"); - db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER); - db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_pdu"); db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER); @@ -757,18 +716,6 @@ private void createMmsTriggers(SQLiteDatabase db) { PDU_UPDATE_THREAD_CONSTRAINTS + PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE); - // Update threads table whenever a message in pdu is deleted - db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_delete"); - db.execSQL("CREATE TRIGGER pdu_update_thread_on_delete " + - "AFTER DELETE ON pdu " + - "BEGIN " + - " UPDATE threads SET " + - " date = (strftime('%s','now') * 1000)" + - " WHERE threads._id = old." + Mms.THREAD_ID + "; " + - UPDATE_THREAD_COUNT_ON_OLD + - UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE + - "END;"); - // Updates threads table whenever a message is added to pdu. db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_insert"); db.execSQL("CREATE TRIGGER pdu_update_thread_on_insert AFTER INSERT ON " + @@ -835,8 +782,11 @@ private void createSmsTables(SQLiteDatabase db) { "body TEXT," + "service_center TEXT," + "locked INTEGER DEFAULT 0," + + "sub_id INTEGER DEFAULT 0," + // sub_id : 0 for subscription 1 + // sub_id : 1 for subscription 2 "error_code INTEGER DEFAULT 0," + - "seen INTEGER DEFAULT 0" + + "seen INTEGER DEFAULT 0," + + "pri INTEGER DEFAULT -1" + ");"); /** @@ -1273,6 +1223,45 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { } finally { db.endTransaction(); } + // fall through + case 57: + if (currentVersion <= 57) { + return; + } + // skip version 58 + // fall through + case 58: + if (currentVersion <= 58) { + return; + } + + db.beginTransaction(); + try { + upgradeDatabaseToVersion59(db); + } catch (Throwable ex) { + Log.e(TAG, ex.getMessage(), ex); + // OK to fail here, this might be present already + } finally { + db.setTransactionSuccessful(); + db.endTransaction(); + } + // fall through + case 59: + if (currentVersion <= 59) { + return; + } + + db.beginTransaction(); + try { + upgradeDatabaseToVersion60(db); + db.setTransactionSuccessful(); + } catch (Throwable ex) { + Log.e(TAG, ex.getMessage(), ex); + break; + } finally { + db.endTransaction(); + } + return; } @@ -1328,7 +1317,6 @@ private void upgradeDatabaseToVersion43(SQLiteDatabase db) { // Add insert and delete triggers for keeping it up to date. db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER); - db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER); } private void upgradeDatabaseToVersion44(SQLiteDatabase db) { @@ -1474,6 +1462,20 @@ private void upgradeDatabaseToVersion57(SQLiteDatabase db) { db.execSQL("DELETE FROM " + MmsProvider.TABLE_PDU + " WHERE " + Mms.THREAD_ID + " IS NULL"); } + private void upgradeDatabaseToVersion59(SQLiteDatabase db) { + // Add 'sub_id' column to pdu table. + db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU + " ADD COLUMN sub_id" + + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS + " ADD COLUMN sub_id" + + " INTEGER DEFAULT 0"); + } + + private void upgradeDatabaseToVersion60(SQLiteDatabase db) { + // Add priority column + db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS + " ADD COLUMN pri" + + " INTEGER DEFAULT -1"); + } + @Override public synchronized SQLiteDatabase getWritableDatabase() { SQLiteDatabase db = super.getWritableDatabase(); @@ -1753,6 +1755,7 @@ private void upgradePduTableToAutoIncrement(SQLiteDatabase db) { Mms.LOCKED + " INTEGER DEFAULT 0," + Mms.SEEN + " INTEGER DEFAULT 0," + Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + + Mms.SUB_ID + " INTEGER DEFAULT 0" + ");"); db.execSQL("INSERT INTO pdu_temp SELECT * from pdu;"); diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java index a15335f..0a738c6 100644 --- a/src/com/android/providers/telephony/MmsSmsProvider.java +++ b/src/com/android/providers/telephony/MmsSmsProvider.java @@ -117,7 +117,8 @@ public class MmsSmsProvider extends ContentProvider { // These are the columns that appear in both the MMS ("pdu") and // SMS ("sms") message tables. private static final String[] MMS_SMS_COLUMNS = - { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, Mms.LOCKED }; + { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, + Mms.LOCKED, Mms.SUB_ID }; // These are the columns that appear only in the MMS message // table. @@ -134,7 +135,7 @@ public class MmsSmsProvider extends ContentProvider { // table. private static final String[] SMS_ONLY_COLUMNS = { "address", "body", "person", "reply_path_present", - "service_center", "status", "subject", "type", "error_code" }; + "service_center", "status", "subject", "type", "error_code", "pri" }; // These are all the columns that appear in the "threads" table. private static final String[] THREADS_COLUMNS = { diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java index c36a0d2..28fb970 100644 --- a/src/com/android/providers/telephony/SmsProvider.java +++ b/src/com/android/providers/telephony/SmsProvider.java @@ -607,7 +607,8 @@ public int delete(Uri url, String where, String[] whereArgs) { */ private int deleteMessageFromIcc(String messageIndexString) { SmsManager smsManager = SmsManager.getDefault(); - + // use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call + long token = Binder.clearCallingIdentity(); try { return smsManager.deleteMessageFromIcc( Integer.parseInt(messageIndexString)) @@ -619,6 +620,7 @@ private int deleteMessageFromIcc(String messageIndexString) { ContentResolver cr = getContext().getContentResolver(); cr.notifyChange(ICC_URI, null); + Binder.restoreCallingIdentity(token); } } diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java index b67aac0..bc936df 100644 --- a/src/com/android/providers/telephony/TelephonyProvider.java +++ b/src/com/android/providers/telephony/TelephonyProvider.java @@ -33,12 +33,16 @@ import android.net.Uri; import android.os.Environment; import android.provider.Telephony; +import android.telephony.MSimTelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.util.Xml; import com.android.internal.telephony.BaseCommands; +import com.android.internal.telephony.MSimConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.TelephonyProperties; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -55,13 +59,14 @@ public class TelephonyProvider extends ContentProvider private static final String DATABASE_NAME = "telephony.db"; private static final boolean DBG = true; - private static final int DATABASE_VERSION = 8 << 16; + private static final int DATABASE_VERSION = 10 << 16; private static final int URL_TELEPHONY = 1; private static final int URL_CURRENT = 2; private static final int URL_ID = 3; private static final int URL_RESTOREAPN = 4; private static final int URL_PREFERAPN = 5; private static final int URL_PREFERAPN_NO_UPDATE = 6; + private static final int URL_PREFERAPN_W_SUB_ID = 7; private static final String TAG = "TelephonyProvider"; private static final String CARRIERS_TABLE = "carriers"; @@ -83,6 +88,7 @@ public class TelephonyProvider extends ContentProvider s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN); s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN); s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE); + s_urlMatcher.addURI("telephony", "carriers/preferapn/#", URL_PREFERAPN_W_SUB_ID); s_currentNullMap = new ContentValues(1); s_currentNullMap.put("current", (Long) null); @@ -147,11 +153,30 @@ public void onCreate(SQLiteDatabase db) { "carrier_enabled BOOLEAN," + "bearer INTEGER," + "mvno_type TEXT," + - "mvno_match_data TEXT);"); + "mvno_match_data TEXT," + + "preferred BOOLEAN DEFAULT 0);"); initDatabase(db); } + private int getDefaultPreferredApnId(SQLiteDatabase db) { + int id = -1; + String configPref = mContext.getResources().getString(R.string.config_preferred_apn, ""); + if (!TextUtils.isEmpty(configPref)) { + String[] s = configPref.split(","); + if (s.length == 3) { + Cursor c = db.query("carriers", new String[] { "_id" }, + "apn='" + s[0] + "' AND mcc='" + s[1] + "' AND mnc='" + s[2] + "'", + null, null, null, null); + if (c.moveToFirst()) { + id = c.getInt(0); + } + c.close(); + } + } + return id; + } + private void initDatabase(SQLiteDatabase db) { // Read internal APNS data Resources r = mContext.getResources(); @@ -241,6 +266,28 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { " ADD COLUMN mvno_match_data TEXT DEFAULT '';"); oldVersion = 8 << 16 | 6; } + if (oldVersion < (9 << 16 | 6)) { + // Dummy upgrade from previous CM versions + oldVersion = 9 << 16 | 6; + } + if (oldVersion < (10 << 16 | 6)) { + // Add preferred field to the APN. + // The XML file does not change. + try { + db.execSQL("ALTER TABLE " + CARRIERS_TABLE + + " ADD COLUMN preferred BOOLEAN DEFAULT 0;"); + oldVersion = 10 << 16 | 6; + } catch (SQLException e) { + // Original implementation for preferred apn feature + // didn't include new version for database + // Consequently we can have version 8 database with and + // without preferred column + // Hence, this operation can result in exception + // (if column is already there) + // Just log it + Log.e(TAG, "Exception adding preferred column to database. ", e); + } + } } /** @@ -325,6 +372,11 @@ private ContentValues getRow(XmlPullParser parser) { map.put(Telephony.Carriers.MVNO_MATCH_DATA, mvno_match_data); } } + + String preferred = parser.getAttributeValue(null, "preferred"); + if (preferred != null) { + map.put(Telephony.Carriers.PREFERRED, Boolean.parseBoolean(preferred)); + } return map; } @@ -384,6 +436,10 @@ private void insertAddingDefaults(SQLiteDatabase db, String table, ContentValues if (row.containsKey(Telephony.Carriers.MVNO_MATCH_DATA) == false) { row.put(Telephony.Carriers.MVNO_MATCH_DATA, ""); } + + if (row.containsKey(Telephony.Carriers.PREFERRED) == false) { + row.put(Telephony.Carriers.PREFERRED, false); + } db.insert(CARRIERS_TABLE, null, row); } } @@ -394,16 +450,127 @@ public boolean onCreate() { return true; } - private void setPreferredApnId(Long id) { + private String getColumnApnIdKey(int subId) { + String result = COLUMN_APN_ID; + // In case multi-sim is enabled, + // if subId is given, use column name "apn_id" + sub id; + // if subId is not given, use column name "apn_id" + preferred data sub id. + // + // In case multi-sim is not enabled, + // use column name "apn_id". + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + switch (subId) { + case MSimConstants.SUB1: + case MSimConstants.SUB2: + result += String.valueOf(subId); + break; + default: + result += String.valueOf(MSimTelephonyManager.getDefault() + .getPreferredDataSubscription()); + break; + } + } + Log.d(TAG, "Column apn id key is '" + result + "'"); + return result; + } + + private void setPreferredApnId(Long id, int subId) { SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); - editor.putLong(COLUMN_APN_ID, id != null ? id.longValue() : -1); + editor.putLong(getColumnApnIdKey(subId), id != null ? id.longValue() : -1); editor.apply(); } - private long getPreferredApnId() { + private void setPreferredApnId(Long id) { + setPreferredApnId(id, -1); + } + + private String getOperatorNumeric(int subId) { + if (subId != MSimConstants.SUB1 && subId != MSimConstants.SUB2) { + subId = MSimTelephonyManager.getDefault().getDefaultSubscription(); + } + String numeric = MSimTelephonyManager.getTelephonyProperty( + TelephonyProperties.PROPERTY_APN_SIM_OPERATOR_NUMERIC, subId, null); + if (numeric != null && numeric.length() > 0) { + return numeric; + } else { + return null; + } + } + + private long getPreferredApnId(int subId) { + long apnId; SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); - return sp.getLong(COLUMN_APN_ID, -1); + apnId = sp.getLong(getColumnApnIdKey(subId), -1); + if (apnId == -1) { + // Check if there is an initial preferred apn + String numeric = getOperatorNumeric(subId); + if (numeric != null) { + checkPermission(); + try { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + qb.setTables("carriers"); + + String where; + where = "numeric=\"" + numeric + "\""; + where += " AND preferred = 1"; + + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + Cursor cursor = qb.query(db, new String[] {"_id"}, where, + null, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); + cursor.moveToFirst(); + if (!cursor.isAfterLast()) { + final int ID_INDEX = 0; + String key = cursor.getString(ID_INDEX); + apnId = Long.valueOf(key); + Log.d(TAG, "Found an inital preferred apn. id = " + apnId); + } else { + apnId = getDefaultPreferredApnId(); + if (apnId > -1) { + setPreferredApnId(apnId); + } + } + } catch (SQLException e) { + Log.e(TAG, "got exception while checking initial preferred apn: " + e); + } + } + } + + return apnId; + } + + private long getPreferredApnId() { + return getPreferredApnId(-1); + } + + private long getDefaultPreferredApnId() { + long id = -1; + String configPref = getContext().getResources().getString(R.string.config_preferred_apn, ""); + if (!TextUtils.isEmpty(configPref)) { + String[] s = configPref.split(","); + if (s.length == 3) { + Cursor c = mOpenHelper.getReadableDatabase().query("carriers", new String[] { "_id" }, + "apn='" + s[0] + "' AND mcc='" + s[1] + "' AND mnc='" + s[2] + "'", + null, null, null, null); + if (c.moveToFirst()) { + id = c.getLong(0); + } + c.close(); + } + } + Log.d(TAG, "Preferred APN: " + id); + return id; + } + + private int parseSubId(Uri url) { + int subId = -1; + try { + subId = Integer.parseInt(url.getLastPathSegment()); + } catch (NumberFormatException e) { + Log.e(TAG, "NumberFormatException: ", e); + } + Log.d(TAG, "SUB ID in the uri is" + subId); + return subId; } @Override @@ -439,6 +606,11 @@ public Cursor query(Uri url, String[] projectionIn, String selection, break; } + case URL_PREFERAPN_W_SUB_ID: { + qb.appendWhere("_id = " + getPreferredApnId(parseSubId(url))); + break; + } + default: { return null; } @@ -486,6 +658,7 @@ public String getType(Uri url) case URL_PREFERAPN: case URL_PREFERAPN_NO_UPDATE: + case URL_PREFERAPN_W_SUB_ID: return "vnd.android.cursor.item/telephony-carrier"; default: @@ -564,6 +737,9 @@ public Uri insert(Uri url, ContentValues initialValues) if (!values.containsKey(Telephony.Carriers.MVNO_MATCH_DATA)) { values.put(Telephony.Carriers.MVNO_MATCH_DATA, ""); } + if (!values.containsKey(Telephony.Carriers.PREFERRED)) { + values.put(Telephony.Carriers.PREFERRED, false); + } long rowID = db.insert(CARRIERS_TABLE, null, values); if (rowID > 0) @@ -608,6 +784,16 @@ public Uri insert(Uri url, ContentValues initialValues) } break; } + + case URL_PREFERAPN_W_SUB_ID: + { + if (initialValues != null) { + if(initialValues.containsKey(COLUMN_APN_ID)) { + setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), parseSubId(url)); + } + } + break; + } } if (notify) { @@ -661,6 +847,13 @@ public int delete(Uri url, String where, String[] whereArgs) break; } + case URL_PREFERAPN_W_SUB_ID: + { + setPreferredApnId((long)-1, parseSubId(url)); + count = 1; + break; + } + default: { throw new UnsupportedOperationException("Cannot delete that URL: " + url); } @@ -719,6 +912,17 @@ public int update(Uri url, ContentValues values, String where, String[] whereArg break; } + case URL_PREFERAPN_W_SUB_ID: + { + if (values != null) { + if (values.containsKey(COLUMN_APN_ID)) { + setPreferredApnId(values.getAsLong(COLUMN_APN_ID), parseSubId(url)); + count = 1; + } + } + break; + } + default: { throw new UnsupportedOperationException("Cannot update that URL: " + url); } @@ -748,5 +952,6 @@ private void restoreDefaultAPN() { } setPreferredApnId((long)-1); mOpenHelper.initDatabase(db); + setPreferredApnId(getDefaultPreferredApnId()); } } From 440cd3bf006eff465a414e5c38d6f67710533e1a Mon Sep 17 00:00:00 2001 From: David James Date: Sat, 28 Jun 2014 14:14:41 -0500 Subject: [PATCH 3/3] Remove Msim Change-Id: I42426210ffa58d40b87f4718cc9a74053f014f76 --- .../telephony/MmsSmsDatabaseHelper.java | 10 +- .../providers/telephony/MmsSmsProvider.java | 3 +- .../telephony/TelephonyProvider.java | 181 ++---------------- 3 files changed, 20 insertions(+), 174 deletions(-) diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java index ea8b67f..ed01a95 100644 --- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java +++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java @@ -555,7 +555,7 @@ private void createMmsTables(SQLiteDatabase db) { Mms.LOCKED + " INTEGER DEFAULT 0," + Mms.SEEN + " INTEGER DEFAULT 0," + Mms.TEXT_ONLY + " INTEGER DEFAULT 0," + - Mms.SUB_ID + " INTEGER DEFAULT 0" + + "sub_id INTEGER DEFAULT 0" + ");"); db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + @@ -782,8 +782,8 @@ private void createSmsTables(SQLiteDatabase db) { "body TEXT," + "service_center TEXT," + "locked INTEGER DEFAULT 0," + - "sub_id INTEGER DEFAULT 0," + // sub_id : 0 for subscription 1 - // sub_id : 1 for subscription 2 + "sub_id INTEGER DEFAULT 0," + // sub_id : 0 for subscription 1 + // sub_id : 1 for subscription 2 "error_code INTEGER DEFAULT 0," + "seen INTEGER DEFAULT 0," + "pri INTEGER DEFAULT -1" + @@ -1754,8 +1754,8 @@ private void upgradePduTableToAutoIncrement(SQLiteDatabase db) { Mms.DELIVERY_REPORT + " INTEGER," + Mms.LOCKED + " INTEGER DEFAULT 0," + Mms.SEEN + " INTEGER DEFAULT 0," + - Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + - Mms.SUB_ID + " INTEGER DEFAULT 0" + + Mms.TEXT_ONLY + " INTEGER DEFAULT 0," + + "sub_id INTEGER DEFAULT 0" + ");"); db.execSQL("INSERT INTO pdu_temp SELECT * from pdu;"); diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java index 0a738c6..347e246 100644 --- a/src/com/android/providers/telephony/MmsSmsProvider.java +++ b/src/com/android/providers/telephony/MmsSmsProvider.java @@ -117,8 +117,7 @@ public class MmsSmsProvider extends ContentProvider { // These are the columns that appear in both the MMS ("pdu") and // SMS ("sms") message tables. private static final String[] MMS_SMS_COLUMNS = - { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, - Mms.LOCKED, Mms.SUB_ID }; + { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, Mms.LOCKED }; // These are the columns that appear only in the MMS message // table. diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java index bc936df..89f6dc4 100644 --- a/src/com/android/providers/telephony/TelephonyProvider.java +++ b/src/com/android/providers/telephony/TelephonyProvider.java @@ -33,16 +33,13 @@ import android.net.Uri; import android.os.Environment; import android.provider.Telephony; -import android.telephony.MSimTelephonyManager; import android.text.TextUtils; import android.util.Log; import android.util.Xml; import com.android.internal.telephony.BaseCommands; -import com.android.internal.telephony.MSimConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; -import com.android.internal.telephony.TelephonyProperties; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -59,14 +56,13 @@ public class TelephonyProvider extends ContentProvider private static final String DATABASE_NAME = "telephony.db"; private static final boolean DBG = true; - private static final int DATABASE_VERSION = 10 << 16; + private static final int DATABASE_VERSION = 9 << 16; private static final int URL_TELEPHONY = 1; private static final int URL_CURRENT = 2; private static final int URL_ID = 3; private static final int URL_RESTOREAPN = 4; private static final int URL_PREFERAPN = 5; private static final int URL_PREFERAPN_NO_UPDATE = 6; - private static final int URL_PREFERAPN_W_SUB_ID = 7; private static final String TAG = "TelephonyProvider"; private static final String CARRIERS_TABLE = "carriers"; @@ -88,7 +84,6 @@ public class TelephonyProvider extends ContentProvider s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN); s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN); s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE); - s_urlMatcher.addURI("telephony", "carriers/preferapn/#", URL_PREFERAPN_W_SUB_ID); s_currentNullMap = new ContentValues(1); s_currentNullMap.put("current", (Long) null); @@ -153,8 +148,7 @@ public void onCreate(SQLiteDatabase db) { "carrier_enabled BOOLEAN," + "bearer INTEGER," + "mvno_type TEXT," + - "mvno_match_data TEXT," + - "preferred BOOLEAN DEFAULT 0);"); + "mvno_match_data TEXT);"); initDatabase(db); } @@ -267,27 +261,11 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { oldVersion = 8 << 16 | 6; } if (oldVersion < (9 << 16 | 6)) { - // Dummy upgrade from previous CM versions + // Add preferred field to the APN. The XML file does not change. + db.execSQL("ALTER TABLE " + CARRIERS_TABLE + + " ADD COLUMN preferred BOOLEAN DEFAULT 0;"); oldVersion = 9 << 16 | 6; } - if (oldVersion < (10 << 16 | 6)) { - // Add preferred field to the APN. - // The XML file does not change. - try { - db.execSQL("ALTER TABLE " + CARRIERS_TABLE + - " ADD COLUMN preferred BOOLEAN DEFAULT 0;"); - oldVersion = 10 << 16 | 6; - } catch (SQLException e) { - // Original implementation for preferred apn feature - // didn't include new version for database - // Consequently we can have version 8 database with and - // without preferred column - // Hence, this operation can result in exception - // (if column is already there) - // Just log it - Log.e(TAG, "Exception adding preferred column to database. ", e); - } - } } /** @@ -372,11 +350,6 @@ private ContentValues getRow(XmlPullParser parser) { map.put(Telephony.Carriers.MVNO_MATCH_DATA, mvno_match_data); } } - - String preferred = parser.getAttributeValue(null, "preferred"); - if (preferred != null) { - map.put(Telephony.Carriers.PREFERRED, Boolean.parseBoolean(preferred)); - } return map; } @@ -436,10 +409,6 @@ private void insertAddingDefaults(SQLiteDatabase db, String table, ContentValues if (row.containsKey(Telephony.Carriers.MVNO_MATCH_DATA) == false) { row.put(Telephony.Carriers.MVNO_MATCH_DATA, ""); } - - if (row.containsKey(Telephony.Carriers.PREFERRED) == false) { - row.put(Telephony.Carriers.PREFERRED, false); - } db.insert(CARRIERS_TABLE, null, row); } } @@ -450,97 +419,23 @@ public boolean onCreate() { return true; } - private String getColumnApnIdKey(int subId) { - String result = COLUMN_APN_ID; - // In case multi-sim is enabled, - // if subId is given, use column name "apn_id" + sub id; - // if subId is not given, use column name "apn_id" + preferred data sub id. - // - // In case multi-sim is not enabled, - // use column name "apn_id". - if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { - switch (subId) { - case MSimConstants.SUB1: - case MSimConstants.SUB2: - result += String.valueOf(subId); - break; - default: - result += String.valueOf(MSimTelephonyManager.getDefault() - .getPreferredDataSubscription()); - break; - } - } - Log.d(TAG, "Column apn id key is '" + result + "'"); - return result; - } - - private void setPreferredApnId(Long id, int subId) { + private void setPreferredApnId(Long id) { SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); - editor.putLong(getColumnApnIdKey(subId), id != null ? id.longValue() : -1); + editor.putLong(COLUMN_APN_ID, id != null ? id.longValue() : -1); editor.apply(); } - private void setPreferredApnId(Long id) { - setPreferredApnId(id, -1); - } - - private String getOperatorNumeric(int subId) { - if (subId != MSimConstants.SUB1 && subId != MSimConstants.SUB2) { - subId = MSimTelephonyManager.getDefault().getDefaultSubscription(); - } - String numeric = MSimTelephonyManager.getTelephonyProperty( - TelephonyProperties.PROPERTY_APN_SIM_OPERATOR_NUMERIC, subId, null); - if (numeric != null && numeric.length() > 0) { - return numeric; - } else { - return null; - } - } - - private long getPreferredApnId(int subId) { - long apnId; + private long getPreferredApnId() { SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); - apnId = sp.getLong(getColumnApnIdKey(subId), -1); - if (apnId == -1) { - // Check if there is an initial preferred apn - String numeric = getOperatorNumeric(subId); - if (numeric != null) { - checkPermission(); - try { - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - qb.setTables("carriers"); - - String where; - where = "numeric=\"" + numeric + "\""; - where += " AND preferred = 1"; - - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - Cursor cursor = qb.query(db, new String[] {"_id"}, where, - null, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); - cursor.moveToFirst(); - if (!cursor.isAfterLast()) { - final int ID_INDEX = 0; - String key = cursor.getString(ID_INDEX); - apnId = Long.valueOf(key); - Log.d(TAG, "Found an inital preferred apn. id = " + apnId); - } else { - apnId = getDefaultPreferredApnId(); - if (apnId > -1) { - setPreferredApnId(apnId); - } - } - } catch (SQLException e) { - Log.e(TAG, "got exception while checking initial preferred apn: " + e); - } + long id = sp.getLong(COLUMN_APN_ID, -1); + if (id == -1) { + id = getDefaultPreferredApnId(); + if (id > -1) { + setPreferredApnId(id); } } - - return apnId; - } - - private long getPreferredApnId() { - return getPreferredApnId(-1); + return id; } private long getDefaultPreferredApnId() { @@ -562,17 +457,6 @@ private long getDefaultPreferredApnId() { return id; } - private int parseSubId(Uri url) { - int subId = -1; - try { - subId = Integer.parseInt(url.getLastPathSegment()); - } catch (NumberFormatException e) { - Log.e(TAG, "NumberFormatException: ", e); - } - Log.d(TAG, "SUB ID in the uri is" + subId); - return subId; - } - @Override public Cursor query(Uri url, String[] projectionIn, String selection, String[] selectionArgs, String sort) { @@ -606,11 +490,6 @@ public Cursor query(Uri url, String[] projectionIn, String selection, break; } - case URL_PREFERAPN_W_SUB_ID: { - qb.appendWhere("_id = " + getPreferredApnId(parseSubId(url))); - break; - } - default: { return null; } @@ -658,7 +537,6 @@ public String getType(Uri url) case URL_PREFERAPN: case URL_PREFERAPN_NO_UPDATE: - case URL_PREFERAPN_W_SUB_ID: return "vnd.android.cursor.item/telephony-carrier"; default: @@ -737,9 +615,6 @@ public Uri insert(Uri url, ContentValues initialValues) if (!values.containsKey(Telephony.Carriers.MVNO_MATCH_DATA)) { values.put(Telephony.Carriers.MVNO_MATCH_DATA, ""); } - if (!values.containsKey(Telephony.Carriers.PREFERRED)) { - values.put(Telephony.Carriers.PREFERRED, false); - } long rowID = db.insert(CARRIERS_TABLE, null, values); if (rowID > 0) @@ -784,16 +659,6 @@ public Uri insert(Uri url, ContentValues initialValues) } break; } - - case URL_PREFERAPN_W_SUB_ID: - { - if (initialValues != null) { - if(initialValues.containsKey(COLUMN_APN_ID)) { - setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), parseSubId(url)); - } - } - break; - } } if (notify) { @@ -847,13 +712,6 @@ public int delete(Uri url, String where, String[] whereArgs) break; } - case URL_PREFERAPN_W_SUB_ID: - { - setPreferredApnId((long)-1, parseSubId(url)); - count = 1; - break; - } - default: { throw new UnsupportedOperationException("Cannot delete that URL: " + url); } @@ -912,17 +770,6 @@ public int update(Uri url, ContentValues values, String where, String[] whereArg break; } - case URL_PREFERAPN_W_SUB_ID: - { - if (values != null) { - if (values.containsKey(COLUMN_APN_ID)) { - setPreferredApnId(values.getAsLong(COLUMN_APN_ID), parseSubId(url)); - count = 1; - } - } - break; - } - default: { throw new UnsupportedOperationException("Cannot update that URL: " + url); }