merge from open-source master
Change-Id: Ie2616d4bbc9f1f545accbf043176b698e2e7dc3f
diff --git a/Android.mk b/Android.mk
index 97439a2..b0f3906 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,13 +1,13 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := user
+LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES :=
-
LOCAL_PACKAGE_NAME := TelephonyProvider
LOCAL_CERTIFICATE := platform
+LOCAL_STATIC_JAVA_LIBRARIES += android-common
+
include $(BUILD_PACKAGE)
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b6
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 The Android Open Source 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/res/drawable-mdpi/ic_launcher_phone.png b/res/drawable-mdpi/ic_launcher_phone.png
index 4e613ec..88336a3 100644
--- a/res/drawable-mdpi/ic_launcher_phone.png
+++ b/res/drawable-mdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index dc74a30..f811e9a 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Úložiště vytáčení"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 0888bcf..37eae10 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Opkaldslagring"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 66e94a3..703fe33 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Speicher des Wählprogramms"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 5efe232..cc55573 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Αποθηκευτικός χώρος προγράμματος αποθήκευσης"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 2fee906..2d26cbb 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Almacenamiento del marcador"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index f3744ec..f134392 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Dialer Storage"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b115c14..fb2f0fa 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Stockage téléphone"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 5762831..f4ee7e6 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Archiviazione dialer"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 16ea74d..bbcc59c 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"端末情報保存"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 1baa28d..2d90961 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"다이얼러 저장소"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 27e6563..5e2074a 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Dialer-lagring"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index ea5b3ac..ce97015 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Telefoonopslag"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 4680eff..500d2c9 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Magazyn telefonu"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index b11fbbf..28b7ca9 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Armazenamento do Marcador"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 1a97e6d..da8b8c7 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Armazenamento do discador"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index d0dca6f..1c87b4e 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Хранилище данных телефона"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index eb4d752..5068312 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Samtalslagring"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 2430820..658ddea 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"Çevirici Deposu"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index cc79baa..52fcf21 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"拨号器存储"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 08c3f62..e080644 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -12,7 +12,8 @@
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.
--->
+ -->
+
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4846406803456361049">"撥號儲存空間"</string>
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index f141cd4..a4e6919 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -16,8 +16,6 @@
package com.android.providers.telephony;
-import com.google.android.mms.pdu.PduHeaders;
-
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
@@ -30,6 +28,7 @@
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
+import android.provider.Telephony;
import android.provider.Telephony.CanonicalAddressesColumns;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
@@ -40,6 +39,8 @@
import android.util.Config;
import android.util.Log;
+import com.google.android.mms.pdu.PduHeaders;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -55,6 +56,7 @@
static final String TABLE_PART = "part";
static final String TABLE_RATE = "rate";
static final String TABLE_DRM = "drm";
+ static final String TABLE_WORDS = "words";
@Override
public boolean onCreate() {
@@ -377,10 +379,12 @@
}
String contentType = values.getAsString("ct");
-
+
// text/plain and app application/smil store their "data" inline in the
// table so there's no need to create the file
- if (!"text/plain".equals(contentType) && !"application/smil".equals(contentType)) {
+ boolean plainText = "text/plain".equals(contentType);
+ boolean smilText = "application/smil".equals(contentType);
+ if (!plainText && !smilText) {
// Generate the '_data' field of the part with default
// permission settings.
String path = getContext().getDir("parts", 0).getPath()
@@ -409,6 +413,26 @@
}
res = Uri.parse(res + "/part/" + rowId);
+
+ // Don't use a trigger for updating the words table because of a bug
+ // in FTS3. The bug is such that the call to get the last inserted
+ // row is incorrect.
+ if (plainText) {
+ // Update the words table with a corresponding row. The words table
+ // allows us to search for words quickly, without scanning the whole
+ // table;
+ ContentValues cv = new ContentValues();
+
+ // we're using the row id of the part table row but we're also using ids
+ // from the sms table so this divides the space into two large chunks.
+ // The row ids from the part table start at 2 << 32.
+ cv.put(Telephony.MmsSms.WordsTable.ID, (2 << 32) + rowId);
+ cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, values.getAsString("text"));
+ cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, rowId);
+ cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 2);
+ db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
+ }
+
} else if (table.equals(TABLE_RATE)) {
long now = values.getAsLong(Rate.SENT_TIME);
long oneHourAgo = now - 1000 * 60 * 60;
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index b62d4eb..c26e855 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -16,26 +16,19 @@
package com.android.providers.telephony;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_DELIVERY_IND;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_READ_ORIG_IND;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_READ_REC_IND;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF;
-import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_SEND_REQ;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.File;
import java.util.ArrayList;
-import com.google.android.mms.pdu.EncodedStringValue;
-
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
+import android.provider.Telephony;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Sms;
@@ -46,6 +39,9 @@
import android.provider.Telephony.MmsSms.PendingMessages;
import android.util.Log;
+import com.google.android.mms.pdu.EncodedStringValue;
+import com.google.android.mms.pdu.PduHeaders;
+
public class MmsSmsDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "MmsSmsDatabaseHelper";
@@ -98,16 +94,27 @@
"END;";
private static final String PDU_UPDATE_THREAD_CONSTRAINTS =
- " WHEN new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF +
- " OR new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND +
- " OR new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_SEND_REQ + " ";
+ " WHEN new." + Mms.MESSAGE_TYPE + "=" +
+ PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF +
+ " OR new." + Mms.MESSAGE_TYPE + "=" +
+ PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
+ " OR new." + Mms.MESSAGE_TYPE + "=" +
+ PduHeaders.MESSAGE_TYPE_SEND_REQ + " ";
+ // When looking in the pdu table for unread messages, only count messages that
+ // are displayed to the user. The constants are defined in PduHeaders and could be used
+ // here, but the string "(m_type=132 OR m_type=130 OR m_type=128)" is used throughout this
+ // file and so it is used here to be consistent.
+ // m_type=128 = MESSAGE_TYPE_SEND_REQ
+ // m_type=130 = MESSAGE_TYPE_NOTIFICATION_IND
+ // m_type=132 = MESSAGE_TYPE_RETRIEVE_CONF
private static final String PDU_UPDATE_THREAD_READ_BODY =
" UPDATE threads SET read = " +
" CASE (SELECT COUNT(*)" +
" FROM " + MmsProvider.TABLE_PDU +
" WHERE " + Mms.READ + " = 0" +
- " AND " + Mms.THREAD_ID + " = threads._id)" +
+ " AND " + Mms.THREAD_ID + " = threads._id " +
+ " AND (m_type=132 OR m_type=130 OR m_type=128)) " +
" WHEN 0 THEN 1" +
" ELSE 0" +
" END" +
@@ -177,9 +184,10 @@
" BEGIN " +
" UPDATE threads SET has_attachment = " +
" CASE " +
- " (SELECT COUNT(*) FROM part JOIN pdu ON pdu._id=part.mid " +
+ " (SELECT COUNT(*) FROM part JOIN pdu " +
" WHERE pdu.thread_id = threads._id " +
- " AND part.ct != 'text/plain' AND part.ct != 'application/smil')" +
+ " AND part.ct != 'text/plain' AND part.ct != 'application/smil' " +
+ " AND part.mid = pdu._id)" +
" WHEN 0 THEN 0 " +
" ELSE 1 " +
" END; " +
@@ -192,14 +200,15 @@
" AFTER UPDATE of thread_id ON pdu " +
" BEGIN " +
" UPDATE threads SET has_attachment=1 WHERE _id IN " +
- " (SELECT pdu.thread_id FROM part JOIN pdu ON new._id=part.mid " +
- " WHERE part.ct != 'text/plain' AND part.ct != 'application/smil'); " +
+ " (SELECT pdu.thread_id FROM part JOIN pdu " +
+ " WHERE part.ct != 'text/plain' AND part.ct != 'application/smil' " +
+ " AND part.mid = pdu._id);" +
" END";
private static MmsSmsDatabaseHelper mInstance = null;
static final String DATABASE_NAME = "mmssms.db";
- static final int DATABASE_VERSION = 47;
+ static final int DATABASE_VERSION = 53;
private MmsSmsDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -274,11 +283,37 @@
// Update the error column of the thread to indicate if there
// are any messages in it that have failed to send.
- db.execSQL(
- "UPDATE threads SET error =" +
- " (SELECT COUNT(*) FROM sms WHERE type=5" +
- " AND thread_id = " + thread_id + " LIMIT 1)" +
- " WHERE threads._id = " + thread_id + ";");
+ // First check to see if there are any messages with errors in this thread.
+ String query = "SELECT thread_id FROM sms WHERE type=" +
+ Telephony.TextBasedSmsColumns.MESSAGE_TYPE_FAILED +
+ " AND thread_id = " + thread_id +
+ " LIMIT 1";
+ int setError = 0;
+ Cursor c = db.rawQuery(query, null);
+ if (c != null) {
+ try {
+ setError = c.getCount(); // Because of the LIMIT 1, count will be 1 or 0.
+ } finally {
+ c.close();
+ }
+ }
+ // What's the current state of the error flag in the threads table?
+ String errorQuery = "SELECT error FROM threads WHERE _id = " + thread_id;
+ c = db.rawQuery(errorQuery, null);
+ if (c != null) {
+ try {
+ if (c.moveToNext()) {
+ int curError = c.getInt(0);
+ if (curError != setError) {
+ // The current thread error column differs, update it.
+ db.execSQL("UPDATE threads SET error=" + setError +
+ " WHERE _id = " + thread_id);
+ }
+ }
+ } finally {
+ c.close();
+ }
+ }
}
public static void updateAllThreads(SQLiteDatabase db, String where, String[] whereArgs) {
@@ -291,10 +326,13 @@
"(SELECT DISTINCT thread_id FROM sms " + where + ")";
Cursor c = db.rawQuery(query, whereArgs);
if (c != null) {
- while (c.moveToNext()) {
- updateThread(db, c.getInt(0));
+ try {
+ while (c.moveToNext()) {
+ updateThread(db, c.getInt(0));
+ }
+ } finally {
+ c.close();
}
- c.close();
}
// remove orphaned threads
db.delete("threads",
@@ -330,6 +368,120 @@
createCommonTables(db);
createCommonTriggers(db);
createMmsTriggers(db);
+ createWordsTables(db);
+ createIndices(db);
+ }
+
+ // When upgrading the database we need to populate the words
+ // table with the rows out of sms and part.
+ private void populateWordsTable(SQLiteDatabase db) {
+ final String TABLE_WORDS = "words";
+ {
+ Cursor smsRows = db.query(
+ "sms",
+ new String[] { Sms._ID, Sms.BODY },
+ null,
+ null,
+ null,
+ null,
+ null);
+ try {
+ if (smsRows != null) {
+ smsRows.moveToPosition(-1);
+ ContentValues cv = new ContentValues();
+ while (smsRows.moveToNext()) {
+ cv.clear();
+
+ long id = smsRows.getLong(0); // 0 for Sms._ID
+ String body = smsRows.getString(1); // 1 for Sms.BODY
+
+ cv.put(Telephony.MmsSms.WordsTable.ID, id);
+ cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
+ cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
+ cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
+ db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
+ }
+ }
+ } finally {
+ if (smsRows != null) {
+ smsRows.close();
+ }
+ }
+ }
+
+ {
+ Cursor mmsRows = db.query(
+ "part",
+ new String[] { Part._ID, Part.TEXT },
+ "ct = 'text/plain'",
+ null,
+ null,
+ null,
+ null);
+ try {
+ if (mmsRows != null) {
+ mmsRows.moveToPosition(-1);
+ ContentValues cv = new ContentValues();
+ while (mmsRows.moveToNext()) {
+ cv.clear();
+
+ long id = mmsRows.getLong(0); // 0 for Part._ID
+ String body = mmsRows.getString(1); // 1 for Part.TEXT
+
+ cv.put(Telephony.MmsSms.WordsTable.ID, id);
+ cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
+ cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
+ cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
+ db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
+ }
+ }
+ } finally {
+ if (mmsRows != null) {
+ mmsRows.close();
+ }
+ }
+ }
+ }
+
+ private void createWordsTables(SQLiteDatabase db) {
+ try {
+ db.execSQL("CREATE VIRTUAL TABLE words USING FTS3 (_id INTEGER PRIMARY KEY, index_text TEXT, source_id INTEGER, table_to_use INTEGER);");
+
+ // monitor the sms table
+ // NOTE don't handle inserts using a trigger because it has an unwanted
+ // side effect: the value returned for the last row ends up being the
+ // id of one of the trigger insert not the original row insert.
+ // Handle inserts manually in the provider.
+ db.execSQL("CREATE TRIGGER sms_words_update AFTER UPDATE ON sms BEGIN UPDATE words " +
+ " SET index_text = NEW.body WHERE (source_id=NEW._id AND table_to_use=1); " +
+ " END;");
+ db.execSQL("CREATE TRIGGER sms_words_delete AFTER DELETE ON sms BEGIN DELETE FROM " +
+ " words WHERE source_id = OLD._id AND table_to_use = 1; END;");
+
+ // monitor the mms table
+ db.execSQL("CREATE TRIGGER mms_words_update AFTER UPDATE ON part BEGIN UPDATE words " +
+ " SET index_text = NEW.text WHERE (source_id=NEW._id AND table_to_use=2); " +
+ " END;");
+ db.execSQL("CREATE TRIGGER mms_words_delete AFTER DELETE ON part BEGIN DELETE FROM " +
+ " words WHERE source_id = OLD._id AND table_to_use = 2; END;");
+
+ populateWordsTable(db);
+ } catch (Exception ex) {
+ Log.e(TAG, "got exception creating words table: " + ex.toString());
+ }
+ }
+
+ private void createIndices(SQLiteDatabase db) {
+ createThreadIdIndex(db);
+ }
+
+ private void createThreadIdIndex(SQLiteDatabase db) {
+ try {
+ db.execSQL("CREATE INDEX IF NOT EXISTS typeThreadIdIndex ON sms" +
+ " (type, thread_id);");
+ } catch (Exception ex) {
+ Log.e(TAG, "got exception creating indices: " + ex.toString());
+ }
}
private void createMmsTables(SQLiteDatabase db) {
@@ -365,7 +517,8 @@
Mms.RESPONSE_TEXT + " TEXT," +
Mms.DELIVERY_TIME + " INTEGER," +
Mms.DELIVERY_REPORT + " INTEGER," +
- Mms.LOCKED + " INTEGER DEFAULT 0" +
+ Mms.LOCKED + " INTEGER DEFAULT 0," +
+ Mms.SEEN + " INTEGER DEFAULT 0" +
");");
db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
@@ -419,11 +572,12 @@
// associated Send.req.
db.execSQL("CREATE TRIGGER cleanup_delivery_and_read_report " +
"AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " +
- "WHEN old." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_SEND_REQ + " " +
+ "WHEN old." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ + " " +
"BEGIN " +
" DELETE FROM " + MmsProvider.TABLE_PDU +
- " WHERE (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_DELIVERY_IND +
- " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_READ_ORIG_IND + ")" +
+ " WHERE (" + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_DELIVERY_IND +
+ " OR " + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_ORIG_IND +
+ ")" +
" AND " + Mms.MESSAGE_ID + "=old." + Mms.MESSAGE_ID + "; " +
"END;");
@@ -455,7 +609,9 @@
"subject TEXT," +
"body TEXT," +
"service_center TEXT," +
- "locked INTEGER DEFAULT 0" +
+ "locked INTEGER DEFAULT 0," +
+ "error_code INTEGER DEFAULT 0," +
+ "seen INTEGER DEFAULT 0" +
");");
/**
@@ -621,8 +777,9 @@
// when they are inserted into Inbox/Outbox.
db.execSQL("CREATE TRIGGER insert_mms_pending_on_insert " +
"AFTER INSERT ON pdu " +
- "WHEN new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND +
- " OR new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_READ_REC_IND + " " +
+ "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
+ " OR new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_REC_IND +
+ " " +
"BEGIN " +
" INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG +
" (" + PendingMessages.PROTO_TYPE + "," +
@@ -641,7 +798,7 @@
// Insert pending status for M-Send.req when it is moved into Outbox.
db.execSQL("CREATE TRIGGER insert_mms_pending_on_update " +
"AFTER UPDATE ON pdu " +
- "WHEN new." + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_SEND_REQ +
+ "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ +
" AND new." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX +
" AND old." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " +
"BEGIN " +
@@ -806,7 +963,7 @@
} finally {
db.endTransaction();
}
- // fall through
+ // fall through
case 44:
if (currentVersion <= 44) {
return;
@@ -822,7 +979,7 @@
} finally {
db.endTransaction();
}
- // fall through
+ // fall through
case 45:
if (currentVersion <= 45) {
return;
@@ -853,10 +1010,94 @@
} finally {
db.endTransaction();
}
+ // fall through
+ case 47:
+ if (currentVersion <= 47) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ upgradeDatabaseToVersion48(db);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ break;
+ } finally {
+ db.endTransaction();
+ }
+ // fall through
+ case 48:
+ if (currentVersion <= 48) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ createWordsTables(db);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ break;
+ } finally {
+ db.endTransaction();
+ }
+ // fall through
+ case 49:
+ if (currentVersion <= 49) {
+ return;
+ }
+ db.beginTransaction();
+ try {
+ createThreadIdIndex(db);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+ // fall through
+ case 50:
+ if (currentVersion <= 50) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ upgradeDatabaseToVersion51(db);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ break;
+ } finally {
+ db.endTransaction();
+ }
+ // fall through
+ case 51:
+ if (currentVersion <= 51) {
+ return;
+ }
+ // 52 was adding a new meta_data column, but that was removed.
+ // fall through
+ case 52:
+ if (currentVersion <= 52) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ upgradeDatabaseToVersion53(db);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ break;
+ } finally {
+ db.endTransaction();
+ }
return;
}
-
Log.e(TAG, "Destroying all old data.");
dropAll(db);
onCreate(db);
@@ -921,12 +1162,25 @@
private void upgradeDatabaseToVersion45(SQLiteDatabase db) {
// Add 'locked' column to sms table.
- db.execSQL("ALTER TABLE sms ADD COLUMN locked INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.LOCKED + " INTEGER DEFAULT 0");
// Add 'locked' column to pdu table.
db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.LOCKED + " INTEGER DEFAULT 0");
}
+ private void upgradeDatabaseToVersion53(SQLiteDatabase db) {
+ db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update");
+
+ // Updates threads table whenever a message in pdu is updated.
+ db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" +
+ " UPDATE OF " + Mms.READ +
+ " ON " + MmsProvider.TABLE_PDU + " " +
+ PDU_UPDATE_THREAD_CONSTRAINTS +
+ "BEGIN " +
+ PDU_UPDATE_THREAD_READ_BODY +
+ "END;");
+ }
+
private void upgradeDatabaseToVersion46(SQLiteDatabase db) {
// add the "text" column for caching inline text (e.g. strings) instead of
// putting them in an external file
@@ -992,6 +1246,31 @@
db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER);
}
+ private void upgradeDatabaseToVersion48(SQLiteDatabase db) {
+ // Add 'error_code' column to sms table.
+ db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0");
+ }
+
+ private void upgradeDatabaseToVersion51(SQLiteDatabase db) {
+ db.execSQL("ALTER TABLE sms add COLUMN seen INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE pdu add COLUMN seen INTEGER DEFAULT 0");
+
+ try {
+ // update the existing sms and pdu tables so the new "seen" column is the same as
+ // the "read" column for each row.
+ ContentValues contentValues = new ContentValues();
+ contentValues.put("seen", 1);
+ int count = db.update("sms", contentValues, "read=1", null);
+ Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
+ " rows in sms table to have READ=1");
+ count = db.update("pdu", contentValues, "read=1", null);
+ Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
+ " rows in pdu table to have READ=1");
+ } catch (Exception ex) {
+ Log.e(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51 caught ", ex);
+ }
+ }
+
private void updateThreadsAttachmentColumn(SQLiteDatabase db) {
// Set the values of that column correctly based on the current
// contents of the database.
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
index 8b21e8e..bfe41ab 100644
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
@@ -22,6 +22,7 @@
import java.util.List;
import java.util.Set;
+import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
@@ -90,8 +91,9 @@
private static final int URI_DRAFT = 12;
private static final int URI_CANONICAL_ADDRESSES = 13;
private static final int URI_SEARCH = 14;
- private static final int URI_FIRST_LOCKED_MESSAGE_ALL = 15;
- private static final int URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID = 16;
+ private static final int URI_SEARCH_SUGGEST = 15;
+ private static final int URI_FIRST_LOCKED_MESSAGE_ALL = 16;
+ private static final int URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID = 17;
/**
* the name of the table that is used to store the queue of
@@ -127,7 +129,7 @@
// table.
private static final String[] SMS_ONLY_COLUMNS =
{ "address", "body", "person", "reply_path_present",
- "service_center", "status", "subject", "type" };
+ "service_center", "status", "subject", "type", "error_code" };
// These are all the columns that appear in the "threads" table.
private static final String[] THREADS_COLUMNS = {
@@ -209,6 +211,7 @@
URI_MATCHER.addURI(AUTHORITY, "canonical-addresses", URI_CANONICAL_ADDRESSES);
URI_MATCHER.addURI(AUTHORITY, "search", URI_SEARCH);
+ URI_MATCHER.addURI(AUTHORITY, "searchSuggest", URI_SEARCH_SUGGEST);
// In this pattern, two query parameters may be supplied:
// "protocol" and "message." For example:
@@ -321,7 +324,22 @@
null, null,
sortOrder);
break;
- case URI_SEARCH:
+ case URI_SEARCH_SUGGEST: {
+ String searchString = uri.getQueryParameter("pattern");
+ String query = String.format("SELECT _id, index_text, source_id, table_to_use, offsets(words) FROM words WHERE words MATCH '%s*' LIMIT 50;", searchString);
+ if ( sortOrder != null
+ || selection != null
+ || selectionArgs != null
+ || projection != null) {
+ throw new IllegalArgumentException(
+ "do not specify sortOrder, selection, selectionArgs, or projection" +
+ "with this query");
+ }
+
+ cursor = db.rawQuery(query, null);
+ break;
+ }
+ case URI_SEARCH: {
if ( sortOrder != null
|| selection != null
|| selectionArgs != null
@@ -337,35 +355,45 @@
// using a UNION so we have to have the same number of result columns from
// both queries.
- String searchString = "%" + uri.getQueryParameter("pattern") + "%";
- String smsProjection = "_id,thread_id,address,body,date";
- String mmsProjection = "pdu._id,thread_id,addr.address,part.text as body,pdu.date";
+ String searchString = uri.getQueryParameter("pattern") + "*";
+ String smsProjection = "sms._id as _id,thread_id,address,body,date," +
+ "index_text,words._id";
+ String mmsProjection = "pdu._id,thread_id,addr.address,part.text as " + "" +
+ "body,pdu.date,index_text,words._id";
+
+ // search on the words table but return the rows from the corresponding sms table
String smsQuery = String.format(
- "SELECT %s FROM sms WHERE (address NOTNULL AND body LIKE ?) ",
+ "SELECT %s FROM sms,words WHERE (words MATCH ? " +
+ " AND sms._id=words.source_id AND words.table_to_use=1) ",
smsProjection);
- // TODO consider whether we're really getting the right addr here (for example, if
- // I send a message to a given phone number do I want the search result to
- // show a match on "me" or on that phone number. I suspect the latter.
+ // search on the words table but return the rows from the corresponding parts table
String mmsQuery = String.format(
- "SELECT %s FROM pdu,part,addr WHERE ((part.mid=pdu._id) AND " +
+ "SELECT %s FROM pdu,part,addr,words WHERE ((part.mid=pdu._id) AND " +
"(addr.msg_id=pdu._id) AND " +
"(addr.type=%d) AND " +
"(part.ct='text/plain') AND " +
- "(body like ?))",
+ "(words MATCH ?) AND " +
+ "(part._id = words.source_id) AND " +
+ "(words.table_to_use=2))",
mmsProjection,
PduHeaders.TO);
+ // join the results from sms and part (mms)
String rawQuery = String.format(
"%s UNION %s GROUP BY %s ORDER BY %s",
smsQuery,
mmsQuery,
"thread_id",
"thread_id ASC, date DESC");
-
- cursor = db.rawQuery(rawQuery, new String[] { searchString, searchString });
+ try {
+ cursor = db.rawQuery(rawQuery, new String[] { searchString, searchString });
+ } catch (Exception ex) {
+ Log.e(LOG_TAG, "got exception: " + ex.toString());
+ }
break;
+ }
case URI_PENDING_MSG: {
String protoName = uri.getQueryParameter("protocol");
String msgId = uri.getQueryParameter("message");
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index 069ee6a..57ac256 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -28,6 +28,7 @@
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.Contacts;
+import android.provider.Telephony;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Sms;
@@ -39,7 +40,7 @@
import android.util.Config;
import android.util.Log;
-import com.android.internal.database.ArrayListCursor;
+import com.android.common.ArrayListCursor;
import java.util.ArrayList;
import java.util.HashMap;
@@ -50,6 +51,7 @@
static final String TABLE_SMS = "sms";
private static final String TABLE_RAW = "raw";
private static final String TABLE_SR_PENDING = "sr_pending";
+ private static final String TABLE_WORDS = "words";
private static final Integer ONE = Integer.valueOf(1);
@@ -75,7 +77,8 @@
"is_status_report", // isStatusReportMessage
"transport_type", // Always "sms".
"type", // Always MESSAGE_TYPE_ALL.
- "locked" // Always 0 (false).
+ "locked", // Always 0 (false).
+ "error_code" // Always 0
};
@Override
@@ -243,6 +246,7 @@
result.add("sms");
result.add(TextBasedSmsColumns.MESSAGE_TYPE_ALL);
result.add(0); // locked
+ result.add(0); // error_code
return result;
}
@@ -484,6 +488,21 @@
}
rowID = db.insert(table, "body", values);
+
+ // Don't use a trigger for updating the words table because of a bug
+ // in FTS3. The bug is such that the call to get the last inserted
+ // row is incorrect.
+ if (table == TABLE_SMS) {
+ // Update the words table with a corresponding row. The words table
+ // allows us to search for words quickly, without scanning the whole
+ // table;
+ ContentValues cv = new ContentValues();
+ cv.put(Telephony.MmsSms.WordsTable.ID, rowID);
+ cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, values.getAsString("body"));
+ cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, rowID);
+ cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
+ db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
+ }
if (rowID > 0) {
Uri uri = Uri.parse("content://" + table + "/" + rowID);